diff options
263 files changed, 3951 insertions, 2088 deletions
diff --git a/api/current.txt b/api/current.txt index 37b8327..eacc452 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4374,6 +4374,7 @@ package android.app { method public abstract android.app.FragmentTransaction add(android.app.Fragment, java.lang.String); method public abstract android.app.FragmentTransaction add(int, android.app.Fragment); method public abstract android.app.FragmentTransaction add(int, android.app.Fragment, java.lang.String); + method public abstract android.app.FragmentTransaction addSharedElement(android.view.View, java.lang.String); method public abstract android.app.FragmentTransaction addToBackStack(java.lang.String); method public abstract android.app.FragmentTransaction attach(android.app.Fragment); method public abstract int commit(); @@ -4393,8 +4394,6 @@ package android.app { method public abstract android.app.FragmentTransaction setCustomAnimations(int, int); method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int); method public abstract android.app.FragmentTransaction setCustomTransition(int, int); - method public abstract android.app.FragmentTransaction setSharedElement(android.view.View, java.lang.String); - method public abstract android.app.FragmentTransaction setSharedElements(android.util.Pair<android.view.View, java.lang.String>...); method public abstract android.app.FragmentTransaction setTransition(int); method public abstract android.app.FragmentTransaction setTransitionStyle(int); method public abstract android.app.FragmentTransaction show(android.app.Fragment); @@ -5643,19 +5642,21 @@ package android.app.job { method public long getIntervalMillis(); method public long getMaxExecutionDelayMillis(); method public long getMinLatencyMillis(); - method public int getNetworkCapabilities(); + method public int getNetworkType(); method public android.content.ComponentName getService(); method public boolean isPeriodic(); method public boolean isPersisted(); method public boolean isRequireCharging(); method public boolean isRequireDeviceIdle(); method public void writeToParcel(android.os.Parcel, int); + field public static final int BACKOFF_POLICY_EXPONENTIAL = 1; // 0x1 + field public static final int BACKOFF_POLICY_LINEAR = 0; // 0x0 field public static final android.os.Parcelable.Creator CREATOR; - } - - public static abstract interface JobInfo.BackoffPolicy { - field public static final int EXPONENTIAL = 1; // 0x1 - field public static final int LINEAR = 0; // 0x0 + field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L + field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L + field public static final int NETWORK_TYPE_ANY = 1; // 0x1 + field public static final int NETWORK_TYPE_NONE = 0; // 0x0 + field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2 } public static final class JobInfo.Builder { @@ -5663,21 +5664,15 @@ package android.app.job { method public android.app.job.JobInfo build(); method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int); method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle); - method public android.app.job.JobInfo.Builder setIsPersisted(boolean); method public android.app.job.JobInfo.Builder setMinimumLatency(long); method public android.app.job.JobInfo.Builder setOverrideDeadline(long); method public android.app.job.JobInfo.Builder setPeriodic(long); - method public android.app.job.JobInfo.Builder setRequiredNetworkCapabilities(int); + method public android.app.job.JobInfo.Builder setPersisted(boolean); + method public android.app.job.JobInfo.Builder setRequiredNetworkType(int); method public android.app.job.JobInfo.Builder setRequiresCharging(boolean); method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean); } - public static abstract interface JobInfo.NetworkType { - field public static final int ANY = 1; // 0x1 - field public static final int NONE = 0; // 0x0 - field public static final int UNMETERED = 2; // 0x2 - } - public class JobParameters implements android.os.Parcelable { method public int describeContents(); method public android.os.PersistableBundle getExtras(); @@ -6627,6 +6622,7 @@ package android.bluetooth.le { method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; } public static final class AdvertiseData.Builder { @@ -6641,10 +6637,10 @@ package android.bluetooth.le { public final class AdvertiseSettings implements android.os.Parcelable { method public int describeContents(); - method public boolean getIsConnectable(); method public int getMode(); method public int getTimeout(); method public int getTxPowerLevel(); + method public boolean isConnectable(); method public void writeToParcel(android.os.Parcel, int); field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1 field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2 @@ -6653,13 +6649,14 @@ package android.bluetooth.le { field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1 field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2 field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0 + field public static final android.os.Parcelable.Creator CREATOR; } public static final class AdvertiseSettings.Builder { ctor public AdvertiseSettings.Builder(); method public android.bluetooth.le.AdvertiseSettings build(); method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int); - method public android.bluetooth.le.AdvertiseSettings.Builder setIsConnectable(boolean); + method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean); method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int); method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int); } @@ -6702,6 +6699,7 @@ package android.bluetooth.le { method public android.os.ParcelUuid getServiceUuidMask(); method public boolean matches(android.bluetooth.le.ScanResult); method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; } public static final class ScanFilter.Builder { @@ -6737,6 +6735,7 @@ package android.bluetooth.le { method public android.bluetooth.le.ScanRecord getScanRecord(); method public long getTimestampNanos(); method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; } public final class ScanSettings implements android.os.Parcelable { @@ -6747,19 +6746,16 @@ package android.bluetooth.le { method public int getScanResultType(); method public void writeToParcel(android.os.Parcel, int); field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1 - field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2 - field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4 + field public static final android.os.Parcelable.Creator CREATOR; field public static final int SCAN_MODE_BALANCED = 1; // 0x1 field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 - field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0 } public static final class ScanSettings.Builder { ctor public ScanSettings.Builder(); method public android.bluetooth.le.ScanSettings build(); - method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int); - method public android.bluetooth.le.ScanSettings.Builder setReportDelayMillis(long); + method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long); method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); } @@ -8680,10 +8676,12 @@ package android.content.pm { method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback); method public void uninstall(java.lang.String, android.content.IntentSender); field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; + field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME"; field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID"; field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS"; field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE"; + field public static final java.lang.String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH"; field public static final int STATUS_FAILURE = 1; // 0x1 field public static final int STATUS_FAILURE_ABORTED = 3; // 0x3 field public static final int STATUS_FAILURE_BLOCKED = 2; // 0x2 @@ -13574,7 +13572,7 @@ package android.inputmethodservice { method public void onStartInput(android.view.inputmethod.EditorInfo, boolean); method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean); method public void onUnbindInput(); - method public void onUpdateCursor(android.graphics.Rect); + method public deprecated void onUpdateCursor(android.graphics.Rect); method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo); method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText); method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo); @@ -22465,21 +22463,21 @@ package android.os { } public final class PowerManager { - method public void goToSleep(long); method public boolean isInteractive(); method public boolean isPowerSaveMode(); method public deprecated boolean isScreenOn(); + method public boolean isWakeLockLevelSupported(int); method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String); method public void reboot(java.lang.String); - method public void userActivity(long, boolean); - method public void wakeUp(long); field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000 field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED"; field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000 field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1 + field public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; // 0x20 field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6 + field public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1; // 0x1 } public final class PowerManager.WakeLock { @@ -22487,6 +22485,7 @@ package android.os { method public void acquire(long); method public boolean isHeld(); method public void release(); + method public void release(int); method public void setReferenceCounted(boolean); method public void setWorkSource(android.os.WorkSource); } @@ -27463,7 +27462,7 @@ package android.service.voice { public class VoiceInteractionService extends android.app.Service { ctor public VoiceInteractionService(); - method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback); + method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback); method public static boolean isActiveService(android.content.Context, android.content.ComponentName); method public android.os.IBinder onBind(android.content.Intent); method public void onReady(); @@ -28556,8 +28555,6 @@ package android.telecomm { method public final int getHandlePresentation(); method public final int getState(); method public final android.telecomm.StatusHints getStatusHints(); - method public final android.telecomm.Connection.VideoProvider getVideoProvider(); - method public final int getVideoState(); method public final boolean isRequestingRingback(); method public void onAbort(); method public void onAnswer(int); @@ -28589,8 +28586,6 @@ package android.telecomm { method public final void setRequestingRingback(boolean); method public final void setRinging(); method public final void setStatusHints(android.telecomm.StatusHints); - method public final void setVideoProvider(android.telecomm.Connection.VideoProvider); - method public final void setVideoState(int); method public final void startActivityFromInCall(android.app.PendingIntent); method public static java.lang.String stateToString(int); field public static final int STATE_ACTIVE = 4; // 0x4 @@ -28602,35 +28597,6 @@ package android.telecomm { field public static final int STATE_RINGING = 2; // 0x2 } - public static abstract class Connection.VideoProvider { - ctor public Connection.VideoProvider(); - method public void changeCallDataUsage(int); - method public void changeCameraCapabilities(android.telecomm.CameraCapabilities); - method public void changePeerDimensions(int, int); - method public void handleCallSessionEvent(int); - method public abstract void onRequestCallDataUsage(); - method public abstract void onRequestCameraCapabilities(); - method public abstract void onSendSessionModifyRequest(android.telecomm.VideoProfile); - method public abstract void onSendSessionModifyResponse(android.telecomm.VideoProfile); - method public abstract void onSetCamera(java.lang.String); - method public abstract void onSetDeviceOrientation(int); - method public abstract void onSetDisplaySurface(android.view.Surface); - method public abstract void onSetPauseImage(java.lang.String); - method public abstract void onSetPreviewSurface(android.view.Surface); - method public abstract void onSetZoom(float); - method public void receiveSessionModifyRequest(android.telecomm.VideoProfile); - method public void receiveSessionModifyResponse(int, android.telecomm.VideoProfile, android.telecomm.VideoProfile); - field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5 - field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6 - field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1 - field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2 - field public static final int SESSION_EVENT_TX_START = 3; // 0x3 - field public static final int SESSION_EVENT_TX_STOP = 4; // 0x4 - field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2 - field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3 - field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1 - } - public final class ConnectionRequest implements android.os.Parcelable { ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, int, android.os.Bundle, int); method public int describeContents(); @@ -28638,7 +28604,6 @@ package android.telecomm { method public android.os.Bundle getExtras(); method public android.net.Uri getHandle(); method public int getHandlePresentation(); - method public int getVideoState(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; } @@ -28750,7 +28715,6 @@ package android.telecomm { method public android.telecomm.RemoteConnection getParent(); method public int getState(); method public android.telecomm.StatusHints getStatusHints(); - method public int getVideoState(); method public void hold(); method public boolean isRequestingRingback(); method public void playDtmfTone(char); @@ -28778,7 +28742,6 @@ package android.telecomm { method public void onStartActivityFromInCall(android.telecomm.RemoteConnection, android.app.PendingIntent); method public void onStateChanged(android.telecomm.RemoteConnection, int); method public void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints); - method public void onVideoStateChanged(android.telecomm.RemoteConnection, int); } public abstract interface Response { @@ -28817,35 +28780,6 @@ package android.telecomm { field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE"; field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.intent.extra.PHONE_ACCOUNT_HANDLE"; field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE"; - field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.intent.extra.START_CALL_WITH_VIDEO_STATE"; - } - - public class VideoProfile implements android.os.Parcelable { - ctor public VideoProfile(int); - ctor public VideoProfile(int, int); - method public int describeContents(); - method public int getQuality(); - method public int getVideoState(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - field public static final int QUALITY_DEFAULT = 4; // 0x4 - field public static final int QUALITY_HIGH = 1; // 0x1 - field public static final int QUALITY_LOW = 3; // 0x3 - field public static final int QUALITY_MEDIUM = 2; // 0x2 - } - - public static class VideoProfile.VideoState { - ctor public VideoProfile.VideoState(); - method public static boolean isAudioOnly(int); - method public static boolean isBidirectional(int); - method public static boolean isPaused(int); - method public static boolean isReceptionEnabled(int); - method public static boolean isTransmissionEnabled(int); - field public static final int AUDIO_ONLY = 0; // 0x0 - field public static final int BIDIRECTIONAL = 3; // 0x3 - field public static final int PAUSED = 4; // 0x4 - field public static final int RX_ENABLED = 2; // 0x2 - field public static final int TX_ENABLED = 1; // 0x1 } } @@ -33387,6 +33321,7 @@ package android.view { field public static final int KEYCODE_U = 49; // 0x31 field public static final int KEYCODE_UNKNOWN = 0; // 0x0 field public static final int KEYCODE_V = 50; // 0x32 + field public static final int KEYCODE_VOICE_ASSIST = 231; // 0xe7 field public static final int KEYCODE_VOLUME_DOWN = 25; // 0x19 field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4 field public static final int KEYCODE_VOLUME_UP = 24; // 0x18 @@ -36187,7 +36122,7 @@ package android.view.inputmethod { method public boolean performPrivateCommand(java.lang.String, android.os.Bundle); method public static final void removeComposingSpans(android.text.Spannable); method public boolean reportFullscreenMode(boolean); - method public int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest); + method public boolean requestUpdateCursorAnchorInfo(int); method public boolean sendKeyEvent(android.view.KeyEvent); method public boolean setComposingRegion(int, int); method public static void setComposingSpans(android.text.Spannable); @@ -36253,25 +36188,6 @@ package android.view.inputmethod { method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int); } - public final class CursorAnchorInfoRequest implements android.os.Parcelable { - ctor public CursorAnchorInfoRequest(int, int); - ctor public CursorAnchorInfoRequest(android.os.Parcel); - method public int describeContents(); - method public int getRequestFlags(); - method public int getRequestType(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - field public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 2; // 0x2 - field public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 1; // 0x1 - field public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 2; // 0x2 - field public static final int FLAG_CURSOR_RECT_MONITOR = 1; // 0x1 - field public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 4; // 0x4 - field public static final int RESULT_NOT_HANDLED = 0; // 0x0 - field public static final int RESULT_SCHEDULED = 1; // 0x1 - field public static final int TYPE_CURSOR_ANCHOR_INFO = 1; // 0x1 - field public static final int TYPE_CURSOR_RECT = 2; // 0x2 - } - public class EditorInfo implements android.text.InputType android.os.Parcelable { ctor public EditorInfo(); method public int describeContents(); @@ -36369,13 +36285,15 @@ package android.view.inputmethod { method public abstract boolean performEditorAction(int); method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle); method public abstract boolean reportFullscreenMode(boolean); - method public abstract int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest); + method public abstract boolean requestUpdateCursorAnchorInfo(int); method public abstract boolean sendKeyEvent(android.view.KeyEvent); method public abstract boolean setComposingRegion(int, int); method public abstract boolean setComposingText(java.lang.CharSequence, int); method public abstract boolean setSelection(int, int); field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1 + field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1; // 0x1 + field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 2; // 0x2 } public class InputConnectionWrapper implements android.view.inputmethod.InputConnection { @@ -36397,7 +36315,7 @@ package android.view.inputmethod { method public boolean performEditorAction(int); method public boolean performPrivateCommand(java.lang.String, android.os.Bundle); method public boolean reportFullscreenMode(boolean); - method public int requestCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfoRequest); + method public boolean requestUpdateCursorAnchorInfo(int); method public boolean sendKeyEvent(android.view.KeyEvent); method public boolean setComposingRegion(int, int); method public boolean setComposingText(java.lang.CharSequence, int); @@ -36463,7 +36381,7 @@ package android.view.inputmethod { method public boolean isActive(android.view.View); method public boolean isActive(); method public boolean isFullscreenMode(); - method public boolean isWatchingCursor(android.view.View); + method public deprecated boolean isWatchingCursor(android.view.View); method public void restartInput(android.view.View); method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle); method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]); @@ -36481,7 +36399,7 @@ package android.view.inputmethod { method public boolean switchToNextInputMethod(android.os.IBinder, boolean); method public void toggleSoftInput(int, int); method public void toggleSoftInputFromWindow(android.os.IBinder, int, int); - method public void updateCursor(android.view.View, int, int, int, int); + method public deprecated void updateCursor(android.view.View, int, int, int, int); method public void updateCursorAnchorInfo(android.view.View, android.view.inputmethod.CursorAnchorInfo); method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText); method public void updateSelection(android.view.View, int, int, int, int); @@ -39770,6 +39688,7 @@ package android.widget { method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener); method public void setVideoPath(java.lang.String); method public void setVideoURI(android.net.Uri); + method public void setVideoURI(android.net.Uri, java.util.Map<java.lang.String, java.lang.String>); method public void start(); method public void stopPlayback(); method public void suspend(); diff --git a/api/removed.txt b/api/removed.txt index 465a18d..93484de 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -6,6 +6,16 @@ package android.media { } +package android.os { + + public final class PowerManager { + method public void goToSleep(long); + method public deprecated void userActivity(long, boolean); + method public void wakeUp(long); + } + +} + package android.view { public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable { diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 46d8ade..d9b40b1 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -1004,6 +1004,10 @@ public final class Pm { params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; } else if (opt.equals("-p")) { params.mode = SessionParams.MODE_INHERIT_EXISTING; + params.appPackageName = nextOptionData(); + if (params.appPackageName == null) { + throw new IllegalArgumentException("Missing inherit package name"); + } } else if (opt.equals("-S")) { params.setSize(Long.parseLong(nextOptionData())); } else if (opt.equals("--abi")) { diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ffcdcf7..2e66a4c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -54,7 +54,6 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.session.MediaController; -import android.media.session.MediaSession; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -5641,8 +5640,8 @@ public class Activity extends ContextThemeWrapper if (info.taskAffinity == null) { return false; } - return !ActivityManagerNative.getDefault() - .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity); + return ActivityManagerNative.getDefault() + .shouldUpRecreateTask(mToken, info.taskAffinity); } catch (RemoteException e) { return false; } catch (NameNotFoundException e) { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 3dafa4b..5b81cc3 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1997,11 +1997,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION: { + case SHOULD_UP_RECREATE_TASK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); String destAffinity = data.readString(); - boolean res = targetTaskAffinityMatchesActivity(token, destAffinity); + boolean res = shouldUpRecreateTask(token, destAffinity); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -4858,14 +4858,14 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeString(destAffinity); - mRemote.transact(TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION, data, reply, 0); + mRemote.transact(SHOULD_UP_RECREATE_TASK_TRANSACTION, data, reply, 0); reply.readException(); boolean result = reply.readInt() != 0; data.recycle(); diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 4433a3a..67863a5 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -580,6 +580,23 @@ final class BackStackRecord extends FragmentTransaction implements } @Override + public FragmentTransaction addSharedElement(View sharedElement, String name) { + String transitionName = sharedElement.getTransitionName(); + if (transitionName == null) { + throw new IllegalArgumentException("Unique transitionNames are required for all" + + " sharedElements"); + } + if (mSharedElementSourceNames == null) { + mSharedElementSourceNames = new ArrayList<String>(); + mSharedElementTargetNames = new ArrayList<String>(); + } + mSharedElementSourceNames.add(transitionName); + mSharedElementTargetNames.add(name); + return this; + } + + /** TODO: remove this */ + @Override public FragmentTransaction setSharedElement(View sharedElement, String name) { String transitionName = sharedElement.getTransitionName(); if (transitionName == null) { @@ -594,6 +611,7 @@ final class BackStackRecord extends FragmentTransaction implements return this; } + /** TODO: remove this */ @Override public FragmentTransaction setSharedElements(Pair<View, String>... sharedElements) { if (sharedElements == null || sharedElements.length == 0) { diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index 0adc835..1077bac 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -190,14 +190,17 @@ public abstract class FragmentTransaction { * @param name The transitionName for a View in an appearing Fragment to match to the shared * element. */ + public abstract FragmentTransaction addSharedElement(View sharedElement, String name); + + /** + * TODO: remove from API + * @hide + */ public abstract FragmentTransaction setSharedElement(View sharedElement, String name); /** - * Used with {@link #setCustomTransition(int, int)} to map multiple Views from removed or hidden - * Fragments to a Views from a shown or added Fragments. Views in - * <var>sharedElements</var> must have unique transitionNames in the View hierarchy. - * @param sharedElements Pairs of Views in disappearing Fragments to transitionNames in - * appearing Fragments. + * TODO: remove from API + * @hide */ public abstract FragmentTransaction setSharedElements(Pair<View, String>... sharedElements); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 70514d8..1664408 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -393,7 +393,7 @@ public interface IActivityManager extends IInterface { public void keyguardWaitingForActivityDrawn() throws RemoteException; - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException; public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData) @@ -702,7 +702,7 @@ public interface IActivityManager extends IInterface { int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142; int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143; int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144; - int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; + int SHOULD_UP_RECREATE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146; int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147; int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148; diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index e8f6818..2b97c6b 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -62,6 +62,8 @@ interface INotificationManager void requestHintsFromListener(in INotificationListener token, int hints); int getHintsFromListener(in INotificationListener token); + ComponentName getEffectsSuppressor(); + ZenModeConfig getZenModeConfig(); boolean setZenModeConfig(in ZenModeConfig config); oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 47967ba..f7300aa 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2579,20 +2579,35 @@ public class Notification implements Parcelable return bitmap; } + private boolean addProfileBadge(RemoteViews contentView, int resId) { + Bitmap profileBadge = getProfileBadge(); + + contentView.setViewVisibility(R.id.profile_badge_large_template, View.GONE); + contentView.setViewVisibility(R.id.profile_badge_line2, View.GONE); + contentView.setViewVisibility(R.id.profile_badge_line3, View.GONE); + + if (profileBadge != null) { + contentView.setImageViewBitmap(resId, profileBadge); + contentView.setViewVisibility(resId, View.VISIBLE); + + // Make sure Line 3 is visible. As badge will be here if there + // is no text to display. + if (resId == R.id.profile_badge_line3) { + contentView.setViewVisibility(R.id.line3, View.VISIBLE); + } + return true; + } + return false; + } + private RemoteViews applyStandardTemplate(int resId) { - Bitmap profileIcon = getProfileBadge(); RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(), mOriginatingUserId, resId); boolean showLine3 = false; boolean showLine2 = false; + boolean contentTextInLine2 = false; - if (profileIcon != null) { - contentView.setImageViewBitmap(R.id.profile_icon, profileIcon); - contentView.setViewVisibility(R.id.profile_icon, View.VISIBLE); - } else { - contentView.setViewVisibility(R.id.profile_icon, View.GONE); - } if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); processLargeIcon(mLargeIcon, contentView); @@ -2639,6 +2654,7 @@ public class Notification implements Parcelable contentView.setTextViewText(R.id.text2, processLegacyText(mContentText)); contentView.setViewVisibility(R.id.text2, View.VISIBLE); showLine2 = true; + contentTextInLine2 = true; } else { contentView.setViewVisibility(R.id.text2, View.GONE); } @@ -2681,6 +2697,15 @@ public class Notification implements Parcelable hasThreeLines(), mContext.getResources().getConfiguration().fontScale), 0, 0); + // We want to add badge to first line of text. + boolean addedBadge = addProfileBadge(contentView, + contentTextInLine2 ? R.id.profile_badge_line2 : R.id.profile_badge_line3); + // If we added the badge to line 3 then we should show line 3. + if (addedBadge && !contentTextInLine2) { + showLine3 = true; + } + + // Note getStandardView may hide line 3 again. contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE); contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE); return contentView; @@ -3347,6 +3372,8 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE); contentView.setViewVisibility(R.id.line3, View.VISIBLE); } else { + // Clear text in case we use the line to show the profile badge. + contentView.setTextViewText(R.id.text, ""); contentView.setViewVisibility(R.id.overflow_divider, View.GONE); contentView.setViewVisibility(R.id.line3, View.GONE); } @@ -3507,6 +3534,9 @@ public class Notification implements Parcelable applyTopPadding(contentView); + boolean twoTextLines = mBuilder.mSubText != null && mBuilder.mContentText != null; + mBuilder.addProfileBadge(contentView, + twoTextLines ? R.id.profile_badge_line2 : R.id.profile_badge_line3); return contentView; } @@ -3632,6 +3662,8 @@ public class Notification implements Parcelable applyTopPadding(contentView); + mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template); + return contentView; } @@ -3769,6 +3801,8 @@ public class Notification implements Parcelable applyTopPadding(contentView); + mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template); + return contentView; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index bd9363d..fc047de 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -16,7 +16,9 @@ package android.app; +import android.annotation.SdkConstant; import android.app.Notification.Builder; +import android.content.ComponentName; import android.content.Context; import android.os.Handler; import android.os.IBinder; @@ -72,6 +74,16 @@ public class NotificationManager private static String TAG = "NotificationManager"; private static boolean localLOGV = false; + /** + * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes. + * This broadcast is only sent to registered receivers. + * + * @hide + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED + = "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED"; + private static INotificationManager sService; /** @hide */ @@ -227,5 +239,17 @@ public class NotificationManager } } + /** + * @hide + */ + public ComponentName getEffectsSuppressor() { + INotificationManager service = getService(); + try { + return service.getEffectsSuppressor(); + } catch (RemoteException e) { + return null; + } + } + private Context mContext; } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 0dc8f66..41bbb87 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1373,6 +1373,8 @@ public class DevicePolicyManager { * and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. + * @return time in milliseconds for the given admin or the minimum value (strictest) of + * all admins if admin is null. */ public long getMaximumTimeToLock(ComponentName admin) { return getMaximumTimeToLock(admin, UserHandle.myUserId()); diff --git a/core/java/android/app/job/IJobService.aidl b/core/java/android/app/job/IJobService.aidl index 63f8b81..7f55d29 100644 --- a/core/java/android/app/job/IJobService.aidl +++ b/core/java/android/app/job/IJobService.aidl @@ -27,6 +27,6 @@ import android.app.job.JobParameters; oneway interface IJobService { /** Begin execution of application's job. */ void startJob(in JobParameters jobParams); - /** Stop execution of application's task. */ + /** Stop execution of application's job. */ void stopJob(in JobParameters jobParams); } diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index b7af544..0d9e778 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -17,7 +17,6 @@ package android.app.job; import android.content.ComponentName; -import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; @@ -26,42 +25,50 @@ import android.os.PersistableBundle; * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the * parameters required to schedule work against the calling application. These are constructed * using the {@link JobInfo.Builder}. + * You must specify at least one sort of constraint on the JobInfo object that you are creating. + * The goal here is to provide the scheduler with high-level semantics about the work you want to + * accomplish. Doing otherwise with throw an exception in your app. */ public class JobInfo implements Parcelable { - public interface NetworkType { - /** Default. */ - public final int NONE = 0; - /** This job requires network connectivity. */ - public final int ANY = 1; - /** This job requires network connectivity that is unmetered. */ - public final int UNMETERED = 2; - } + /** Default. */ + public static final int NETWORK_TYPE_NONE = 0; + /** This job requires network connectivity. */ + public static final int NETWORK_TYPE_ANY = 1; + /** This job requires network connectivity that is unmetered. */ + public static final int NETWORK_TYPE_UNMETERED = 2; /** * Amount of backoff a job has initially by default, in milliseconds. - * @hide. */ - public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 5000L; + public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 30 seconds. /** - * Default type of backoff. - * @hide + * Maximum backoff we allow for a job, in milliseconds. */ - public static final int DEFAULT_BACKOFF_POLICY = BackoffPolicy.EXPONENTIAL; + public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000; // 5 hours. + /** - * Maximum backoff we allow for a job, in milliseconds. - * @hide + * Linearly back-off a failed job. See + * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} + * retry_time(current_time, num_failures) = + * current_time + initial_backoff_millis * num_failures, num_failures >= 1 */ - public static final long MAX_BACKOFF_DELAY_MILLIS = 24 * 60 * 60 * 1000; // 24 hours. + public static final int BACKOFF_POLICY_LINEAR = 0; /** - * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1 - * Expon: retry_time(failure_time, t) = failure_time + initial_retry_delay ^ t, t >= 1 + * Exponentially back-off a failed job. See + * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} + * + * retry_time(current_time, num_failures) = + * current_time + initial_backoff_millis * 2 ^ (num_failures - 1), num_failures >= 1 */ - public interface BackoffPolicy { - public final int LINEAR = 0; - public final int EXPONENTIAL = 1; - } + public static final int BACKOFF_POLICY_EXPONENTIAL = 1; + + /** + * Default type of backoff. + * @hide + */ + public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL; private final int jobId; private final PersistableBundle extras; @@ -70,7 +77,7 @@ public class JobInfo implements Parcelable { private final boolean requireDeviceIdle; private final boolean hasEarlyConstraint; private final boolean hasLateConstraint; - private final int networkCapabilities; + private final int networkType; private final long minLatencyMillis; private final long maxExecutionDelayMillis; private final boolean isPeriodic; @@ -115,10 +122,12 @@ public class JobInfo implements Parcelable { } /** - * See {@link android.app.job.JobInfo.NetworkType} for a description of this value. + * One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY}, + * {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, or + * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}. */ - public int getNetworkCapabilities() { - return networkCapabilities; + public int getNetworkType() { + return networkType; } /** @@ -169,8 +178,9 @@ public class JobInfo implements Parcelable { } /** - * See {@link android.app.job.JobInfo.BackoffPolicy} for an explanation of the values this field - * can take. This defaults to exponential. + * One of either {@link android.app.job.JobInfo#BACKOFF_POLICY_EXPONENTIAL}, or + * {@link android.app.job.JobInfo#BACKOFF_POLICY_LINEAR}, depending on which criteria you set + * when creating this job. */ public int getBackoffPolicy() { return backoffPolicy; @@ -200,7 +210,7 @@ public class JobInfo implements Parcelable { service = in.readParcelable(null); requireCharging = in.readInt() == 1; requireDeviceIdle = in.readInt() == 1; - networkCapabilities = in.readInt(); + networkType = in.readInt(); minLatencyMillis = in.readLong(); maxExecutionDelayMillis = in.readLong(); isPeriodic = in.readInt() == 1; @@ -218,7 +228,7 @@ public class JobInfo implements Parcelable { service = b.mJobService; requireCharging = b.mRequiresCharging; requireDeviceIdle = b.mRequiresDeviceIdle; - networkCapabilities = b.mNetworkCapabilities; + networkType = b.mNetworkType; minLatencyMillis = b.mMinLatencyMillis; maxExecutionDelayMillis = b.mMaxExecutionDelayMillis; isPeriodic = b.mIsPeriodic; @@ -242,7 +252,7 @@ public class JobInfo implements Parcelable { out.writeParcelable(service, flags); out.writeInt(requireCharging ? 1 : 0); out.writeInt(requireDeviceIdle ? 1 : 0); - out.writeInt(networkCapabilities); + out.writeInt(networkType); out.writeLong(minLatencyMillis); out.writeLong(maxExecutionDelayMillis); out.writeInt(isPeriodic ? 1 : 0); @@ -279,7 +289,7 @@ public class JobInfo implements Parcelable { // Requirements. private boolean mRequiresCharging; private boolean mRequiresDeviceIdle; - private int mNetworkCapabilities; + private int mNetworkType; private boolean mIsPersisted; // One-off parameters. private long mMinLatencyMillis; @@ -317,15 +327,15 @@ public class JobInfo implements Parcelable { } /** - * Set some description of the kind of network capabilities you would like to have. This - * will be a parameter defined in {@link android.app.job.JobInfo.NetworkType}. - * Not calling this function means the network is not necessary. + * Set some description of the kind of network type your job needs to have. + * Not calling this function means the network is not necessary, as the default is + * {@link #NETWORK_TYPE_NONE}. * Bear in mind that calling this function defines network as a strict requirement for your - * job if the network requested is not available your job will never run. See + * job. If the network requested is not available your job will never run. See * {@link #setOverrideDeadline(long)} to change this behaviour. */ - public Builder setRequiredNetworkCapabilities(int networkCapabilities) { - mNetworkCapabilities = networkCapabilities; + public Builder setRequiredNetworkType(int networkType) { + mNetworkType = networkType; return this; } @@ -398,8 +408,8 @@ public class JobInfo implements Parcelable { /** * Set up the back-off/retry policy. - * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at - * 1hr. + * This defaults to some respectable values: {30 seconds, Exponential}. We cap back-off at + * 5hrs. * Note that trying to set a backoff criteria for a job with * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build(). * This is because back-off typically does not make sense for these types of jobs. See @@ -408,7 +418,8 @@ public class JobInfo implements Parcelable { * mode. * @param initialBackoffMillis Millisecond time interval to wait initially when job has * failed. - * @param backoffPolicy is one of {@link BackoffPolicy} + * @param backoffPolicy is one of {@link #BACKOFF_POLICY_LINEAR} or + * {@link #BACKOFF_POLICY_EXPONENTIAL} */ public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) { mBackoffPolicySet = true; @@ -425,7 +436,7 @@ public class JobInfo implements Parcelable { * @param isPersisted True to indicate that the job will be written to disk and loaded at * boot. */ - public Builder setIsPersisted(boolean isPersisted) { + public Builder setPersisted(boolean isPersisted) { mIsPersisted = isPersisted; return this; } @@ -434,9 +445,9 @@ public class JobInfo implements Parcelable { * @return The job object to hand to the JobScheduler. This object is immutable. */ public JobInfo build() { - // Allow tasks with no constraints. What am I, a database? + // Allow jobs with no constraints - What am I, a database? if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging && - !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) { + !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_NONE) { throw new IllegalArgumentException("You're trying to build a job with no " + "constraints, this is not allowed."); } diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java index eea0268..940a530 100644 --- a/core/java/android/app/job/JobService.java +++ b/core/java/android/app/job/JobService.java @@ -17,9 +17,6 @@ package android.app.job; import android.app.Service; -import android.app.job.IJobCallback; -import android.app.job.IJobService; -import android.app.job.IJobService.Stub; import android.content.Intent; import android.os.Handler; import android.os.IBinder; @@ -218,7 +215,7 @@ public abstract class JobService extends Service { * * <p>This will happen if the requirements specified at schedule time are no longer met. For * example you may have requested WiFi with - * {@link android.app.job.JobInfo.Builder#setRequiredNetworkCapabilities(int)}, yet while your + * {@link android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}, yet while your * job was executing the user toggled WiFi. Another example is if you had specified * {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its * idle maintenance window. You are solely responsible for the behaviour of your application @@ -248,8 +245,8 @@ public abstract class JobService extends Service { * * @param params Parameters specifying system-provided info about this job, this was given to * your application in {@link #onStartJob(JobParameters)}. - * @param needsReschedule True if this job is complete, false if you want the JobManager to - * reschedule you. + * @param needsReschedule True if this job should be rescheduled according to the back-off + * criteria specified at schedule-time. False otherwise. */ public final void jobFinished(JobParameters params, boolean needsReschedule) { ensureHandler(); diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index 843cd84..c7bfae9 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -172,9 +172,6 @@ public final class AdvertiseData implements Parcelable { dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); } - /** - * @hide - */ public static final Parcelable.Creator<AdvertiseData> CREATOR = new Creator<AdvertiseData>() { @Override diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java index 71d7b5b..62c68a4 100644 --- a/core/java/android/bluetooth/le/AdvertiseSettings.java +++ b/core/java/android/bluetooth/le/AdvertiseSettings.java @@ -66,13 +66,13 @@ public final class AdvertiseSettings implements Parcelable { public static final int ADVERTISE_TX_POWER_HIGH = 3; /** - * The maximimum limited advertisement duration as specified by the Bluetooth SIG + * The maximum limited advertisement duration as specified by the Bluetooth SIG */ - private static final int LIMITED_ADVERTISING_MAX_DURATION = 180; + private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000; private final int mAdvertiseMode; private final int mAdvertiseTxPowerLevel; - private final int mAdvertiseTimeoutSeconds; + private final int mAdvertiseTimeoutMillis; private final boolean mAdvertiseConnectable; private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel, @@ -80,14 +80,14 @@ public final class AdvertiseSettings implements Parcelable { mAdvertiseMode = advertiseMode; mAdvertiseTxPowerLevel = advertiseTxPowerLevel; mAdvertiseConnectable = advertiseConnectable; - mAdvertiseTimeoutSeconds = advertiseTimeout; + mAdvertiseTimeoutMillis = advertiseTimeout; } private AdvertiseSettings(Parcel in) { mAdvertiseMode = in.readInt(); mAdvertiseTxPowerLevel = in.readInt(); mAdvertiseConnectable = in.readInt() != 0 ? true : false; - mAdvertiseTimeoutSeconds = in.readInt(); + mAdvertiseTimeoutMillis = in.readInt(); } /** @@ -107,15 +107,15 @@ public final class AdvertiseSettings implements Parcelable { /** * Returns whether the advertisement will indicate connectable. */ - public boolean getIsConnectable() { + public boolean isConnectable() { return mAdvertiseConnectable; } /** - * Returns the advertising time limit in seconds. + * Returns the advertising time limit in milliseconds. */ public int getTimeout() { - return mAdvertiseTimeoutSeconds; + return mAdvertiseTimeoutMillis; } @Override @@ -123,7 +123,7 @@ public final class AdvertiseSettings implements Parcelable { return "Settings [mAdvertiseMode=" + mAdvertiseMode + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel + ", mAdvertiseConnectable=" + mAdvertiseConnectable - + ", mAdvertiseTimeoutSeconds=" + mAdvertiseTimeoutSeconds + "]"; + + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]"; } @Override @@ -136,12 +136,9 @@ public final class AdvertiseSettings implements Parcelable { dest.writeInt(mAdvertiseMode); dest.writeInt(mAdvertiseTxPowerLevel); dest.writeInt(mAdvertiseConnectable ? 1 : 0); - dest.writeInt(mAdvertiseTimeoutSeconds); + dest.writeInt(mAdvertiseTimeoutMillis); } - /** - * @hide - */ public static final Parcelable.Creator<AdvertiseSettings> CREATOR = new Creator<AdvertiseSettings>() { @Override @@ -161,7 +158,7 @@ public final class AdvertiseSettings implements Parcelable { public static final class Builder { private int mMode = ADVERTISE_MODE_LOW_POWER; private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM; - private int mTimeoutSeconds = 0; + private int mTimeoutMillis = 0; private boolean mConnectable = true; /** @@ -204,26 +201,26 @@ public final class AdvertiseSettings implements Parcelable { /** * Set whether the advertisement type should be connectable or non-connectable. * - * @param isConnectable Controls whether the advertisment type will be connectable (true) + * @param connectable Controls whether the advertisment type will be connectable (true) * or non-connectable (false). */ - public Builder setIsConnectable(boolean isConnectable) { - mConnectable = isConnectable; + public Builder setConnectable(boolean connectable) { + mConnectable = connectable; return this; } /** * Limit advertising to a given amount of time. - * @param timeoutSeconds Advertising time limit. May not exceed 180 seconds. + * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds. * A value of 0 will disable the time limit. - * @throws IllegalArgumentException If the provided timeout is over 180s. + * @throws IllegalArgumentException If the provided timeout is over 180000 ms. */ - public Builder setTimeout(int timeoutSeconds) { - if (timeoutSeconds < 0 || timeoutSeconds > LIMITED_ADVERTISING_MAX_DURATION) { - throw new IllegalArgumentException("timeoutSeconds invalid (must be 0-" - + LIMITED_ADVERTISING_MAX_DURATION + " seconds)"); + public Builder setTimeout(int timeoutMillis) { + if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) { + throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" + + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)"); } - mTimeoutSeconds = timeoutSeconds; + mTimeoutMillis = timeoutMillis; return this; } @@ -231,7 +228,7 @@ public final class AdvertiseSettings implements Parcelable { * Build the {@link AdvertiseSettings} object. */ public AdvertiseSettings build() { - return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutSeconds); + return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis); } } } diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java index 5b37384..05782a8 100644 --- a/core/java/android/bluetooth/le/ScanCallback.java +++ b/core/java/android/bluetooth/le/ScanCallback.java @@ -47,8 +47,8 @@ public abstract class ScanCallback { /** * Callback when a BLE advertisement has been found. * - * @param callbackType Determines if this callback was triggered because of first match, a lost - * match indication or a regular scan result. + * @param callbackType Determines how this callback was triggered. Currently could only be + * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}. * @param result A Bluetooth LE scan result. */ public void onScanResult(int callbackType, ScanResult result) { @@ -64,6 +64,7 @@ public abstract class ScanCallback { /** * Callback when scan could not be started. + * * @param errorCode Error code (one of SCAN_FAILED_*) for scan failure. */ public void onScanFailed(int errorCode) { diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index d1b93d2..5025218 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -138,8 +138,6 @@ public final class ScanFilter implements Parcelable { /** * A {@link android.os.Parcelable.Creator} to create {@link ScanFilter} from parcel. - * - * @hide */ public static final Creator<ScanFilter> CREATOR = new Creator<ScanFilter>() { diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index a0bdaff..2fdfe7f 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -149,9 +149,6 @@ public final class ScanResult implements Parcelable { + mTimestampNanos + '}'; } - /** - * @hide - */ public static final Parcelable.Creator<ScanResult> CREATOR = new Creator<ScanResult>() { @Override public ScanResult createFromParcel(Parcel source) { diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index b2ee6a8..7eae439 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -52,19 +52,28 @@ public final class ScanSettings implements Parcelable { /** * A result callback is only triggered for the first advertisement packet received that matches * the filter criteria. + * + * @hide */ + @SystemApi public static final int CALLBACK_TYPE_FIRST_MATCH = 2; /** * Receive a callback when advertisements are no longer received from a device that has been * previously reported by a first match callback. + * + * @hide */ + @SystemApi public static final int CALLBACK_TYPE_MATCH_LOST = 4; /** * Request full scan results which contain the device, rssi, advertising data, scan response as * well as the scan timestamp. + * + * @hide */ + @SystemApi public static final int SCAN_RESULT_TYPE_FULL = 0; /** @@ -137,9 +146,6 @@ public final class ScanSettings implements Parcelable { return 0; } - /** - * @hide - */ public static final Parcelable.Creator<ScanSettings> CREATOR = new Creator<ScanSettings>() { @Override @@ -183,7 +189,9 @@ public final class ScanSettings implements Parcelable { * * @param callbackType The callback type flags for the scan. * @throws IllegalArgumentException If the {@code callbackType} is invalid. + * @hide */ + @SystemApi public Builder setCallbackType(int callbackType) { if (!isValidCallbackType(callbackType)) { @@ -226,14 +234,14 @@ public final class ScanSettings implements Parcelable { /** * Set report delay timestamp for Bluetooth LE scan. * - * @param reportDelayMillis Set to 0 to be notified of results immediately. Values > 0 - * causes the scan results to be queued up and delivered after the requested - * delay or when the internal buffers fill up. + * @param reportDelayMillis Delay of report in milliseconds. Set to 0 to be notified of + * results immediately. Values > 0 causes the scan results to be queued up and + * delivered after the requested delay or when the internal buffers fill up. * @throws IllegalArgumentException If {@code reportDelayMillis} < 0. */ - public Builder setReportDelayMillis(long reportDelayMillis) { + public Builder setReportDelay(long reportDelayMillis) { if (reportDelayMillis < 0) { - throw new IllegalArgumentException("reportDelayMillis must be > 0"); + throw new IllegalArgumentException("reportDelay must be > 0"); } mReportDelayMillis = reportDelayMillis; return this; diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 7419ebc..9afdbf7 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -45,6 +45,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.security.MessageDigest; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -86,6 +87,8 @@ public class PackageInstaller { * <p> * In some cases, a matching Activity may not exist, so ensure you safeguard * against this. + * <p> + * The session to show details for is defined in {@link #EXTRA_SESSION_ID}. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; @@ -95,21 +98,57 @@ public class PackageInstaller { ACTION_CONFIRM_PERMISSIONS = "android.content.pm.action.CONFIRM_PERMISSIONS"; /** - * An integer session ID. + * An integer session ID that an operation is working with. * - * @see #ACTION_SESSION_DETAILS + * @see Intent#getIntExtra(String, int) */ public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID"; + /** + * Package name that an operation is working with. + * + * @see Intent#getStringExtra(String) + */ + public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; + + /** + * Current status of an operation. Will be one of + * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS}, + * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED}, + * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT}, + * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or + * {@link #STATUS_FAILURE_STORAGE}. + * <p> + * More information about a status may be available through additional + * extras; see the individual status documentation for details. + * + * @see Intent#getIntExtra(String, int) + */ public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS"; + + /** + * Detailed string representation of the status, including raw details that + * are useful for debugging. + * + * @see Intent#getStringExtra(String) + */ public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE"; /** - * Package name relevant to a status. + * Another package name relevant to a status. This is typically the package + * responsible for causing an operation failure. * * @see Intent#getStringExtra(String) */ - public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; + public static final String + EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME"; + + /** + * Storage path relevant to a status. + * + * @see Intent#getStringExtra(String) + */ + public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH"; /** {@hide} */ @Deprecated @@ -153,8 +192,12 @@ public class PackageInstaller { * The operation failed because it was blocked. For example, a device policy * may be blocking the operation, a package verifier may have blocked the * operation, or the app may be required for core system operation. + * <p> + * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the + * specific package blocking the install. * * @see #EXTRA_STATUS_MESSAGE + * @see #EXTRA_OTHER_PACKAGE_NAME */ public static final int STATUS_FAILURE_BLOCKED = 2; @@ -182,10 +225,11 @@ public class PackageInstaller { * permission, incompatible certificates, etc. The user may be able to * uninstall another app to fix the issue. * <p> - * The result may also contain {@link #EXTRA_PACKAGE_NAME} with the + * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the * specific package identified as the cause of the conflict. * * @see #EXTRA_STATUS_MESSAGE + * @see #EXTRA_OTHER_PACKAGE_NAME */ public static final int STATUS_FAILURE_CONFLICT = 5; @@ -193,8 +237,12 @@ public class PackageInstaller { * The operation failed because of storage issues. For example, the device * may be running low on space, or external media may be unavailable. The * user may be able to help free space or insert different external media. + * <p> + * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to + * the storage device that caused the failure. * * @see #EXTRA_STATUS_MESSAGE + * @see #EXTRA_STORAGE_PATH */ public static final int STATUS_FAILURE_STORAGE = 6; @@ -281,6 +329,13 @@ public class PackageInstaller { * To succeed, the caller must be the current home app. */ public @NonNull List<SessionInfo> getAllSessions() { + final ApplicationInfo info = mContext.getApplicationInfo(); + if ("com.google.android.googlequicksearchbox".equals(info.packageName) + && info.versionCode <= 300400070) { + Log.d(TAG, "Ignoring callback request from old prebuilt"); + return Collections.EMPTY_LIST; + } + try { return mInstaller.getAllSessions(mUserId); } catch (RemoteException e) { diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index eb8b762..142206a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -264,7 +264,7 @@ public class PackageParser { public final boolean coreApp; public final boolean multiArch; - private PackageLite(String codePath, ApkLite baseApk, String[] splitNames, + public PackageLite(String codePath, ApkLite baseApk, String[] splitNames, String[] splitCodePaths) { this.packageName = baseApk.packageName; this.versionCode = baseApk.versionCode; diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java index 0dbde6b..518a874 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java @@ -25,6 +25,8 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.service.voice.AlwaysOnHotwordDetector; +import android.text.TextUtils; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.Slog; import android.util.Xml; @@ -35,6 +37,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Locale; /** * Enrollment information about the different available keyphrases. @@ -74,6 +77,7 @@ public class KeyphraseEnrollmentInfo { "com.android.intent.extra.VOICE_KEYPHRASE_HINT_TEXT"; /** * Intent extra: The voice locale to use while managing the keyphrase. + * This is a BCP-47 language tag. */ public static final String EXTRA_VOICE_KEYPHRASE_LOCALE = "com.android.intent.extra.VOICE_KEYPHRASE_LOCALE"; @@ -151,33 +155,8 @@ public class KeyphraseEnrollmentInfo { TypedArray array = res.obtainAttributes(attrs, com.android.internal.R.styleable.VoiceEnrollmentApplication); - int searchKeyphraseId = array.getInt( - com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphraseId, - -1); - if (searchKeyphraseId != -1) { - String searchKeyphrase = array.getString(com.android.internal.R.styleable - .VoiceEnrollmentApplication_searchKeyphrase); - if (searchKeyphrase == null) { - searchKeyphrase = ""; - } - String searchKeyphraseSupportedLocales = - array.getString(com.android.internal.R.styleable - .VoiceEnrollmentApplication_searchKeyphraseSupportedLocales); - String[] supportedLocales = new String[0]; - // Get all the supported locales from the comma-delimted string. - if (searchKeyphraseSupportedLocales != null - && !searchKeyphraseSupportedLocales.isEmpty()) { - supportedLocales = searchKeyphraseSupportedLocales.split(","); - } - int recognitionModes = array.getInt(com.android.internal.R.styleable - .VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, 0); - mKeyphrases = new KeyphraseMetadata[1]; - mKeyphrases[0] = new KeyphraseMetadata( - searchKeyphraseId, searchKeyphrase, supportedLocales, recognitionModes); - } else { - mParseError = "searchKeyphraseId not specified in meta-data"; - return; - } + initializeKeyphrasesFromTypedArray(array); + array.recycle(); } catch (XmlPullParserException e) { mParseError = "Error parsing keyphrase enrollment meta-data: " + e; Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e); @@ -195,6 +174,65 @@ public class KeyphraseEnrollmentInfo { } } + private void initializeKeyphrasesFromTypedArray(TypedArray array) { + // Get the keyphrase ID. + int searchKeyphraseId = array.getInt( + com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphraseId, -1); + if (searchKeyphraseId <= 0) { + mParseError = "No valid searchKeyphraseId specified in meta-data"; + Slog.w(TAG, mParseError); + return; + } + + // Get the keyphrase text. + String searchKeyphrase = array.getString( + com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphrase); + if (searchKeyphrase == null) { + mParseError = "No valid searchKeyphrase specified in meta-data"; + Slog.w(TAG, mParseError); + return; + } + + // Get the supported locales. + String searchKeyphraseSupportedLocales = array.getString( + com.android.internal.R.styleable + .VoiceEnrollmentApplication_searchKeyphraseSupportedLocales); + if (searchKeyphraseSupportedLocales == null) { + mParseError = "No valid searchKeyphraseSupportedLocales specified in meta-data"; + Slog.w(TAG, mParseError); + return; + } + ArraySet<Locale> locales = new ArraySet<>(); + // Try adding locales if the locale string is non-empty. + if (!TextUtils.isEmpty(searchKeyphraseSupportedLocales)) { + try { + String[] supportedLocalesDelimited = searchKeyphraseSupportedLocales.split(","); + for (int i = 0; i < supportedLocalesDelimited.length; i++) { + locales.add(Locale.forLanguageTag(supportedLocalesDelimited[i])); + } + } catch (Exception ex) { + // We catch a generic exception here because we don't want the system service + // to be affected by a malformed metadata because invalid locales were specified + // by the system application. + mParseError = "Error reading searchKeyphraseSupportedLocales from meta-data"; + Slog.w(TAG, mParseError, ex); + return; + } + } + + // Get the supported recognition modes. + int recognitionModes = array.getInt(com.android.internal.R.styleable + .VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, -1); + if (recognitionModes < 0) { + mParseError = "No valid searchKeyphraseRecognitionFlags specified in meta-data"; + Slog.w(TAG, mParseError); + return; + } + mKeyphrases = new KeyphraseMetadata[1]; + mKeyphrases[0] = new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales, + recognitionModes); + } + public String getParseError() { return mParseError; } @@ -217,11 +255,10 @@ public class KeyphraseEnrollmentInfo { * or {@link AlwaysOnHotwordDetector#MANAGE_ACTION_UN_ENROLL} * @param keyphrase The keyphrase that the user needs to be enrolled to. * @param locale The locale for which the enrollment needs to be performed. - * This is a Java locale, for example "en_US". * @return An {@link Intent} to manage the keyphrase. This can be null if managing the * given keyphrase/locale combination isn't possible. */ - public Intent getManageKeyphraseIntent(int action, String keyphrase, String locale) { + public Intent getManageKeyphraseIntent(int action, String keyphrase, Locale locale) { if (mEnrollmentPackage == null || mEnrollmentPackage.isEmpty()) { Slog.w(TAG, "No enrollment application exists"); return null; @@ -231,7 +268,7 @@ public class KeyphraseEnrollmentInfo { Intent intent = new Intent(ACTION_MANAGE_VOICE_KEYPHRASES) .setPackage(mEnrollmentPackage) .putExtra(EXTRA_VOICE_KEYPHRASE_HINT_TEXT, keyphrase) - .putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale) + .putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale.toLanguageTag()) .putExtra(EXTRA_VOICE_KEYPHRASE_ACTION, action); return intent; } @@ -248,7 +285,7 @@ public class KeyphraseEnrollmentInfo { * @return The metadata, if the enrollment client supports the given keyphrase * and locale, null otherwise. */ - public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, String locale) { + public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, Locale locale) { if (mKeyphrases == null || mKeyphrases.length == 0) { Slog.w(TAG, "Enrollment application doesn't support keyphrases"); return null; diff --git a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java index 38305f9..ed8c296 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java @@ -18,6 +18,8 @@ package android.hardware.soundtrigger; import android.util.ArraySet; +import java.util.Locale; + /** * A Voice Keyphrase metadata read from the enrollment application. * @@ -26,17 +28,14 @@ import android.util.ArraySet; public class KeyphraseMetadata { public final int id; public final String keyphrase; - public final ArraySet<String> supportedLocales; + public final ArraySet<Locale> supportedLocales; public final int recognitionModeFlags; - public KeyphraseMetadata(int id, String keyphrase, String[] supportedLocales, + public KeyphraseMetadata(int id, String keyphrase, ArraySet<Locale> supportedLocales, int recognitionModeFlags) { this.id = id; this.keyphrase = keyphrase; - this.supportedLocales = new ArraySet<String>(supportedLocales.length); - for (String locale : supportedLocales) { - this.supportedLocales.add(locale); - } + this.supportedLocales = supportedLocales; this.recognitionModeFlags = recognitionModeFlags; } @@ -56,7 +55,7 @@ public class KeyphraseMetadata { /** * @return Indicates if we support the given locale. */ - public boolean supportsLocale(String locale) { + public boolean supportsLocale(Locale locale) { return supportedLocales.isEmpty() || supportedLocales.contains(locale); } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index ba811b7..2eb42a7 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -53,7 +53,6 @@ import android.view.WindowManager.BadTokenException; import android.view.animation.AnimationUtils; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CursorAnchorInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -1711,13 +1710,12 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called when the application has reported a new location of its text cursor. This is only - * called if explicitly requested by the input method. The default implementation does nothing. - * @param newCursor The new cursor position, in screen coordinates if the input method calls - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with - * {@link CursorAnchorInfoRequest#FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. Otherwise, - * this is in local coordinates. + * Called when the application has reported a new location of its text + * cursor. This is only called if explicitly requested by the input method. + * The default implementation does nothing. + * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead. */ + @Deprecated public void onUpdateCursor(Rect newCursor) { // Intentionally empty } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 75f8279..f7b0ead 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -17,6 +17,7 @@ package android.os; import android.annotation.SdkConstant; +import android.annotation.SystemApi; import android.content.Context; import android.util.Log; @@ -186,8 +187,6 @@ public final class PowerManager { * </p><p> * Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}. * </p> - * - * {@hide} */ public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020; @@ -197,6 +196,8 @@ public final class PowerManager { * <p> * This is used by the dream manager to implement doze mode. It currently * has no effect unless the power manager is in the dozing state. + * </p><p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. * </p> * * {@hide} @@ -243,11 +244,9 @@ public final class PowerManager { public static final int UNIMPORTANT_FOR_LOGGING = 0x40000000; /** - * Flag for {@link WakeLock#release release(int)} to defer releasing a - * {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor returns - * a negative value. - * - * {@hide} + * Flag for {@link WakeLock#release WakeLock.release(int)}: Defer releasing a + * {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor + * indicates that an object is not in close proximity. */ public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1; @@ -276,28 +275,44 @@ public final class PowerManager { * User activity event type: Unspecified event type. * @hide */ + @SystemApi public static final int USER_ACTIVITY_EVENT_OTHER = 0; /** * User activity event type: Button or key pressed or released. * @hide */ + @SystemApi public static final int USER_ACTIVITY_EVENT_BUTTON = 1; /** * User activity event type: Touch down, move or up. * @hide */ + @SystemApi public static final int USER_ACTIVITY_EVENT_TOUCH = 2; /** - * User activity flag: Do not restart the user activity timeout or brighten - * the display in response to user activity if it is already dimmed. + * User activity flag: If already dimmed, extend the dim timeout + * but do not brighten. This flag is useful for keeping the screen on + * a little longer without causing a visible change such as when + * the power key is pressed. * @hide */ + @SystemApi public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0; /** + * User activity flag: Note the user activity as usual but do not + * reset the user activity timeout. This flag is useful for applying + * user activity power hints when interacting with the device indirectly + * on a secondary screen while allowing the primary screen to go to sleep. + * @hide + */ + @SystemApi + public static final int USER_ACTIVITY_FLAG_INDIRECT = 1 << 1; + + /** * Go to sleep reason code: Going to sleep due by application request. * @hide */ @@ -335,6 +350,12 @@ public final class PowerManager { public static final int GO_TO_SLEEP_REASON_HDMI = 5; /** + * Go to sleep flag: Skip dozing state and directly go to full sleep. + * @hide + */ + public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0; + + /** * The value to pass as the 'reason' argument to reboot() to * reboot into recovery mode (for applying system updates, doing * factory resets, etc.). @@ -347,12 +368,6 @@ public final class PowerManager { */ public static final String REBOOT_RECOVERY = "recovery"; - /** - * Go to sleep flag: Skip dozing state and directly go to full sleep. - * @hide - */ - public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0; - final Context mContext; final IPowerManager mService; final Handler mHandler; @@ -456,6 +471,7 @@ public final class PowerManager { * @see #FULL_WAKE_LOCK * @see #SCREEN_DIM_WAKE_LOCK * @see #SCREEN_BRIGHT_WAKE_LOCK + * @see #PROXIMITY_SCREEN_OFF_WAKE_LOCK * @see #ACQUIRE_CAUSES_WAKEUP * @see #ON_AFTER_RELEASE */ @@ -505,11 +521,44 @@ public final class PowerManager { * * @see #wakeUp * @see #goToSleep + * + * @removed Requires signature or system permission. + * @deprecated Use {@link #userActivity(long, int, int)}. */ + @Deprecated public void userActivity(long when, boolean noChangeLights) { + userActivity(when, USER_ACTIVITY_EVENT_OTHER, + noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0); + } + + /** + * Notifies the power manager that user activity happened. + * <p> + * Resets the auto-off timer and brightens the screen if the device + * is not asleep. This is what happens normally when a key or the touch + * screen is pressed or when some other user activity occurs. + * This method does not wake up the device if it has been put to sleep. + * </p><p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} or + * {@link android.Manifest.permission#USER_ACTIVITY} permission. + * </p> + * + * @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()} + * time base. This timestamp is used to correctly order the user activity request with + * other power management functions. It should be set + * to the timestamp of the input event that caused the user activity. + * @param event The user activity event. + * @param flags Optional user activity flags. + * + * @see #wakeUp + * @see #goToSleep + * + * @hide Requires signature or system permission. + */ + @SystemApi + public void userActivity(long when, int event, int flags) { try { - mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER, - noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0); + mService.userActivity(when, event, flags); } catch (RemoteException e) { } } @@ -530,13 +579,33 @@ public final class PowerManager { * * @see #userActivity * @see #wakeUp + * + * @removed Requires signature permission. */ public void goToSleep(long time) { goToSleep(time, GO_TO_SLEEP_REASON_APPLICATION, 0); } /** - * @hide + * Forces the device to go to sleep. + * <p> + * Overrides all the wake locks that are held. + * This is what happens when the power key is pressed to turn off the screen. + * </p><p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. + * </p> + * + * @param time The time when the request to go to sleep was issued, in the + * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly + * order the go to sleep request with other power management functions. It should be set + * to the timestamp of the input event that caused the request to go to sleep. + * @param reason The reason the device is going to sleep. + * @param flags Optional flags to apply when going to sleep. + * + * @see #userActivity + * @see #wakeUp + * + * @hide Requires signature permission. */ public void goToSleep(long time, int reason, int flags) { try { @@ -561,6 +630,8 @@ public final class PowerManager { * * @see #userActivity * @see #goToSleep + * + * @removed Requires signature permission. */ public void wakeUp(long time) { try { @@ -588,7 +659,7 @@ public final class PowerManager { * @see #wakeUp * @see #goToSleep * - * @hide + * @hide Requires signature permission. */ public void nap(long time) { try { @@ -605,7 +676,7 @@ public final class PowerManager { * * @param brightness The brightness value from 0 to 255. * - * {@hide} + * @hide Requires signature permission. */ public void setBacklightBrightness(int brightness) { try { @@ -619,8 +690,6 @@ public final class PowerManager { * * @param level The wake lock level to check. * @return True if the specified wake lock level is supported. - * - * {@hide} */ public boolean isWakeLockLevelSupported(int level) { try { @@ -893,8 +962,6 @@ public final class PowerManager { * * @param flags Combination of flag values to modify the release behavior. * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported. - * - * {@hide} */ public void release(int flags) { synchronized (mToken) { diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 939cda9..d1fadd6 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -321,7 +321,7 @@ public interface IMountService extends IInterface { * Mount a secure container with the specified key and owner UID. * Returns an int consistent with MountServiceResultCode */ - public int mountSecureContainer(String id, String key, int ownerUid) + public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); @@ -331,6 +331,7 @@ public interface IMountService extends IInterface { _data.writeString(id); _data.writeString(key); _data.writeInt(ownerUid); + _data.writeInt(readOnly ? 1 : 0); mRemote.transact(Stub.TRANSACTION_mountSecureContainer, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); @@ -834,6 +835,27 @@ public interface IMountService extends IInterface { } return _result; } + + @Override + public int resizeSecureContainer(String id, int sizeMb, String key) + throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(id); + _data.writeInt(sizeMb); + _data.writeString(key); + mRemote.transact(Stub.TRANSACTION_resizeSecureContainer, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } } private static final String DESCRIPTOR = "IMountService"; @@ -918,6 +940,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_getField = IBinder.FIRST_CALL_TRANSACTION + 39; + static final int TRANSACTION_resizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 40; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1082,7 +1106,9 @@ public interface IMountService extends IInterface { key = data.readString(); int ownerUid; ownerUid = data.readInt(); - int resultCode = mountSecureContainer(id, key, ownerUid); + boolean readOnly; + readOnly = data.readInt() != 0; + int resultCode = mountSecureContainer(id, key, ownerUid, readOnly); reply.writeNoException(); reply.writeInt(resultCode); return true; @@ -1308,6 +1334,19 @@ public interface IMountService extends IInterface { reply.writeString(contents); return true; } + case TRANSACTION_resizeSecureContainer: { + data.enforceInterface(DESCRIPTOR); + String id; + id = data.readString(); + int sizeMb; + sizeMb = data.readInt(); + String key; + key = data.readString(); + int resultCode = resizeSecureContainer(id, sizeMb, key); + reply.writeNoException(); + reply.writeInt(resultCode); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1405,7 +1444,8 @@ public interface IMountService extends IInterface { * Mount a secure container with the specified key and owner UID. Returns an * int consistent with MountServiceResultCode */ - public int mountSecureContainer(String id, String key, int ownerUid) throws RemoteException; + public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) + throws RemoteException; /** * Mount external storage at given mount point. Returns an int consistent @@ -1571,4 +1611,6 @@ public interface IMountService extends IInterface { * @return contents of field */ public String getField(String field) throws RemoteException; + + public int resizeSecureContainer(String id, int sizeMb, String key) throws RemoteException; } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 8db99a5..942da5a 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -24,13 +24,17 @@ import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.database.Cursor; +import android.location.Country; +import android.location.CountryDetector; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.CommonDataKinds.Callable; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Data; import android.provider.ContactsContract.DataUsageFeedback; import android.telecomm.PhoneAccountHandle; +import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.internal.telephony.CallerInfo; @@ -345,6 +349,13 @@ public class CallLog { public static final String PHONE_ACCOUNT_ID = "subscription_id"; /** + * If a successful call is made that is longer than this duration, update the phone number + * in the ContactsProvider with the normalized version of the number, based on the user's + * current country code. + */ + private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10; + + /** * Adds a call to the call log. * * @param ci the CallerInfo object to get the target contact from. Can be null @@ -484,12 +495,13 @@ public class CallLog { if (cursor != null) { try { if (cursor.getCount() > 0 && cursor.moveToFirst()) { - final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() - .appendPath(cursor.getString(0)) - .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, - DataUsageFeedback.USAGE_TYPE_CALL) - .build(); - resolver.update(feedbackUri, new ContentValues(), null, null); + final String dataId = cursor.getString(0); + updateDataUsageStatForData(resolver, dataId); + if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS + && callType == Calls.OUTGOING_TYPE + && TextUtils.isEmpty(ci.normalizedNumber)) { + updateNormalizedNumber(context, resolver, dataId, number); + } } } finally { cursor.close(); @@ -562,5 +574,53 @@ public class CallLog { + " LIMIT -1 OFFSET 500)", null); return result; } + + private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) { + final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() + .appendPath(dataId) + .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, + DataUsageFeedback.USAGE_TYPE_CALL) + .build(); + resolver.update(feedbackUri, new ContentValues(), null, null); + } + + /** + * Update the normalized phone number for the given dataId in the ContactsProvider, based + * on the user's current country. + */ + private static void updateNormalizedNumber(Context context, ContentResolver resolver, + String dataId, String number) { + if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) { + return; + } + + final String countryIso = getCurrentCountryIso(context); + if (TextUtils.isEmpty(countryIso)) { + return; + } + + final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, + getCurrentCountryIso(context)); + if (TextUtils.isEmpty(normalizedNumber)) { + return; + } + + final ContentValues values = new ContentValues(); + values.put(Phone.NORMALIZED_NUMBER, normalizedNumber); + resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId}); + } + + private static String getCurrentCountryIso(Context context) { + String countryIso = null; + final CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + final Country country = detector.detectCountry(); + if (country != null) { + countryIso = country.getCountryIso(); + } + } + return countryIso; + } } } diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl index 637d080..bd80a3f 100644 --- a/core/java/android/service/trust/ITrustAgentService.aidl +++ b/core/java/android/service/trust/ITrustAgentService.aidl @@ -24,6 +24,7 @@ import android.service.trust.ITrustAgentServiceCallback; */ interface ITrustAgentService { oneway void onUnlockAttempt(boolean successful); + oneway void onTrustTimeout(); oneway void setCallback(ITrustAgentServiceCallback callback); oneway void setTrustAgentFeaturesEnabled(in Bundle options, IBinder token); } diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java index 5fe9194..337ae60 100644 --- a/core/java/android/service/trust/TrustAgentService.java +++ b/core/java/android/service/trust/TrustAgentService.java @@ -30,6 +30,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.SystemClock; import android.util.Log; import android.util.Slog; @@ -37,7 +38,10 @@ import android.util.Slog; * A service that notifies the system about whether it believes the environment of the device * to be trusted. * - * <p>Trust agents may only be provided by the platform.</p> + * <p>Trust agents may only be provided by the platform. It is expected that there is only + * one trust agent installed on the platform. In the event there is more than one, + * either trust agent can enable trust. + * </p> * * <p>To extend this class, you must declare the service in your manifest file with * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission @@ -90,6 +94,7 @@ public class TrustAgentService extends Service { private static final int MSG_UNLOCK_ATTEMPT = 1; private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2; + private static final int MSG_TRUST_TIMEOUT = 3; private ITrustAgentServiceCallback mCallback; @@ -118,6 +123,9 @@ public class TrustAgentService extends Service { onError("calling onSetTrustAgentFeaturesEnabledCompleted()"); } break; + case MSG_TRUST_TIMEOUT: + onTrustTimeout(); + break; } } }; @@ -139,21 +147,32 @@ public class TrustAgentService extends Service { } /** - * Called when the user attempted to authenticate on the device. + * Called after the user attempts to authenticate in keyguard with their device credentials, + * such as pin, pattern or password. * - * @param successful true if the attempt succeeded + * @param successful true if the user successfully completed the challenge. */ public void onUnlockAttempt(boolean successful) { } + /** + * Called when the timeout provided by the agent expires. Note that this may be called earlier + * than requested by the agent if the trust timeout is adjusted by the system or + * {@link DevicePolicyManager}. The agent is expected to re-evaluate the trust state and only + * call {@link #grantTrust(CharSequence, long, boolean)} if the trust state should be + * continued. + */ + public void onTrustTimeout() { + } + private void onError(String msg) { Slog.v(TAG, "Remote exception while " + msg); } /** - * Called when device policy wants to restrict features in the TrustAgent in response to + * Called when device policy wants to restrict features in the agent in response to * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }. - * TrustAgents that support this feature should overload this method and return 'true'. + * Agents that support this feature should overload this method and return 'true'. * * The list of options can be obtained by calling * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list @@ -174,10 +193,19 @@ public class TrustAgentService extends Service { * Call to grant trust on the device. * * @param message describes why the device is trusted, e.g. "Trusted by location". - * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust - * for this agent will automatically be revoked when the timeout expires. - * @param initiatedByUser indicates that the user has explicitly initiated an action that proves - * the user is about to use the device. + * @param durationMs amount of time in milliseconds to keep the device in a trusted state. + * Trust for this agent will automatically be revoked when the timeout expires unless + * extended by a subsequent call to this function. The timeout is measured from the + * invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}. + * For security reasons, the value should be no larger than necessary. + * The value may be adjusted by the system as necessary to comply with a policy controlled + * by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()} + * for determining when trust expires. + * @param initiatedByUser this is a hint to the system that trust is being granted as the + * direct result of user action - such as solving a security challenge. The hint is used + * by the system to optimize the experience. Behavior may vary by device and release, so + * one should only set this parameter if it meets the above criteria rather than relying on + * the behavior of any particular device or release. * @throws IllegalStateException if the agent is not currently managing trust. */ public final void grantTrust( @@ -254,13 +282,17 @@ public class TrustAgentService extends Service { } private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub { - @Override + @Override /* Binder API */ public void onUnlockAttempt(boolean successful) { - mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0) - .sendToTarget(); + mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget(); + } + + @Override /* Binder API */ + public void onTrustTimeout() { + mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); } - @Override + @Override /* Binder API */ public void setCallback(ITrustAgentServiceCallback callback) { synchronized (mLock) { mCallback = callback; @@ -280,7 +312,7 @@ public class TrustAgentService extends Service { } } - @Override + @Override /* Binder API */ public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) { Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token); msg.setData(features); diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index 15e66a0..2095773 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -39,10 +39,10 @@ import android.util.Slog; import com.android.internal.app.IVoiceInteractionManagerService; -import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Locale; /** * A class that lets a VoiceInteractionService implementation interact with @@ -167,7 +167,7 @@ public class AlwaysOnHotwordDetector { private static final int MSG_DETECTION_RESUME = 5; private final String mText; - private final String mLocale; + private final Locale mLocale; /** * The metadata of the Keyphrase, derived from the enrollment application. * This may be null if this keyphrase isn't supported by the enrollment application. @@ -317,7 +317,7 @@ public class AlwaysOnHotwordDetector { * * @hide */ - public AlwaysOnHotwordDetector(String text, String locale, Callback callback, + public AlwaysOnHotwordDetector(String text, Locale locale, Callback callback, KeyphraseEnrollmentInfo keyphraseEnrollmentInfo, IVoiceInteractionService voiceInteractionService, IVoiceInteractionManagerService modelManagementService) { @@ -491,8 +491,6 @@ public class AlwaysOnHotwordDetector { */ void onSoundModelsChanged() { synchronized (mLock) { - // FIXME: This should stop the recognition if it was using an enrolled sound model - // that's no longer available. if (mAvailability == STATE_INVALID || mAvailability == STATE_HARDWARE_UNAVAILABLE || mAvailability == STATE_KEYPHRASE_UNSUPPORTED) { @@ -500,6 +498,13 @@ public class AlwaysOnHotwordDetector { return; } + // Stop the recognition before proceeding. + // This is done because we want to stop the recognition on an older model if it changed + // or was deleted. + // The availability change callback should ensure that the client starts recognition + // again if needed. + stopRecognitionLocked(); + // Execute a refresh availability task - which should then notify of a change. new RefreshAvailabiltyTask().execute(); } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index b200356..884fa9f 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -35,6 +35,7 @@ import com.android.internal.app.IVoiceInteractionManagerService; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Locale; /** @@ -163,7 +164,7 @@ public class VoiceInteractionService extends Service { * Called during service initialization to tell you when the system is ready * to receive interaction from it. You should generally do initialization here * rather than in {@link #onCreate()}. Methods such as {@link #startSession(Bundle)} and - * {@link #createAlwaysOnHotwordDetector(String, String, android.service.voice.AlwaysOnHotwordDetector.Callback)} + * {@link #createAlwaysOnHotwordDetector(String, Locale, android.service.voice.AlwaysOnHotwordDetector.Callback)} * will not be operational until this point. */ public void onReady() { @@ -200,6 +201,17 @@ public class VoiceInteractionService extends Service { } /** + * FIXME: Remove once the prebuilts are updated. + * + * @hide + */ + @Deprecated + public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( + String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) { + return createAlwaysOnHotwordDetector(keyphrase, new Locale(locale), callback); + } + + /** * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale. * This instance must be retained and used by the client. * Calling this a second time invalidates the previously created hotword detector @@ -207,12 +219,11 @@ public class VoiceInteractionService extends Service { * * @param keyphrase The keyphrase that's being used, for example "Hello Android". * @param locale The locale for which the enrollment needs to be performed. - * This is a Java locale, for example "en_US". * @param callback The callback to notify of detection events. * @return An always-on hotword detector for the given keyphrase and locale. */ public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( - String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) { + String keyphrase, Locale locale, AlwaysOnHotwordDetector.Callback callback) { if (mSystemService == null) { throw new IllegalStateException("Not available until onReady() is called"); } diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 681717c..964b054 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -657,11 +657,15 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: TV data service key. * Displays data services like weather, sports. */ public static final int KEYCODE_TV_DATA_SERVICE = 230; + /** Key code constant: Voice Assist key. + * Launches the global voice assist activity. Not delivered to applications. */ + public static final int KEYCODE_VOICE_ASSIST = 231; - private static final int LAST_KEYCODE = KEYCODE_TV_DATA_SERVICE; + private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST; // NOTE: If you add a new keycode here you must also add it to: // isSystem() + // isWakeKey() // frameworks/native/include/android/keycodes.h // frameworks/native/include/input/InputEventLabels.h // frameworks/base/core/res/res/values/attrs.xml diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 8cae27b..4d2f57a 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -429,25 +429,10 @@ public class BaseInputConnection implements InputConnection { } /** - * The default implementation is responsible for handling - * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. In fact, for derived classes, calling - * {@code super.requestCursorAnchorInfo(request)} is the only way to handle - * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. + * The default implementation does nothing. */ - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - // This implementation supports TYPE_CURSOR_RECT only. - if (request == null || - request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_RECT) { - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; - } - if (mIMM == null) { - // In this case, TYPE_CURSOR_RECT is not handled. - // TODO: Return some notification code for the input method that indicates - // Cursor rect information is temporarily unavailable. - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; - } - mIMM.setCursorRectMonitorMode(request.getRequestFlags()); - return CursorAnchorInfoRequest.RESULT_SCHEDULED; + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return false; } /** diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl deleted file mode 100644 index 41ef7cc6..0000000 --- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.view.inputmethod; - -parcelable CursorAnchorInfoRequest; diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java deleted file mode 100644 index e4c94f2..0000000 --- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package android.view.inputmethod; - -import android.inputmethodservice.InputMethodService; -import android.os.Parcel; -import android.os.Parcelable; -import android.view.View; - -/** - * Used to enable or disable event notification for - * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. This class is also used to - * enable {@link InputMethodService#onUpdateCursor(android.graphics.Rect)} for existing editors - * that have not supported {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. - */ -public final class CursorAnchorInfoRequest implements Parcelable { - private final int mRequestType; - private final int mRequestFlags; - - /** - * Not handled by the editor. - */ - public static final int RESULT_NOT_HANDLED = 0x00; - /** - * Request is scheduled in the editor task queue. - */ - public static final int RESULT_SCHEDULED = 0x01; - - /** - * The request is for {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. - * This mechanism is powerful enough to retrieve fine-grained positional information of - * characters in the editor. - */ - public static final int TYPE_CURSOR_ANCHOR_INFO = 0x01; - /** - * The editor is requested to call - * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} - * whenever cursor/anchor position is changed. To disable monitoring, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with - * {@link #TYPE_CURSOR_ANCHOR_INFO} and this flag off. - * <p> - * This flag can be used together with {@link #FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE}. - * </p> - */ - public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 0x01; - /** - * The editor is requested to call - * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at - * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be - * used together with {@link #FLAG_CURSOR_ANCHOR_INFO_MONITOR}. - */ - public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 0x02; - - /** - * The request is for {@link InputMethodService#onUpdateCursor(android.graphics.Rect)}. This - * mechanism has been available since API Level 3 (CUPCAKE) but only the cursor rectangle can - * be retrieved with this mechanism. - */ - public static final int TYPE_CURSOR_RECT = 0x02; - /** - * The editor is requested to call - * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} - * whenever the cursor position is changed. To disable monitoring, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with - * {@link #TYPE_CURSOR_RECT} and this flag off. - * <p> - * This flag can be used together with {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. - * </p> - */ - public static final int FLAG_CURSOR_RECT_MONITOR = 0x01; - /** - * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be - * called back in screen coordinates. To receive cursor position in local coordinates, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with - * {@link #TYPE_CURSOR_RECT} and this flag off. - */ - public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 0x02; - /** - * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be - * called back in screen coordinates after coordinate conversion with {@link View#getMatrix()}. - * To disable coordinate conversion with {@link View#getMatrix()} again, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with - * {@link #TYPE_CURSOR_RECT} and this flag off. - * - * <p> - * The flag is ignored if {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES} is off. - * </p> - */ - public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 0x04; - - /** - * Constructs the object with request type and type-specific flags. - * - * @param requestType the type of this request. Currently {@link #TYPE_CURSOR_ANCHOR_INFO} or - * {@link #TYPE_CURSOR_RECT} is supported. - * @param requestFlags the flags for the given request type. - */ - public CursorAnchorInfoRequest(int requestType, int requestFlags) { - mRequestType = requestType; - mRequestFlags = requestFlags; - } - - /** - * Used to make this class parcelable. - * - * @param source the parcel from which the object is unmarshalled. - */ - public CursorAnchorInfoRequest(Parcel source) { - mRequestType = source.readInt(); - mRequestFlags = source.readInt(); - } - - /** - * @return the type of this request. - */ - public int getRequestType() { - return mRequestType; - } - - /** - * @return the flags that are specific to the type of this request. - */ - public int getRequestFlags() { - return mRequestFlags; - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mRequestType); - dest.writeInt(mRequestFlags); - } - - @Override - public int hashCode(){ - return mRequestType * 31 + mRequestFlags; - } - - @Override - public boolean equals(Object obj){ - if (obj == null) { - return false; - } - if (this == obj) { - return true; - } - if (!(obj instanceof CursorAnchorInfoRequest)) { - return false; - } - final CursorAnchorInfoRequest that = (CursorAnchorInfoRequest) obj; - if (hashCode() != that.hashCode()) { - return false; - } - return mRequestType != that.mRequestType && mRequestFlags == that.mRequestFlags; - } - - @Override - public String toString() { - return "CursorAnchorInfoRequest{mRequestType=" + mRequestType - + " mRequestFlags=" + mRequestFlags - + "}"; - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<CursorAnchorInfoRequest> CREATOR = - new Parcelable.Creator<CursorAnchorInfoRequest>() { - @Override - public CursorAnchorInfoRequest createFromParcel(Parcel source) { - return new CursorAnchorInfoRequest(source); - } - - @Override - public CursorAnchorInfoRequest[] newArray(int size) { - return new CursorAnchorInfoRequest[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index dff91dc..ca094c1 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -725,13 +725,34 @@ public interface InputConnection { public boolean performPrivateCommand(String action, Bundle data); /** - * Called by the IME to ask the editor for calling back + * The editor is requested to call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at + * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be + * used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}. + */ + public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0; + + /** + * The editor is requested to call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} + * whenever cursor/anchor position is changed. To disable monitoring, call + * {@link InputConnection#requestUpdateCursorAnchorInfo(int)} again with this flag off. + * <p> + * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}. + * </p> + */ + public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1; + + /** + * Called by the input method to ask the editor for calling back * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to * notify cursor/anchor locations. * - * @param request the details of the request. - * @return a result code that depends on {@link CursorAnchorInfoRequest#getRequestType()}. See - * {@link CursorAnchorInfoRequest} for details. + * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or + * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR} + * @return {@code true} if the request is scheduled. {@code false} to indicate that when the + * application will not call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}. */ - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode); } diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index c831d7c..d95df25 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -126,7 +126,7 @@ public class InputConnectionWrapper implements InputConnection { return mTarget.performPrivateCommand(action, data); } - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - return mTarget.requestCursorAnchorInfo(request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode); } } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index eec3570..0a472c7 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -313,9 +313,8 @@ public final class InputMethodManager { CompletionInfo[] mCompletions; // Cursor position on the screen. - Rect mNextCursorRect = new Rect(); + Rect mTmpCursorRect = new Rect(); Rect mCursorRect = new Rect(); - RectF mTempRectF = new RectF(); int mCursorSelStart; int mCursorSelEnd; int mCursorCandStart; @@ -372,28 +371,12 @@ public final class InputMethodManager { InputChannel mCurChannel; ImeInputEventSender mCurSender; - private static final int CURSOR_RECT_MONITOR_MODE_NONE = 0x0; - - private static final int CURSOR_RECT_MONITOR_FLAG_MASK = - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR | - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES | - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX; - - private static final int CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE = 0x0; - - private static final int CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK = - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR | - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE; - - /** - * The monitor mode for {@link #updateCursor(View, int, int, int, int)}. - */ - private int mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE; + private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0; /** * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}. */ - private int mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE; + private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20); final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20); @@ -446,8 +429,8 @@ public final class InputMethodManager { return; } - mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE; - mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE; + mRequestUpdateCursorAnchorInfoMonitorMode = + REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; setInputChannelLocked(res.channel); mCurMethod = res.method; @@ -1540,59 +1523,49 @@ public final class InputMethodManager { } /** - * Returns true if the current input method wants to watch the location + * Return true if the current input method wants to watch the location * of the input editor's cursor in its window. - */ - public boolean isWatchingCursor(View view) { - if (!isActive(view)) { - return false; - } - synchronized (mH) { - return (mCursorRectMonitorMode & CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR) != 0; - } - } - - /** - * Updates the result of {@link #isWatchingCursor(View)}. * - * @hide + * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead. */ - public void setCursorRectMonitorMode(int flags) { - synchronized (mH) { - mCursorRectMonitorMode = (CURSOR_RECT_MONITOR_FLAG_MASK & flags); - } + @Deprecated + public boolean isWatchingCursor(View view) { + return false; } /** - * Returns true if the current input method wants to be notified when cursor/anchor location + * Return true if the current input method wants to be notified when cursor/anchor location * is changed. * * @hide */ public boolean isCursorAnchorInfoEnabled() { synchronized (mH) { - final boolean isImmediate = (mCursorAnchorInfoMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; - final boolean isMonitoring = (mCursorAnchorInfoMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR) != 0; + final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; + final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0; return isImmediate || isMonitoring; } } /** - * Updates the result of {@link #isWatchingCursor(View)}. + * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}. * * @hide */ - public void setCursorAnchorInfoMonitorMode(int flags) { + public void setUpdateCursorAnchorInfoMode(int flags) { synchronized (mH) { - mCursorAnchorInfoMonitorMode = (CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK & flags); + mRequestUpdateCursorAnchorInfoMonitorMode = flags; } } /** * Report the current cursor location in its window. + * + * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead. */ + @Deprecated public void updateCursor(View view, int left, int top, int right, int bottom) { checkFocus(); synchronized (mH) { @@ -1601,33 +1574,15 @@ public final class InputMethodManager { || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } - if (DEBUG) Log.d(TAG, "updateCursor"); - final boolean usesScreenCoordinates = (mCursorRectMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES) != 0; - if (usesScreenCoordinates) { - view.getLocationOnScreen(mViewTopLeft); - final Matrix viewMatrix = view.getMatrix(); - final boolean usesViewMatrix = (viewMatrix != null) && ((mCursorRectMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX) != 0); - if (usesViewMatrix) { - mTempRectF.set(left, top, right, bottom); - mViewToScreenMatrix.set(viewMatrix); - mViewToScreenMatrix.postTranslate(mViewTopLeft[0], mViewTopLeft[1]); - mViewToScreenMatrix.mapRect(mTempRectF); - mNextCursorRect.set((int)mTempRectF.left, (int)mTempRectF.top, - (int)mTempRectF.right, (int)mTempRectF.bottom); - } else { - mNextCursorRect.set(left + mViewTopLeft[0], top + mViewTopLeft[1], - right + mViewTopLeft[0], bottom + mViewTopLeft[1]); - } - } else { - mNextCursorRect.set(left, top, right, bottom); - } - if (!Objects.equals(mCursorRect, mNextCursorRect)) { - if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mNextCursorRect); + + mTmpCursorRect.set(left, top, right, bottom); + if (!mCursorRect.equals(mTmpCursorRect)) { + if (DEBUG) Log.d(TAG, "updateCursor"); + try { - mCurMethod.updateCursor(mNextCursorRect); - mCursorRect.set(mNextCursorRect); + if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod); + mCurMethod.updateCursor(mTmpCursorRect); + mCursorRect.set(mTmpCursorRect); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } @@ -1652,8 +1607,8 @@ public final class InputMethodManager { } // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has // not been changed from the previous call. - final boolean isImmediate = (mCursorAnchorInfoMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; + final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) { // TODO: Consider always emitting this message once we have addressed redundant // calls of this method from android.widget.Editor. @@ -1668,8 +1623,8 @@ public final class InputMethodManager { mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo); mCursorAnchorInfo = cursorAnchorInfo; // Clear immediate bit (if any). - mCursorAnchorInfoMonitorMode &= - ~CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE; + mRequestUpdateCursorAnchorInfoMonitorMode &= + ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 60ef693..eb93745 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -65,7 +65,6 @@ import android.view.animation.LinearInterpolator; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -5718,8 +5717,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } @Override - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - return getTarget().requestCursorAnchorInfo(request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return getTarget().requestUpdateCursorAnchorInfo(cursorUpdateMode); } } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 3f5f045..29c8298 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1298,25 +1298,6 @@ public class Editor { reported = reportExtractedText(); } } - - if (imm.isWatchingCursor(mTextView) && highlight != null) { - highlight.computeBounds(ims.mTmpRectF, true); - ims.mTmpOffset[0] = ims.mTmpOffset[1] = 0; - - canvas.getMatrix().mapPoints(ims.mTmpOffset); - ims.mTmpRectF.offset(ims.mTmpOffset[0], ims.mTmpOffset[1]); - - ims.mTmpRectF.offset(0, cursorOffsetVertical); - - ims.mCursorRectInWindow.set((int)(ims.mTmpRectF.left + 0.5), - (int)(ims.mTmpRectF.top + 0.5), - (int)(ims.mTmpRectF.right + 0.5), - (int)(ims.mTmpRectF.bottom + 0.5)); - - imm.updateCursor(mTextView, - ims.mCursorRectInWindow.left, ims.mCursorRectInWindow.top, - ims.mCursorRectInWindow.right, ims.mCursorRectInWindow.bottom); - } } } @@ -4136,7 +4117,6 @@ public class Editor { static class InputMethodState { Rect mCursorRectInWindow = new Rect(); - RectF mTmpRectF = new RectF(); float[] mTmpOffset = new float[2]; ExtractedTextRequest mExtractedTextRequest; final ExtractedText mExtractedText = new ExtractedText(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 096fe88..9b3a1e0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5719,8 +5719,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (mEditor != null && mEditor.mKeyListener != null) { - resetErrorChangedFlag(); - boolean doDown = true; if (otherEvent != null) { try { @@ -7637,6 +7635,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener list.get(i).afterTextChanged(text); } } + hideErrorIfUnchanged(); } void updateAfterEdit() { @@ -7676,7 +7675,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } ims.mChangedDelta += after-before; } - + resetErrorChangedFlag(); sendOnTextChanged(buffer, start, before, after); onTextChanged(buffer, start, before, after); } diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index 1b89179..ae44047 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -37,6 +37,8 @@ import com.android.internal.R; import java.util.Calendar; import java.util.Locale; +import libcore.icu.LocaleData; + import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES; @@ -143,11 +145,8 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input); mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); - /* Get the localized am/pm strings and use them in the spinner */ - final Resources res = context.getResources(); - final String amText = res.getString(R.string.time_picker_am_label); - final String pmText = res.getString(R.string.time_picker_pm_label); - mAmPmStrings = new String[] {amText, pmText}; + // Get the localized am/pm strings and use them in the spinner. + mAmPmStrings = getAmPmStrings(context); // am/pm View amPmView = mDelegator.findViewById(R.id.amPm); @@ -601,5 +600,12 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { } }; } -} + public static String[] getAmPmStrings(Context context) { + String[] result = new String[2]; + LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale); + result[0] = d.amPm[0].length() > 2 ? d.narrowAm : d.amPm[0]; + result[1] = d.amPm[1].length() > 2 ? d.narrowPm : d.amPm[1]; + return result; + } +} diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java index 9a50250..dd1bf4f 100644 --- a/core/java/android/widget/TimePickerSpinnerDelegate.java +++ b/core/java/android/widget/TimePickerSpinnerDelegate.java @@ -127,8 +127,10 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate im mSelectHours = res.getString(R.string.select_hours); mMinutePickerDescription = res.getString(R.string.minute_picker_description); mSelectMinutes = res.getString(R.string.select_minutes); - mAmText = res.getString(R.string.time_picker_am_label); - mPmText = res.getString(R.string.time_picker_pm_label); + + String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(context); + mAmText = amPmStrings[0]; + mPmText = amPmStrings[1]; final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout, R.layout.time_picker_holo); diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 8ee0a1b..cb0c3d0 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -230,16 +230,29 @@ public class VideoView extends SurfaceView mTargetState = STATE_IDLE; } + /** + * Sets video path. + * + * @param path the path of the video. + */ public void setVideoPath(String path) { setVideoURI(Uri.parse(path)); } + /** + * Sets video URI. + * + * @param uri the URI of the video. + */ public void setVideoURI(Uri uri) { setVideoURI(uri, null); } /** - * @hide + * Sets video URI using specific headers. + * + * @param uri the URI of the video. + * @param headers the headers for the URI request. */ public void setVideoURI(Uri uri, Map<String, String> headers) { mUri = uri; diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java index 229df8f..1f0bb76 100644 --- a/core/java/com/android/internal/app/LocalePicker.java +++ b/core/java/com/android/internal/app/LocalePicker.java @@ -27,6 +27,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -50,10 +51,6 @@ public class LocalePicker extends ListFragment { public void onLocaleSelected(Locale locale); } - protected boolean isInDeveloperMode() { - return false; - } - LocaleSelectionListener mListener; // default to null public static class LocaleInfo implements Comparable<LocaleInfo> { @@ -86,40 +83,17 @@ public class LocalePicker extends ListFragment { } } - /** - * Constructs an Adapter object containing Locale information. Content is sorted by - * {@link LocaleInfo#label}. - */ - public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) { - return constructAdapter(context, false /* disable pesudolocales */); - } - - public static ArrayAdapter<LocaleInfo> constructAdapter(Context context, - final boolean isInDeveloperMode) { - return constructAdapter(context, R.layout.locale_picker_item, R.id.locale, - isInDeveloperMode); - } - - public static ArrayAdapter<LocaleInfo> constructAdapter(Context context, - final int layoutId, final int fieldId) { - return constructAdapter(context, layoutId, fieldId, false /* disable pseudolocales */); - } - public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) { final Resources resources = context.getResources(); final String[] locales = Resources.getSystem().getAssets().getLocales(); List<String> localeList = new ArrayList<String>(locales.length); Collections.addAll(localeList, locales); - if (isInDeveloperMode) { - if (!localeList.contains("zz_ZZ")) { - localeList.add("zz_ZZ"); - } - /** - TODO: Enable when zz_ZY Pseudolocale is complete - * if (!localeList.contains("zz_ZY")) { - * localeList.add("zz_ZY"); - * } - */ + + // Don't show the pseudolocales unless we're in developer mode. http://b/17190407. + if (!isInDeveloperMode) { + localeList.remove("ar-XB"); + localeList.remove("en-XA"); } Collections.sort(localeList); @@ -160,14 +134,7 @@ public class LocalePicker extends ListFragment { localeInfos.add(new LocaleInfo(toTitleCase( getDisplayName(l, specialLocaleCodes, specialLocaleNames)), l)); } else { - String displayName; - if (locale.equals("zz_ZZ")) { - displayName = "[Developer] Accented English"; - } else if (locale.equals("zz_ZY")) { - displayName = "[Developer] Fake Bi-Directional"; - } else { - displayName = toTitleCase(l.getDisplayLanguage(l)); - } + String displayName = toTitleCase(l.getDisplayLanguage(l)); if (DEBUG) { Log.v(TAG, "adding "+displayName); } @@ -180,8 +147,18 @@ public class LocalePicker extends ListFragment { return localeInfos; } + /** + * Constructs an Adapter object containing Locale information. Content is sorted by + * {@link LocaleInfo#label}. + */ + public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) { + return constructAdapter(context, R.layout.locale_picker_item, R.id.locale); + } + public static ArrayAdapter<LocaleInfo> constructAdapter(Context context, - final int layoutId, final int fieldId, final boolean isInDeveloperMode) { + final int layoutId, final int fieldId) { + boolean isInDeveloperMode = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0; final List<LocaleInfo> localeInfos = getAllAssetLocales(context, isInDeveloperMode); final LayoutInflater inflater = @@ -232,8 +209,7 @@ public class LocalePicker extends ListFragment { @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity(), - isInDeveloperMode()); + final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity()); setListAdapter(adapter); } diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index 179d5e8..02f675c 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -25,6 +25,7 @@ import static android.system.OsConstants.S_IRWXU; import static android.system.OsConstants.S_IXGRP; import static android.system.OsConstants.S_IXOTH; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.Package; @@ -51,9 +52,11 @@ import java.util.List; */ public class NativeLibraryHelper { private static final String TAG = "NativeHelper"; - private static final boolean DEBUG_NATIVE = false; + public static final String LIB_DIR_NAME = "lib"; + public static final String LIB64_DIR_NAME = "lib64"; + // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate // that the cpuAbiOverride must be clear. public static final String CLEAR_ABI_OVERRIDE = "-"; @@ -70,6 +73,7 @@ public class NativeLibraryHelper { private volatile boolean mClosed; final long[] apkHandles; + final boolean multiArch; public static Handle create(File packageFile) throws IOException { try { @@ -81,14 +85,15 @@ public class NativeLibraryHelper { } public static Handle create(Package pkg) throws IOException { - return create(pkg.getAllCodePaths()); + return create(pkg.getAllCodePaths(), + (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0); } public static Handle create(PackageLite lite) throws IOException { - return create(lite.getAllCodePaths()); + return create(lite.getAllCodePaths(), lite.multiArch); } - private static Handle create(List<String> codePaths) throws IOException { + private static Handle create(List<String> codePaths, boolean multiArch) throws IOException { final int size = codePaths.size(); final long[] apkHandles = new long[size]; for (int i = 0; i < size; i++) { @@ -103,11 +108,12 @@ public class NativeLibraryHelper { } } - return new Handle(apkHandles); + return new Handle(apkHandles, multiArch); } - Handle(long[] apkHandles) { + Handle(long[] apkHandles, boolean multiArch) { this.apkHandles = apkHandles; + this.multiArch = multiArch; mGuard.open("close"); } @@ -159,8 +165,7 @@ public class NativeLibraryHelper { * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another * error code from that class if not */ - public static int copyNativeBinariesIfNeededLI(Handle handle, File sharedLibraryDir, - String abi) { + public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) { for (long apkHandle : handle.apkHandles) { int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi); if (res != INSTALL_SUCCEEDED) { @@ -267,7 +272,7 @@ public class NativeLibraryHelper { } } - private static long sumNativeBinaries(Handle handle, String[] abiList) { + private static long sumNativeBinariesForSupportedAbi(Handle handle, String[] abiList) { int abi = findSupportedAbi(handle, abiList); if (abi >= 0) { return sumNativeBinaries(handle, abiList[abi]); @@ -276,7 +281,7 @@ public class NativeLibraryHelper { } } - public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot, + public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot, String[] abiList, boolean useIsaSubdir) throws IOException { createNativeLibrarySubdir(libraryRoot); @@ -300,7 +305,7 @@ public class NativeLibraryHelper { subDir = libraryRoot; } - int copyRet = copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]); + int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]); if (copyRet != PackageManager.INSTALL_SUCCEEDED) { return copyRet; } @@ -309,10 +314,10 @@ public class NativeLibraryHelper { return abi; } - public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot, - String abiOverride, boolean multiArch) { + public static int copyNativeBinariesWithOverride(Handle handle, File libraryRoot, + String abiOverride) { try { - if (multiArch) { + if (handle.multiArch) { // Warn if we've set an abiOverride for multi-lib packages.. // By definition, we need to copy both 32 and 64 bit libraries for // such packages. @@ -322,7 +327,7 @@ public class NativeLibraryHelper { int copyRet = PackageManager.NO_NATIVE_LIBRARIES; if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { - copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, + copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */); if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES && copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { @@ -332,7 +337,7 @@ public class NativeLibraryHelper { } if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { - copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, + copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */); if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES && copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { @@ -355,7 +360,7 @@ public class NativeLibraryHelper { abiList = Build.SUPPORTED_32_BIT_ABIS; } - int copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, abiList, + int copyRet = copyNativeBinariesForSupportedAbi(handle, libraryRoot, abiList, true /* use isa specific subdirs */); if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]"); @@ -370,10 +375,10 @@ public class NativeLibraryHelper { } } - public static long sumNativeBinaries(Handle handle, String abiOverride, boolean multiArch) + public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride) throws IOException { long sum = 0; - if (multiArch) { + if (handle.multiArch) { // Warn if we've set an abiOverride for multi-lib packages.. // By definition, we need to copy both 32 and 64 bit libraries for // such packages. @@ -382,11 +387,11 @@ public class NativeLibraryHelper { } if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { - sum += sumNativeBinaries(handle, Build.SUPPORTED_32_BIT_ABIS); + sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); } if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { - sum += sumNativeBinaries(handle, Build.SUPPORTED_64_BIT_ABIS); + sum += sumNativeBinariesForSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); } } else { String cpuAbiOverride = null; @@ -403,7 +408,7 @@ public class NativeLibraryHelper { abiList = Build.SUPPORTED_32_BIT_ABIS; } - sum += sumNativeBinaries(handle, abiList); + sum += sumNativeBinariesForSupportedAbi(handle, abiList); } return sum; } diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index a529cc3..c17f4ee 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -16,11 +16,14 @@ package com.android.internal.content; +import static android.net.TrafficStats.MB_IN_BYTES; + import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.PackageParser.PackageLite; import android.os.Environment; import android.os.Environment.UserEnvironment; import android.os.FileUtils; @@ -77,9 +80,10 @@ public class PackageHelper { } } - public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid, + public static String createSdDir(long sizeBytes, String cid, String sdEncKey, int uid, boolean isExternal) { - // Create mount point via MountService + // Round up to nearest MB, plus another MB for filesystem overhead + final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1; try { IMountService mountService = getMountService(); @@ -102,19 +106,39 @@ public class PackageHelper { return null; } - public static String mountSdDir(String cid, String key, int ownerUid) { - try { - int rc = getMountService().mountSecureContainer(cid, key, ownerUid); - if (rc != StorageResultCode.OperationSucceeded) { - Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc); - return null; + public static boolean resizeSdDir(long sizeBytes, String cid, String sdEncKey) { + // Round up to nearest MB, plus another MB for filesystem overhead + final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1; + try { + IMountService mountService = getMountService(); + int rc = mountService.resizeSecureContainer(cid, sizeMb, sdEncKey); + if (rc == StorageResultCode.OperationSucceeded) { + return true; + } + } catch (RemoteException e) { + Log.e(TAG, "MountService running?"); } - return getMountService().getSecureContainerPath(cid); - } catch (RemoteException e) { - Log.e(TAG, "MountService running?"); + Log.e(TAG, "Failed to create secure container " + cid); + return false; + } + + public static String mountSdDir(String cid, String key, int ownerUid) { + return mountSdDir(cid, key, ownerUid, true); + } + + public static String mountSdDir(String cid, String key, int ownerUid, boolean readOnly) { + try { + int rc = getMountService().mountSecureContainer(cid, key, ownerUid, readOnly); + if (rc != StorageResultCode.OperationSucceeded) { + Log.i(TAG, "Failed to mount container " + cid + " rc : " + rc); + return null; + } + return getMountService().getSecureContainerPath(cid); + } catch (RemoteException e) { + Log.e(TAG, "MountService running?"); + } + return null; } - return null; - } public static boolean unMountSdDir(String cid) { try { @@ -400,6 +424,37 @@ public class PackageHelper { } } + public static long calculateInstalledSize(PackageLite pkg, boolean isForwardLocked, + String abiOverride) throws IOException { + NativeLibraryHelper.Handle handle = null; + try { + handle = NativeLibraryHelper.Handle.create(pkg); + return calculateInstalledSize(pkg, handle, isForwardLocked, abiOverride); + } finally { + IoUtils.closeQuietly(handle); + } + } + + public static long calculateInstalledSize(PackageLite pkg, NativeLibraryHelper.Handle handle, + boolean isForwardLocked, String abiOverride) throws IOException { + long sizeBytes = 0; + + // Include raw APKs, and possibly unpacked resources + for (String codePath : pkg.getAllCodePaths()) { + final File codeFile = new File(codePath); + sizeBytes += codeFile.length(); + + if (isForwardLocked) { + sizeBytes += PackageHelper.extractPublicFiles(codeFile, null); + } + } + + // Include all relevant native code + sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride); + + return sizeBytes; + } + public static String replaceEnd(String str, String before, String after) { if (!str.endsWith(before)) { throw new IllegalArgumentException( diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java index f812ad6..d6f6d0b 100644 --- a/core/java/com/android/internal/net/LegacyVpnInfo.java +++ b/core/java/com/android/internal/net/LegacyVpnInfo.java @@ -40,6 +40,7 @@ public class LegacyVpnInfo implements Parcelable { public String key; public int state = -1; + public PendingIntent intent; @Override public int describeContents() { @@ -50,6 +51,7 @@ public class LegacyVpnInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(key); out.writeInt(state); + out.writeParcelable(intent, flags); } public static final Parcelable.Creator<LegacyVpnInfo> CREATOR = @@ -59,6 +61,7 @@ public class LegacyVpnInfo implements Parcelable { LegacyVpnInfo info = new LegacyVpnInfo(); info.key = in.readString(); info.state = in.readInt(); + info.intent = in.readParcelable(null); return info; } diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java index aa66d7d..9c3f419 100644 --- a/core/java/com/android/internal/net/VpnConfig.java +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -28,6 +28,7 @@ import android.net.LinkAddress; import android.net.RouteInfo; import android.os.Parcel; import android.os.Parcelable; +import android.os.UserHandle; import java.net.Inet4Address; import java.net.InetAddress; @@ -57,6 +58,15 @@ public class VpnConfig implements Parcelable { return intent; } + /** NOTE: This should only be used for legacy VPN. */ + public static PendingIntent getIntentForStatusPanel(Context context) { + Intent intent = new Intent(); + intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | + Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, UserHandle.CURRENT); + } + public static CharSequence getVpnLabel(Context context, String packageName) throws NameNotFoundException { PackageManager pm = context.getPackageManager(); diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index 897381d..b1f5d90 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -25,7 +25,6 @@ import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; @@ -55,7 +54,7 @@ public class IInputConnectionWrapper extends IInputContext.Stub { private static final int DO_REPORT_FULLSCREEN_MODE = 100; private static final int DO_PERFORM_PRIVATE_COMMAND = 120; private static final int DO_CLEAR_META_KEY_STATES = 130; - private static final int DO_REQUEST_CURSOR_ANCHOR_INFO = 140; + private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140; private WeakReference<InputConnection> mInputConnection; @@ -177,9 +176,10 @@ public class IInputConnectionWrapper extends IInputContext.Stub { dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data)); } - public void requestCursorAnchorInfo(CursorAnchorInfoRequest request, int seq, + public void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq, IInputContextCallback callback) { - dispatchMessage(obtainMessageOSC(DO_REQUEST_CURSOR_ANCHOR_INFO, request, seq, callback)); + dispatchMessage(obtainMessageISC(DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO, cursorUpdateMode, + seq, callback)); } void dispatchMessage(Message msg) { @@ -427,18 +427,17 @@ public class IInputConnectionWrapper extends IInputContext.Stub { (Bundle)args.arg2); return; } - case DO_REQUEST_CURSOR_ANCHOR_INFO: { + case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: { SomeArgs args = (SomeArgs)msg.obj; try { InputConnection ic = mInputConnection.get(); if (ic == null || !isActive()) { Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection"); - args.callback.setRequestCursorAnchorInfoResult(0, args.seq); + args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq); return; } - args.callback.setRequestCursorAnchorInfoResult( - ic.requestCursorAnchorInfo((CursorAnchorInfoRequest)args.arg1), - args.seq); + args.callback.setRequestUpdateCursorAnchorInfoResult( + ic.requestUpdateCursorAnchorInfo(msg.arg1), args.seq); } catch (RemoteException e) { Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e); } diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl index c06596a..fd2b513 100644 --- a/core/java/com/android/internal/view/IInputContext.aidl +++ b/core/java/com/android/internal/view/IInputContext.aidl @@ -20,7 +20,6 @@ import android.os.Bundle; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.ExtractedTextRequest; import com.android.internal.view.IInputContextCallback; @@ -74,6 +73,6 @@ import com.android.internal.view.IInputContextCallback; void getSelectedText(int flags, int seq, IInputContextCallback callback); - void requestCursorAnchorInfo(in CursorAnchorInfoRequest request, int seq, + void requestUpdateCursorAnchorInfo(in int cursorUpdateMode, int seq, IInputContextCallback callback); } diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl index ab2fbdc..54ea306 100644 --- a/core/java/com/android/internal/view/IInputContextCallback.aidl +++ b/core/java/com/android/internal/view/IInputContextCallback.aidl @@ -27,5 +27,5 @@ oneway interface IInputContextCallback { void setCursorCapsMode(int capsMode, int seq); void setExtractedText(in ExtractedText extractedText, int seq); void setSelectedText(CharSequence selectedText, int seq); - void setRequestCursorAnchorInfoResult(int result, int seq); + void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq); } diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java index 8535a98..a8526c8 100644 --- a/core/java/com/android/internal/view/InputConnectionWrapper.java +++ b/core/java/com/android/internal/view/InputConnectionWrapper.java @@ -23,7 +23,6 @@ import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; @@ -41,7 +40,7 @@ public class InputConnectionWrapper implements InputConnection { public CharSequence mSelectedText; public ExtractedText mExtractedText; public int mCursorCapsMode; - public int mCursorAnchorInfoRequestResult; + public boolean mRequestUpdateCursorAnchorInfoResult; // A 'pool' of one InputContextCallback. Each ICW request will attempt to gain // exclusive access to this object. @@ -155,10 +154,10 @@ public class InputConnectionWrapper implements InputConnection { } } - public void setRequestCursorAnchorInfoResult(int result, int seq) { + public void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq) { synchronized (this) { if (seq == mSeq) { - mCursorAnchorInfoRequestResult = result; + mRequestUpdateCursorAnchorInfoResult = result; mHaveValue = true; notifyAll(); } else { @@ -429,21 +428,21 @@ public class InputConnectionWrapper implements InputConnection { } } - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - int value = CursorAnchorInfoRequest.RESULT_NOT_HANDLED; + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + boolean result = false; try { InputContextCallback callback = InputContextCallback.getInstance(); - mIInputContext.requestCursorAnchorInfo(request, callback.mSeq, callback); + mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode, callback.mSeq, callback); synchronized (callback) { callback.waitForResultLocked(); if (callback.mHaveValue) { - value = callback.mCursorAnchorInfoRequestResult; + result = callback.mRequestUpdateCursorAnchorInfoResult; } } callback.dispose(); } catch (RemoteException e) { - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; + return false; } - return value; + return result; } } diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java index 891baea..7eec392 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java @@ -265,13 +265,15 @@ public class ActionMenuItemView extends TextView final int width = getWidth(); final int height = getHeight(); final int midy = screenPos[1] + height / 2; - final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; - + int referenceX = screenPos[0] + width / 2; + if (v.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) { + final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; + referenceX = screenWidth - referenceX; // mirror + } Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT); if (midy < displayFrame.height()) { // Show along the top; follow action buttons - cheatSheet.setGravity(Gravity.TOP | Gravity.END, - screenWidth - screenPos[0] - width / 2, height); + cheatSheet.setGravity(Gravity.TOP | Gravity.END, referenceX, height); } else { // Show along the bottom center cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height); diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java index a2b8ff2..8111e63 100644 --- a/core/java/com/android/internal/widget/ActionBarContainer.java +++ b/core/java/com/android/internal/widget/ActionBarContainer.java @@ -272,9 +272,12 @@ public class ActionBarContainer extends FrameLayout { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); + if (child == mTabContainer) { + continue; + } final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - nonTabMaxHeight = isCollapsed(child) ? 0 : - child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; + nonTabMaxHeight = Math.max(nonTabMaxHeight, isCollapsed(child) ? 0 : + child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); } if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index bfe0090..2967938 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -25,9 +25,9 @@ import android.util.Log; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; import android.widget.TextView; public class EditableInputConnection extends BaseInputConnection { @@ -188,24 +188,17 @@ public class EditableInputConnection extends BaseInputConnection { } @Override - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - if (DEBUG) Log.v(TAG, "requestCursorAnchorInfo " + request); - - // This implementation supports TYPE_CURSOR_ANCHOR_INFO only. Other events will be - // delegated to the super class. - if (request == null || - request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_ANCHOR_INFO) { - return super.requestCursorAnchorInfo(request); - } + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode); + if (mIMM == null) { // In this case, TYPE_CURSOR_ANCHOR_INFO is not handled. - // TODO: Return some notification code for the input method that indicates + // TODO: Return some notification code rather than false to indicate method that // CursorAnchorInfo is temporarily unavailable. - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; + return false; } - final int flags = request.getRequestFlags(); - mIMM.setCursorAnchorInfoMonitorMode(flags); - if ((flags & CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) { + mIMM.setUpdateCursorAnchorInfoMode(cursorUpdateMode); + if ((cursorUpdateMode & InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) { if (mTextView == null) { // In this case, FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE is silently ignored. // TODO: Return some notification code for the input method that indicates @@ -220,6 +213,6 @@ public class EditableInputConnection extends BaseInputConnection { mTextView.requestLayout(); } } - return CursorAnchorInfoRequest.RESULT_SCHEDULED; + return true; } } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 74b1fdd..6dec036 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -479,6 +479,7 @@ public class LockPatternUtils { saveLockPattern(null); setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); + onAfterChangingPassword(); } /** @@ -565,6 +566,7 @@ public class LockPatternUtils { dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userId); } + onAfterChangingPassword(); } catch (RemoteException re) { Log.e(TAG, "Couldn't save lock pattern " + re); } @@ -844,6 +846,7 @@ public class LockPatternUtils { DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle); } + onAfterChangingPassword(); } catch (RemoteException re) { // Cant do much Log.e(TAG, "Unable to save lock password " + re); @@ -1561,4 +1564,8 @@ public class LockPatternUtils { public void requireCredentialEntry(int userId) { getTrustManager().reportRequireCredentialEntry(userId); } + + private void onAfterChangingPassword() { + getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId()); + } } diff --git a/services/backup/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java index 26e2e2a..26e2e2a 100644 --- a/services/backup/java/com/android/server/backup/SystemBackupAgent.java +++ b/core/java/com/android/server/backup/SystemBackupAgent.java diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index fbb243a..e02aa5e 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -54,26 +54,19 @@ static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong { SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); SkSafeUnref(shader); - SkShader* shaderWithLM = reinterpret_cast<SkShader*>(shaderWithLMHandle); - SkSafeUnref(shaderWithLM); } -static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, - jlong oldLocalMatrixShaderHandle, jlong matrixHandle) +static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle) { - // The old shader with local matrix is no longer needed, so unref it. - SkSafeUnref(reinterpret_cast<SkShader*>(oldLocalMatrixShaderHandle)); - SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); if (shader) { - if (NULL == matrix) { - matrix = &SkMatrix::I(); + if (matrix) { + shader->setLocalMatrix(*matrix); + } else { + shader->resetLocalMatrix(); } - SkShader* newShader = SkShader::CreateLocalMatrixShader(shader, *matrix); - shader = newShader; } - return reinterpret_cast<jlong>(shader); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -243,8 +236,8 @@ static JNINativeMethod gColorMethods[] = { }; static JNINativeMethod gShaderMethods[] = { - { "nativeDestructor", "(JJ)V", (void*)Shader_destructor }, - { "nativeSetLocalMatrix", "(JJJ)J", (void*)Shader_setLocalMatrix } + { "nativeDestructor", "(J)V", (void*)Shader_destructor }, + { "nativeSetLocalMatrix", "(JJ)V", (void*)Shader_setLocalMatrix } }; static JNINativeMethod gBitmapShaderMethods[] = { diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 3fb084a..8f30f5d 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -180,7 +180,8 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, // takes ownership of ScreenshotClient SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo, (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot, - (void*) (screenshot.detach())); + (void*) (screenshot.get())); + screenshot.detach(); pixels->setImmutable(); bitmap->setPixelRef(pixels)->unref(); bitmap->lockPixels(); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7809c71..672ad84 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2408,6 +2408,13 @@ android:description="@string/permdesc_devicePower" android:protectionLevel="signature" /> + <!-- Allows access to the PowerManager.userActivity function. + <p>Not for use by third-party applications. @hide @SystemApi --> + <permission android:name="android.permission.USER_ACTIVITY" + android:label="@string/permlab_userActivity" + android:description="@string/permdesc_userActivity" + android:protectionLevel="signature|system" /> + <!-- @hide Allows low-level access to tun tap driver --> <permission android:name="android.permission.NET_TUNNELING" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" @@ -2869,7 +2876,7 @@ android:label="@string/managed_profile_label"> </activity-alias> <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity" - android:theme="@style/Theme.Holo.Dialog" + android:theme="@style/Theme.Material.Dialog" android:label="@string/heavy_weight_switcher_title" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true" diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml index 3d8a527..f264b7b 100644 --- a/core/res/res/layout/notification_template_material_big_base.xml +++ b/core/res/res/layout/notification_template_material_big_base.xml @@ -37,14 +37,30 @@ > <include layout="@layout/notification_template_part_line1" /> <include layout="@layout/notification_template_part_line2" /> - <TextView android:id="@+id/big_text" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginEnd="8dp" - android:singleLine="false" - android:visibility="gone" - /> + android:orientation="horizontal" + android:gravity="top" + > + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:singleLine="false" + android:visibility="gone" + /> + <ImageView android:id="@+id/profile_badge_large_template" + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_weight="0" + android:layout_marginStart="4dp" + android:scaleType="fitCenter" + android:visibility="gone" + /> + </LinearLayout> <include layout="@layout/notification_template_part_line3" android:layout_width="match_parent" diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml index 36f8701..d9120f6 100644 --- a/core/res/res/layout/notification_template_material_big_text.xml +++ b/core/res/res/layout/notification_template_material_big_text.xml @@ -37,14 +37,31 @@ > <include layout="@layout/notification_template_part_line1" /> <include layout="@layout/notification_template_part_line2" /> - <TextView android:id="@+id/big_text" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginBottom="10dp" - android:visibility="gone" - /> + android:orientation="horizontal" + android:gravity="top" + > + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:singleLine="false" + android:visibility="gone" + /> + <ImageView android:id="@+id/profile_badge_large_template" + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_weight="0" + android:layout_marginStart="4dp" + android:scaleType="fitCenter" + android:visibility="gone" + /> + </LinearLayout> <ImageView android:layout_width="match_parent" android:layout_height="1dp" diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml index ef6cbd0..38b3ae2 100644 --- a/core/res/res/layout/notification_template_material_inbox.xml +++ b/core/res/res/layout/notification_template_material_inbox.xml @@ -37,79 +37,102 @@ > <include layout="@layout/notification_template_part_line1" /> <include layout="@layout/notification_template_part_line2" /> - <TextView android:id="@+id/inbox_text0" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + <LinearLayout android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_text1" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_text2" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_text3" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_text4" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_text5" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_text6" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - /> - <TextView android:id="@+id/inbox_more" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" - android:layout_width="match_parent" - android:layout_height="0dp" - android:singleLine="true" - android:ellipsize="end" - android:visibility="gone" - android:layout_weight="1" - android:text="@android:string/ellipsis" - /> + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="top" + > + <LinearLayout + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="wrap_content" + android:orientation="vertical" + > + <TextView android:id="@+id/inbox_text0" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text1" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text2" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text3" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text4" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text5" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text6" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_more" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + android:text="@android:string/ellipsis" + /> + </LinearLayout> + <ImageView android:id="@+id/profile_badge_large_template" + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_weight="0" + android:layout_marginStart="4dp" + android:layout_marginEnd="8dp" + android:scaleType="fitCenter" + android:visibility="gone" + /> + </LinearLayout> <FrameLayout android:id="@+id/inbox_end_pad" android:layout_width="match_parent" diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml index d3f202f..1f95150 100644 --- a/core/res/res/layout/notification_template_part_line2.xml +++ b/core/res/res/layout/notification_template_part_line2.xml @@ -16,20 +16,37 @@ --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> - <TextView - android:id="@+id/text2" - android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2" + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginEnd="8dp" - android:layout_marginTop="-1dp" - android:layout_marginBottom="-1dp" - android:singleLine="true" - android:fadingEdge="horizontal" - android:ellipsize="marquee" android:visibility="gone" android:layout_weight="0" + android:orientation="horizontal" + android:gravity="center_vertical" + > + <TextView + android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="-1dp" + android:layout_marginBottom="-1dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + android:layout_weight="1" /> + <ImageView android:id="@+id/profile_badge_line2" + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_weight="0" + android:layout_marginStart="4dp" + android:scaleType="fitCenter" + android:visibility="gone" + /> + </LinearLayout> <ProgressBar android:id="@android:id/progress" android:layout_width="match_parent" diff --git a/core/res/res/layout/notification_template_part_line3.xml b/core/res/res/layout/notification_template_part_line3.xml index dd2779d..06de2a5 100644 --- a/core/res/res/layout/notification_template_part_line3.xml +++ b/core/res/res/layout/notification_template_part_line3.xml @@ -43,13 +43,13 @@ android:gravity="center" android:paddingStart="8dp" /> - <ImageView android:id="@+id/profile_icon" - android:layout_width="24dp" - android:layout_height="24dp" + <ImageView android:id="@+id/profile_badge_line3" + android:layout_width="20dp" + android:layout_height="20dp" android:layout_gravity="center" android:layout_weight="0" - android:layout_marginStart="8dp" - android:scaleType="centerInside" + android:layout_marginStart="4dp" + android:scaleType="fitCenter" android:visibility="gone" /> </LinearLayout> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 45a392b..d27b49a 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Raak om USB-ontfouting te deaktiveer."</string> <string name="select_input_method" msgid="8547250819326693584">"Verander sleutelbord"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Kies sleutelborde"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fisiese sleutelbord"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardeware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Kies sleutelborduitleg"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Raak om \'n sleutelborduitleg te kies."</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 91f777d..ce5464c 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ማረሚያ ላለማንቃት ዳስስ።"</string> <string name="select_input_method" msgid="8547250819326693584">"ቁልፍ ሰሌዳ ይቀይሩ"</string> <string name="configure_input_methods" msgid="4769971288371946846">"ቁልፍ ሰሌዳዎችን ምረጥ"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"የሚዳሰስ የቁልፍ ሰሌዳ"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ሃርድዌር"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"የቁልፍ ሰሌዳ አቀማመጥ ምረጥ"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"የቁልፍ ሰሌዳ አቀማመጥ ለመምረጥ ንካ።"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index e0cd94c..a6f65d0 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"المس لتعطيل تصحيح أخطاء USB."</string> <string name="select_input_method" msgid="8547250819326693584">"تغيير لوحة المفاتيح"</string> <string name="configure_input_methods" msgid="4769971288371946846">"اختيار لوحات المفاتيح"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"لوحة مفاتيح فعلية"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"أجهزة"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"تحديد تخطيط لوحة مفاتيح"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"المس لتحديد تخطيط لوحة مفاتيح."</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 51d11c6..f2a9927 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Докоснете, за да деактивирате отстраняването на грешки през USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Промяна на клавиатурата"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Избиране на клавиатури"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Физическа клавиатура"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Хардуер"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избиране на клавиатурна подредба"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Докоснете, за да изберете клавиатурна подредба."</string> diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml index c288ab1..d0a6813 100644 --- a/core/res/res/values-bn-rBD/strings.xml +++ b/core/res/res/values-bn-rBD/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ডিবাগিং অক্ষম করতে স্পর্শ করুন৷"</string> <string name="select_input_method" msgid="8547250819326693584">"কীবোর্ড পরিবর্তন করুন"</string> <string name="configure_input_methods" msgid="4769971288371946846">"কীবোর্ড চয়ন করুন"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ফিজিক্যাল কীবোর্ড"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"হার্ডওয়্যার"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"কীবোর্ডের লেআউট নির্বাচন করুন"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"একটি কীবোর্ডের লেআউট নির্বাচন করতে স্পর্শ করুন৷"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 510c772..75cc1f0 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca per desactivar la depuració USB"</string> <string name="select_input_method" msgid="8547250819326693584">"Canviar el teclat"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Tria els teclats"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclat físic"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Maquinari"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona una disposició de teclat"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca per seleccionar una disposició de teclat."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 7bab386..7853f50 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotykem zakážete ladění USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Změna klávesnice"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Vyberte klávesnice"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyzická klávesnice"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Výběr rozložení klávesnice"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dotykem vyberte rozložení klávesnice."</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index c0351bc..6d05780 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryk for at deaktivere USB-fejlretning."</string> <string name="select_input_method" msgid="8547250819326693584">"Skift tastatur"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Vælg tastaturer"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysisk tastatur"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Vælg tastaturlayout"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tryk for at vælge et tastaturlayout."</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index e45ce8a..8f7866f 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren von USB-Debugging berühren"</string> <string name="select_input_method" msgid="8547250819326693584">"Tastatur ändern"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Tastatur auswählen"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Physische Tastatur"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Tastaturlayout auswählen"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Zum Auswählen eines Tastaturlayouts berühren"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index b3db37d..b68c386 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -716,10 +716,8 @@ <string name="permdesc_use_sip" msgid="2297804849860225257">"Επιτρέπει στην εφαρμογή να πραγματοποιεί και να λαμβάνει κλήσεις SIP."</string> <string name="permlab_bind_call_service" msgid="6724009726671246551">"αλληλεπίδραση με την οθόνη κατά τη διάρκεια κλήσης"</string> <string name="permdesc_bind_call_service" msgid="8732547662442572435">"Επιτρέπει στην εφαρμογή να ελέγχει πότε και πώς βλέπει ο χρήστης την οθόνη κατά τη διάρκεια κλήσης."</string> - <!-- no translation found for permlab_bind_connection_service (3557341439297014940) --> - <skip /> - <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) --> - <skip /> + <string name="permlab_bind_connection_service" msgid="3557341439297014940">"αλληλεπίδραση με υπηρεσίες τηλεφωνίας"</string> + <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Επιτρέπει στην εφαρμογή να αλληλεπιδρά με υπηρεσίες τηλεφωνίας για την πραγματοποίηση/λήψη κλήσεων."</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ανάγνωση ιστορικών δεδομένων χρήσης δικτύου"</string> <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Επιτρέπει στην εφαρμογή την ανάγνωση ιστορικών στοιχείων χρήσης δικτύου για συγκεκριμένα δίκτυα και εφαρμογές."</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"διαχείριση πολιτικής δικτύου"</string> @@ -1352,7 +1350,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Αγγίξτε για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Αλλαγή πληκτρολογίου"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Επιλογή πληκτρολογίων"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Φυσικό πληκτρολόγιο"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Υλικό"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Επιλογή διάταξης πληκτρολογίου"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Αγγίξτε για να επιλέξετε διάταξη πληκτρολογίου."</string> @@ -1764,31 +1763,20 @@ <string name="item_is_selected" msgid="949687401682476608">"Επιλέχτηκε το στοιχείο <xliff:g id="ITEM">%1$s</xliff:g>"</string> <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string> <string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string> - <!-- no translation found for lock_to_app_toast (1230563865743799321) --> - <skip /> - <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) --> - <skip /> - <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) --> - <skip /> - <!-- no translation found for lock_to_app_title (1682643873107812874) --> - <skip /> - <!-- no translation found for lock_to_app_description (9076084599283282800) --> - <skip /> - <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) --> - <skip /> + <string name="lock_to_app_toast" msgid="1230563865743799321">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα τα κουμπιά \"Επιστροφή\" και \"Πρόσφατα\" ταυτόχρονα."</string> + <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα το κουμπί \"Πρόσφατα\"."</string> + <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"Η οθόνη καρφιστώθηκε. Το ξεκαρφίτσωμα δεν επιτρέπεται από τον οργανισμό σας."</string> + <string name="lock_to_app_title" msgid="1682643873107812874">"Χρήση καρφιτσώματος οθόνης;"</string> + <string name="lock_to_app_description" msgid="9076084599283282800">"Το καρφίτσωμα της οθόνης κλειδώνει την οθόνη σε μία μόνο προβολή.\n\nΓια έξοδο, αγγίξτε παρατεταμένα τα κουμπιά \"Επιστροφή\" και \"Πρόσφατα\" ταυτόχρονα."</string> + <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"Το καρφίτσωμα της οθόνης κλειδώνει την οθόνη σε μία μόνο προβολή.\n\nΓια έξοδο, αγγίξτε παρατεταμένα το κουμπί \"Πρόσφατα\"."</string> <string name="lock_to_app_negative" msgid="2259143719362732728">"ΟΧΙ, ΕΥΧΑΡΙΣΤΩ"</string> <string name="lock_to_app_positive" msgid="7085139175671313864">"ΕΝΑΡΞΗ"</string> - <!-- no translation found for lock_to_app_start (6643342070839862795) --> - <skip /> - <!-- no translation found for lock_to_app_exit (8598219838213787430) --> - <skip /> - <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) --> - <skip /> + <string name="lock_to_app_start" msgid="6643342070839862795">"Η οθόνη καρφιτσώθηκε"</string> + <string name="lock_to_app_exit" msgid="8598219838213787430">"Η οθόνη ξεκαρφιτσώθηκε"</string> + <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"Να γίνεται ερώτηση για %1$s πριν από το ξεκαρφίτσωμα"</string> <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"Αριθμός PIN"</string> <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"μοτίβο ξεκλειδώματος"</string> <string name="lock_to_app_unlock_password" msgid="795224196583495868">"κωδικός πρόσβασης"</string> - <!-- no translation found for battery_saver_description (725676363406667978) --> - <skip /> - <!-- no translation found for downtime_condition_summary (8761776337475705749) --> - <skip /> + <string name="battery_saver_description" msgid="725676363406667978">"Για τη βελτίωση της διάρκειας ζωής της μπαταρίας, η λειτουργία εξοικονόμησης μπαταρίας μειώνει την απόδοση της συσκευής σας και περιορίζει τη δόνηση και την πλειονότητα των δεδομένων παρασκηνίου. Το ηλεκτρονικό ταχυδρομείου, η ανταλλαγή μηνυμάτων και άλλες εφαρμογές που βασίζονται στο συγχρονισμό ενδέχεται να μην ενημερώνονται, παρά μόνο εάν τις ανοίξετε.\n\nΗ λειτουργία εξοικονόμησης μπαταρίας απενεργοποιείται αυτόματα κατά τη φόρτιση της συσκευής σας."</string> + <string name="downtime_condition_summary" msgid="8761776337475705749">"Έως τη λήξη του νεκρού χρόνου σας στις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> </resources> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 3e2d93e..0d87540 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string> <string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Physical keyboard"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Select keyboard layout"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Touch to select a keyboard layout."</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 3e2d93e..0d87540 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string> <string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Choose keyboards"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Physical keyboard"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Select keyboard layout"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Touch to select a keyboard layout."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index d321412..d853a0f 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar la depuración por USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Cambiar el teclado"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un diseño de teclado."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index ccbb8d3..5782c9b 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para inhabilitar la depuración USB"</string> <string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un diseño de teclado."</string> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index a3820ee..a490e9c 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Puudutage USB-silumise keelamiseks."</string> <string name="select_input_method" msgid="8547250819326693584">"Klaviatuuri muutmine"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Vali klaviatuurid"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Füüsiline klaviatuur"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Riistvara"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Klaviatuuri paigutuse valimine"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Puudutage klaviatuuri paigutuse valimiseks."</string> diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index a82f4a3..f00e596 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB arazketa desgaitzeko, ukitu hau."</string> <string name="select_input_method" msgid="8547250819326693584">"Aldatu teklatua"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Aukeratu teklatuak"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teklatu fisikoa"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardwarea"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Hautatu teklatuaren diseinua"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Ukitu teklatuaren diseinua hautatzeko."</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index bd725ae..99f6c0d 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"برای غیرفعال کردن اشکال زدایی USB لمس کنید."</string> <string name="select_input_method" msgid="8547250819326693584">"تغییر صفحهکلید"</string> <string name="configure_input_methods" msgid="4769971288371946846">"انتخاب صفحهکلیدها"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحهکلید فیزیکی"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"سختافزار"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرحبندی صفحهکلید"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرحبندی صفحهکلید لمس کنید…"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 71e33e9..3b62f74 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Poista USB-vianetsintä käytöstä koskettamalla tätä."</string> <string name="select_input_method" msgid="8547250819326693584">"Vaihda näppäimistö"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Valitse näppäimistöt"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyysinen näppäimistö"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Laitteisto"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Valitse näppäimistöasettelu"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Kosketa ja valitse näppäimistöasettelu."</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 4a63f0e..298c64a 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Choisir les claviers"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Clavier physique"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Matériel"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Sélectionnez la disposition du clavier"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Appuyez ici pour sélectionner une disposition de clavier."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index d300946..77fe1f9 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Sélectionner des claviers"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Clavier physique"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Matériel"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Sélectionnez la disposition du clavier"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Appuyez ici pour sélectionner une disposition de clavier."</string> diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml index 622d3d0..f163c4e 100644 --- a/core/res/res/values-gl-rES/strings.xml +++ b/core/res/res/values-gl-rES/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar a depuración de erros de USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Seleccionar teclados"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Seleccionar deseño de teclado"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toca para seleccionar un deseño de teclado."</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 9662dda..720cc06 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करना अक्षम करने के लिए स्पर्श करें."</string> <string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदल सकता है"</string> <string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड चुनें"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"भौतिक कीबोर्ड"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"हार्डवेयर"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"कीबोर्ड लेआउट को चुनें"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"कीबोर्ड लेआउट का चयन करने के लिए स्पर्श करें."</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 4e434f4..3ab351b 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili rješavanje programske pogreške na USB-u."</string> <string name="select_input_method" msgid="8547250819326693584">"Promjena tipkovnice"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Odaberi tipkovnice"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizička tipkovnica"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardver"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Odaberite izgled tipkovnice"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dodirnite za odabir izgleda tipkovnice."</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index d38e841..c18fe3d 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Érintse meg az USB hibakeresés kikapcsolásához."</string> <string name="select_input_method" msgid="8547250819326693584">"Billentyűzet megváltoztatása"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Billentyűzetek kiválasztása"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizikai billentyűzet"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardver"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Válasszon billentyűzetkiosztást"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Érintse meg az egyik billentyűzetkiosztás kiválasztásához."</string> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index 69c0c60..49c1354 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Հպեք` USB կարգաբերումը կասեցնելու համար:"</string> <string name="select_input_method" msgid="8547250819326693584">"Փոխել ստեղնաշարը"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Ընտրել ստեղնաշար"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Ֆիզիկական ստեղնաշար"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Սարքաշար"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Ընտրեք ստեղնաշարի դիրքը"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Հպեք` ստեղնաշարի դիրքը ընտրելու համար:"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 465f9d4..e76cbbc 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk menonaktifkan debugging USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Ubah keyboard"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Pilih keyboard"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Keyboard fisik"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Perangkat Keras"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pilih tata letak keyboard"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Sentuh untuk memilih tata letak keyboard."</string> diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml index 716c789..c7e94dd 100644 --- a/core/res/res/values-is-rIS/strings.xml +++ b/core/res/res/values-is-rIS/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Snertu til að slökkva á USB-villuleit."</string> <string name="select_input_method" msgid="8547250819326693584">"Skipta um lyklaborð"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Velja lyklaborð"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Vélbúnaðarlyklaborð"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Vélbúnaður"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Veldu lyklaskipan"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Snertu til að velja lyklaskipan."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 13374b7..de7961b 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tocca per disattivare il debug USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Cambia tastiera"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Scegli tastiere"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Tastiera fisica"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Seleziona layout tastiera"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tocca per selezionare un layout di tastiera."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 01444be..d53028d 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"גע כדי להשבית את ניקוי הבאגים בהתקן ה-USB."</string> <string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string> <string name="configure_input_methods" msgid="4769971288371946846">"בחר מקלדות"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"מקלדת פיזית"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"חומרה"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"בחירת פריסת מקלדת"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"גע כדי לבחור פריסת מקלדת."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 09d51da..5666693 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効にします。"</string> <string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string> <string name="configure_input_methods" msgid="4769971288371946846">"キーボードの選択"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"物理キーボード"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ハードウェア"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"キーボードレイアウトの選択"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"タップしてキーボードレイアウトを選択してください。"</string> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index 9849d9b..b0b5e80 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"შეეხეთ, რათა შეწყვიტოთ USB-ის გამართვა."</string> <string name="select_input_method" msgid="8547250819326693584">"კლავიატურის შეცვლა"</string> <string name="configure_input_methods" msgid="4769971288371946846">"კლავიატურების არჩევა"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ფიზიკური კლავიატურა"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"მოწყობილობა"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"შეარჩიეთ კლავიატურის განლაგება."</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"კლავიატურის განლაგების შესარჩევად შეეხეთ."</string> diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml index 3c3d15b..03a42f2 100644 --- a/core/res/res/values-kk-rKZ/strings.xml +++ b/core/res/res/values-kk-rKZ/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB күйін келтіруді өшіру үшін түртіңіз."</string> <string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Пернетақталарды таңдау"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Қатты пернетақта"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Компьютерлік жабдық"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Пернетақта орналасуын таңдау"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Пернетақта орналасуын таңдау үшін түртіңіз."</string> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index f2eaf10..aeea46f 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -1354,7 +1354,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"ប៉ះ ដើម្បីបិទការកែកំហុសយូអេសប៊ី។"</string> <string name="select_input_method" msgid="8547250819326693584">"ប្ដូរក្ដារចុច"</string> <string name="configure_input_methods" msgid="4769971288371946846">"ជ្រើសក្ដារចុច"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ក្ដារចុចពិតប្រាកដ"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ផ្នែករឹង"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"ជ្រើសប្លង់ក្ដារចុច"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ប៉ះ ដើម្បីជ្រើសប្លង់ក្ដារចុច។"</string> diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml index 2e5fbee..2750032 100644 --- a/core/res/res/values-kn-rIN/strings.xml +++ b/core/res/res/values-kn-rIN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string> <string name="select_input_method" msgid="8547250819326693584">"ಕೀಬೋರ್ಡ್ ಬದಲಿಸಿ"</string> <string name="configure_input_methods" msgid="4769971288371946846">"ಕೀಬೋರ್ಡ್ಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ಹಾರ್ಡ್ವೇರ್"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಆಯ್ಕೆಮಾಡಿ"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಆಯ್ಕೆ ಮಾಡಲು ಸ್ಪರ್ಶಿಸಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 55ae682..2631902 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB 디버깅을 사용하지 않으려면 터치하세요."</string> <string name="select_input_method" msgid="8547250819326693584">"키보드 변경"</string> <string name="configure_input_methods" msgid="4769971288371946846">"키보드 선택"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"물리적 키보드"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"하드웨어"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"키보드 레이아웃 선택"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"터치하여 키보드 레이아웃을 선택합니다."</string> diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml index 2b66d13..4f14e95 100644 --- a/core/res/res/values-ky-rKG/strings.xml +++ b/core/res/res/values-ky-rKG/strings.xml @@ -1747,7 +1747,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB мүчүлүштүктөрдү жоюу мүмкүнчүлүгүн өчүрүү үчүн тийип коюңуз."</string> <string name="select_input_method" msgid="8547250819326693584">"Баскычтопту өзгөртүү"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Баскычтопторду тандаңыз"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Аппараттык тергич"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Аппараттык"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Тергичтин жайгашуусун тандоо"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Тергичтин жайгашуусун тандаш үчүн басыңыз."</string> diff --git a/core/res/res/values-land/dimens_material.xml b/core/res/res/values-land/dimens_material.xml index c8c95d7b..77719a6 100644 --- a/core/res/res/values-land/dimens_material.xml +++ b/core/res/res/values-land/dimens_material.xml @@ -19,5 +19,9 @@ <dimen name="action_bar_default_height_material">48dp</dimen> <!-- Default padding of an action bar. --> <dimen name="action_bar_default_padding_material">0dp</dimen> + <!-- Default text size for action bar title.--> + <dimen name="text_size_title_material_toolbar">14dp</dimen> + <!-- Default text size for action bar subtitle.--> + <dimen name="text_size_subtitle_material_toolbar">12dp</dimen> </resources> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index 7372528..d7e2b9b 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -716,10 +716,8 @@ <string name="permdesc_use_sip" msgid="2297804849860225257">"ອະນຸຍາດໃຫ້ແອັບຯສາມາດຮັບສາຍ ແລະໂທອອກຜ່ານ SIP ໄດ້"</string> <string name="permlab_bind_call_service" msgid="6724009726671246551">"ໂຕ້ຕອບກັບໜ້າຈໍການໂທ"</string> <string name="permdesc_bind_call_service" msgid="8732547662442572435">"ອະນຸຍາດໃຫ້ແອັບຯ ຄວບຄຸມເວລາ ແລະວິທີການທີ່ຜູ່ໃຊ້ເຫັນໜ້າຈໍການໂທໄດ້."</string> - <!-- no translation found for permlab_bind_connection_service (3557341439297014940) --> - <skip /> - <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) --> - <skip /> + <string name="permlab_bind_connection_service" msgid="3557341439297014940">"ສັ່ງບໍລິການໂທລະສັບ"</string> + <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"ອະນຸຍາດໃຫ້ແອັບຯສັ່ງບໍລິການໂທລະສັບເພື່ອໂທຫຼືຮັບສາຍໄດ້."</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ອ່ານປະຫວັດການນຳໃຊ້ເຄືອຂ່າຍ"</string> <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານປະຫວັດການນຳໃຊ້ເຄືອຂ່າຍຂອງແອັບຯ ແລະເຄືອຂ່າຍໃດນຶ່ງ."</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ຈັດການນະໂຍບາຍເຄືອຂ່າຍ"</string> @@ -1352,7 +1350,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"ແຕະເພື່ອປິດການດີບັ໊ກຜ່ານ USB."</string> <string name="select_input_method" msgid="8547250819326693584">"ປ່ຽນແປ້ນພິມ"</string> <string name="configure_input_methods" msgid="4769971288371946846">"ເລືອກແປ້ນພິມ"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ແປ້ນພິມແທ້"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ຮາດແວ"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"ເລືອກຮູບແບບແປ້ນພິມ"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ກົດເພື່ອເລືອກຮູບແບບແປ້ນພິມ."</string> @@ -1764,30 +1763,20 @@ <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ຖືກເລືອກແລ້ວ"</string> <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string> <string name="managed_profile_label_badge" msgid="2355652472854327647">"ບ່ອນເຮັດວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string> - <!-- no translation found for lock_to_app_toast (1230563865743799321) --> - <skip /> - <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) --> - <skip /> - <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) --> - <skip /> - <!-- no translation found for lock_to_app_title (1682643873107812874) --> - <skip /> - <!-- no translation found for lock_to_app_description (9076084599283282800) --> - <skip /> - <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) --> - <skip /> + <string name="lock_to_app_toast" msgid="1230563865743799321">"ເພື່ອຍົກເລີກການປັກໝຸດໜ້າຈໍນີ້, ໃຫ້ແຕະປຸ່ມກັບຄືນແລະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້ພ້ອມກັນ."</string> + <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"ເພື່ອຍົກເລີກການປັກໝຸດໜ້າຈໍນີ້, ໃຫ້ແຕະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້."</string> + <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"ໜ້າຈໍຖືກປັກໝຸດໄວ້. ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຍົກເລີກການປັກໝຸດໄດ້."</string> + <string name="lock_to_app_title" msgid="1682643873107812874">"ໃຊ້ການປັກໝຸດໜ້າຈໍບໍ່?"</string> + <string name="lock_to_app_description" msgid="9076084599283282800">"ການປັກໝຸດໜ້າຈໍຈະລັອກໜ້າຈໍໄວ້ທີ່ມຸມມອງໃດນຶ່ງ.\n\nເພື່ອອອກ, ໃຫ້ແຕະປຸ່ມກັບຄືນແລະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້ພ້ອມກັນ."</string> + <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"ການປັກໝຸດໜ້າຈໍຈະລັອກໜ້າຈໍໄວ້ທີ່ມຸມມອງໃດນຶ່ງ.\n\nເພື່ອອອກ, ໃຫ້ແຕະປຸ່ມແອັບຯທີ່ຫາກໍໃຊ້ຄ້າງໄວ້."</string> <string name="lock_to_app_negative" msgid="2259143719362732728">"ບໍ່, ຂອບໃຈ"</string> <string name="lock_to_app_positive" msgid="7085139175671313864">"ເລີ່ມ"</string> - <!-- no translation found for lock_to_app_start (6643342070839862795) --> - <skip /> - <!-- no translation found for lock_to_app_exit (8598219838213787430) --> - <skip /> - <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) --> - <skip /> + <string name="lock_to_app_start" msgid="6643342070839862795">"ປັກໝຸດໜ້າຈໍແລ້ວ"</string> + <string name="lock_to_app_exit" msgid="8598219838213787430">"ຍົກເລີກການປັກໝຸນຫນ້າຈໍແລ້ວ"</string> + <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"ຖາມ %1$s ກ່ອນຍົກເລີກການປັກໝຸດ"</string> <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string> <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"ຮູບແບບປົດລັອກ"</string> <string name="lock_to_app_unlock_password" msgid="795224196583495868">"ລະຫັດຜ່ານ"</string> <string name="battery_saver_description" msgid="725676363406667978">"ເພື່ອຊ່ວຍປັບປຸງອາຍຸແບັດເຕີຣີ, ໂຕປະຢັດແບັດເຕີຣີຈະຫຼຸດປະສິດທິພາບຂອງອຸປະກອນຂອງທ່ານລົງ ແລະຈຳກັດການສັ່ນເຕືອນ ຮວມທັງຂໍ້ມູນພື້ນຫຼັງສ່ວນໃຫຍ່. ອີເມວ, ການສົ່ງຂໍ້ຄວາມ ແລະແອັບຯອື່ນໆທີ່ອີງອາໃສການຊິ້ງຂໍ້ມູນອາດບໍ່ມີການອັບເດດຈົນກວ່າທ່ານຈະເປີດແອັບຯເຫຼົ່ານັ້ນ.\n\nໂຕປະຢັດແບັດເຕີຣີຈະປິດໂຕເອງອັດຕະໂນມັດໃນເວລາທີ່ອຸປະກອນຂອງທ່ານສາກໄຟຢູ່"</string> - <!-- no translation found for downtime_condition_summary (8761776337475705749) --> - <skip /> + <string name="downtime_condition_summary" msgid="8761776337475705749">"ຈົນກວ່າດາວທາມຂອງທ່ານຈະສິ້ນສຸດທີ່ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> </resources> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 5d65ce3..058a5fc 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Palieskite, kad neleistumėte USB derinimo."</string> <string name="select_input_method" msgid="8547250819326693584">"Klaviatūros keitimas"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Pasirinkti klaviatūras"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizinė klaviatūra"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Apar. įr."</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pasirinkite klaviatūros išdėstymą"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Palieskite, kad pasirinktumėte klaviatūros išdėstymą."</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 7c07f92..de566b8 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Pieskarieties, lai atspējotu USB atkļūdošanu."</string> <string name="select_input_method" msgid="8547250819326693584">"Tastatūras maiņa"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Izvēlēties tastatūru"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fiziskā tastatūra"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Aparatūra"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Atlasiet tastatūras izkārtojumu"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Pieskarieties, lai atlasītu tastatūras izkārtojumu."</string> diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml index c53226a..4e58f49 100644 --- a/core/res/res/values-mk-rMK/strings.xml +++ b/core/res/res/values-mk-rMK/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Допрете за да се оневозможи отстранувањето грешки преку USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Измени тастатура"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Избери тастатури"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Физичка тастатура"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Хардвер"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избери изглед на тастатура"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Допри за да избереш изглед на тастатура."</string> diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml index 733a508..4679b27 100644 --- a/core/res/res/values-ml-rIN/strings.xml +++ b/core/res/res/values-ml-rIN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ഡീബഗ്ഗിംഗ് പ്രവർത്തനരഹിതമാക്കാൻ സ്പർശിക്കുക."</string> <string name="select_input_method" msgid="8547250819326693584">"കീബോർട്ട് മാറ്റുക"</string> <string name="configure_input_methods" msgid="4769971288371946846">"കീബോർഡുകൾ തിരഞ്ഞെടുക്കുക"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ഭൗതിക കീബോർഡ്"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ഹാർഡ്വെയർ"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ഒരു കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കാൻ സ്പർശിക്കുക."</string> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 0e90ada..9c0b211 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -716,10 +716,8 @@ <string name="permdesc_use_sip" msgid="2297804849860225257">"Апп-д SIP дуудлага хийх болон хүлээн авахыг зөвшөөрөх."</string> <string name="permlab_bind_call_service" msgid="6724009726671246551">"дуудлагын дэлгэцтэй харьцах"</string> <string name="permdesc_bind_call_service" msgid="8732547662442572435">"Апп-д дуудлагын дэлгэцийг хэрэглэгчид хэзээ хэрхэн харуулахыг удирдахыг зөвшөөрнө."</string> - <!-- no translation found for permlab_bind_connection_service (3557341439297014940) --> - <skip /> - <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) --> - <skip /> + <string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефоны үйлчилгээтэй харилцах"</string> + <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Апп-д телефон үйлчилгээтэй харилцаж дуудлага хийх/авахыг зөвшөөрнө."</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"сүлжээний ашиглалтын түүхийг унших"</string> <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Апп нь тусгай сүлжээ болон апп-н сүлжээ ашиглалтын түүхийг унших боломжтой."</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"сүлжээний бодлогыг удирдах"</string> @@ -1352,7 +1350,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB дебаг хийхийг идэвхгүй болгох бол хүрнэ үү."</string> <string name="select_input_method" msgid="8547250819326693584">"Гарыг өөрчлөх"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Гар сонгох"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Бодит гар"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Хардвер"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Гарын схемийг сонгох"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Гарын схемийг сонгох бол хүрнэ үү."</string> @@ -1764,30 +1763,20 @@ <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> сонгогдсон"</string> <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string> <string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string> - <!-- no translation found for lock_to_app_toast (1230563865743799321) --> - <skip /> - <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) --> - <skip /> - <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) --> - <skip /> - <!-- no translation found for lock_to_app_title (1682643873107812874) --> - <skip /> - <!-- no translation found for lock_to_app_description (9076084599283282800) --> - <skip /> - <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) --> - <skip /> + <string name="lock_to_app_toast" msgid="1230563865743799321">"Дэлгэцийг суллахын тулд Буцах болон Саяхных-г зэрэг дараад барина уу."</string> + <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"Дэлгэцийг суллахын тулд Саяхных-д хүрээд барина уу."</string> + <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"Дэлгэцийг тогтоосон. Дэлгэц суллахыг таны байгууллага зөвшөөрөөгүй."</string> + <string name="lock_to_app_title" msgid="1682643873107812874">"Дэлгэц тогтоогчийг ашиглах уу?"</string> + <string name="lock_to_app_description" msgid="9076084599283282800">"Дэлгэц тогтоогч нь дэлгэцийг нэг янзаар түгжинэ.\n\nГарахын тулд Буцах болон Саяхных-д зэрэг хүрээд барина уу."</string> + <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"Дэлгэц тогтоогч нь дэлгэцийг нэг янзаар түгжинэ.\n\nГарахын тулд Буцах болон Саяхных-д зэрэг хүрээд барина уу."</string> <string name="lock_to_app_negative" msgid="2259143719362732728">"ҮГҮЙ"</string> <string name="lock_to_app_positive" msgid="7085139175671313864">"ЭХЛҮҮЛЭХ"</string> - <!-- no translation found for lock_to_app_start (6643342070839862795) --> - <skip /> - <!-- no translation found for lock_to_app_exit (8598219838213787430) --> - <skip /> - <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) --> - <skip /> + <string name="lock_to_app_start" msgid="6643342070839862795">"Дэлгэцийг тогтоосон"</string> + <string name="lock_to_app_exit" msgid="8598219838213787430">"Дэлгэцийг сулласан"</string> + <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"Суллахаас өмнө %1$s хүснэ үү"</string> <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string> <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"тайлах хээ"</string> <string name="lock_to_app_unlock_password" msgid="795224196583495868">"нууц үг"</string> <string name="battery_saver_description" msgid="725676363406667978">"Батерейны ашиглалтыг уртасгахын тулд батерей хэмнэгч нь таны төхөөрөмжийн ажиллагааг бууруулж, чичрэлт болон далд датаны ихэнх хувийг хязгаарлана. Имэйл, зурвас гэх мэт синк хийгддэг бусад апп-ууд таныг нээхээс нааш шинэчлэгдэхгүй байж болно.\n\nТаныг төхөөрөмжөө цэнэглэх үед батерей хэмнэгч автоматаар унтарна."</string> - <!-- no translation found for downtime_condition_summary (8761776337475705749) --> - <skip /> + <string name="downtime_condition_summary" msgid="8761776337475705749">"Таны уйтгартай байдал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-д дуусах хүртэл"</string> </resources> diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml index cde4dd1..7715a01 100644 --- a/core/res/res/values-mr-rIN/strings.xml +++ b/core/res/res/values-mr-rIN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करणे अक्षम करण्यासाठी स्पर्श करा."</string> <string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदला"</string> <string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड निवडा"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"वास्तविक कीबोर्ड"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"हार्डवेअर"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"कीबोर्ड लेआउट निवडा"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"कीबोर्ड लेआउट निवडण्यासाठी स्पर्श करा."</string> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 0bf4ca6..ce4bb30 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk melumpuhkan penyahpepijatan USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Tukar papan kekunci"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Pilih papan kekunci"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Papan kekunci fizikal"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Perkakasan"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pilih susun atur papan kekunci"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Sentuh untuk memilih susun atur papan kekunci."</string> diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml index 8fdeedb..5066ea6 100644 --- a/core/res/res/values-my-rMM/strings.xml +++ b/core/res/res/values-my-rMM/strings.xml @@ -716,10 +716,8 @@ <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ခေါ်ဆိုမှုများ ခေါ်ရန်နှင့် လက်ခံနိုင်ရန် app ကို ခွင့်ပြုပါ။"</string> <string name="permlab_bind_call_service" msgid="6724009726671246551">"တခါတည်း ခေါ်ဆိုနိုင်သော ဖန်သားပြင်နဲ့ ဆက်ဆံရန်"</string> <string name="permdesc_bind_call_service" msgid="8732547662442572435">"ဖုန်းကိုင်သူ ဘယ်အချိန် ဘယ်လိုမှာ အပလီကေးရှင်းအတွင်း ဖုန်းခေါ်မှုကို မြင်ရခြင်းအား ထိန်းချုပ်ခွင့်ပေးခြင်း"</string> - <!-- no translation found for permlab_bind_connection_service (3557341439297014940) --> - <skip /> - <!-- no translation found for permdesc_bind_connection_service (4008754499822478114) --> - <skip /> + <string name="permlab_bind_connection_service" msgid="3557341439297014940">"တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှု"</string> + <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"appအား ခေါ်ဆိုမှုများ လုပ်ခြင်း/လက်ခံခြင်း ပြုလုပ်နိုင်ရန် တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှုကို ခွင့်ပြုသည်။"</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ရာဇဝင်အလိုက် ကွန်ယက်သုံစွဲမှုအား ဖတ်ခြင်း"</string> <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"appအား အထူး ကွန်ရက်များ နှင့် appများ အတွက် ကွန်ရက် အသုံးပြုမှု မှတ်တမ်းကို ဖတ်ကြားခွင့် ပြုသည်။"</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ကွန်ယက်မူဝါဒအား စီမံခြင်း"</string> @@ -1352,7 +1350,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ဒီဘာဂင် ပိတ်ရန် ထိပါ။"</string> <string name="select_input_method" msgid="8547250819326693584">"ကီးဘုတ် ပြောင်းလဲရန်"</string> <string name="configure_input_methods" msgid="4769971288371946846">"ကီးဘုတ်များကို ရွေးရန်"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"ခလုတ်ပါဝင်သော ကီးဘုတ်"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ဟာ့ဒ်ဝဲ"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"လက်ကွက် အပြင်အဆင်ရွေးရန်"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"လက်ကွက် အပြင်အဆင်ရွေးရန် တို့ထိပါ"</string> @@ -1481,7 +1480,7 @@ <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>မှ တည်နေရာအား တောင်းခံသည်"</string> <string name="gpsNotifTitle" msgid="5446858717157416839">"တည်နေရာအား တောင်းခံသည်"</string> <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)မှတောင်းခံသည်"</string> - <string name="gpsVerifYes" msgid="2346566072867213563">"ဟုတ်သည်"</string> + <string name="gpsVerifYes" msgid="2346566072867213563">"ဟုတ်ကဲ့"</string> <string name="gpsVerifNo" msgid="1146564937346454865">"မဟုတ်ပါ"</string> <string name="sync_too_many_deletes" msgid="5296321850662746890">"ပယ်ဖျက်မည့်ကန့်သတ်နှုန်းကျော်လွန်သည်"</string> <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>၊ account <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> အတွက် စုစုပေါင်း <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> အရာဖျက်ထားပါသည်။ သင်ဘာလုပ်ချင်ပါလဲ?"</string> @@ -1764,31 +1763,20 @@ <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ခုရွေးချယ်ထားပြီး"</string> <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ကို ဖျက်ပြီးပါပြီ"</string> <string name="managed_profile_label_badge" msgid="2355652472854327647">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string> - <!-- no translation found for lock_to_app_toast (1230563865743799321) --> - <skip /> - <!-- no translation found for lock_to_app_toast_accessible (3340628918851844044) --> - <skip /> - <!-- no translation found for lock_to_app_toast_locked (8739004135132606329) --> - <skip /> - <!-- no translation found for lock_to_app_title (1682643873107812874) --> - <skip /> - <!-- no translation found for lock_to_app_description (9076084599283282800) --> - <skip /> - <!-- no translation found for lock_to_app_description_accessible (2132076937479670601) --> - <skip /> + <string name="lock_to_app_toast" msgid="1230563865743799321">"ဒီမျက်နှာပြင် ပင်ထိုးထားမှုကို ဖြုတ်ရန် နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို တစ်ချိန်တည်း ထိလျက် ကိုင်ထားပါ။"</string> + <string name="lock_to_app_toast_accessible" msgid="3340628918851844044">"ဒီမျက်နှာပြင် ပင်ထိုးထားမှုကို ဖြုတ်ရန် နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို ထိလျက် ကိုင်ထားပါ။."</string> + <string name="lock_to_app_toast_locked" msgid="8739004135132606329">"မျက်နှာပြင်ကို ပင်ထိုးထားသည်။ ပင်ထိုးထားမှု ဖြုတ်ခြင်းကို သင့် အဖွဲ့အစည်းက ခွင့် မပြုပါ။"</string> + <string name="lock_to_app_title" msgid="1682643873107812874">"မျက်နှာပြင် ပင်ထိုးမှုကို သုံးမလား?"</string> + <string name="lock_to_app_description" msgid="9076084599283282800">"မျက်နှာပြင်ကို ပင်ထိုးလိုက်ခြင်းက ပြကွက်ကို တစ်ခုတည်းသော မြင်းကွင်းသို့ သော့ပိတ်ထားမည်။ \n\nထွက်လိုက်ရန်၊ နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို တစ်ချိန်တည်း ထိလျက် ကိုင်ထားပါ။"</string> + <string name="lock_to_app_description_accessible" msgid="2132076937479670601">"မျက်နှာပြင်ကို ပင်ထိုးလိုက်ခြင်းက ပြကွက်ကို တစ်ခုတည်းသော မြင်းကွင်းသို့ သော့ပိတ်ထားမည်။ \n\nထွက်လိုက်ရန်၊ နောက် နှင့် မကြာမီတုန်းက ခလုတ်များကို ထိလျက် ကိုင်ထားပါ။"</string> <string name="lock_to_app_negative" msgid="2259143719362732728">"မလို၊ ကျေးဇူးပါပဲ"</string> <string name="lock_to_app_positive" msgid="7085139175671313864">"စတင်ရန်"</string> - <!-- no translation found for lock_to_app_start (6643342070839862795) --> - <skip /> - <!-- no translation found for lock_to_app_exit (8598219838213787430) --> - <skip /> - <!-- no translation found for lock_to_app_use_screen_lock (5732663305876339596) --> - <skip /> + <string name="lock_to_app_start" msgid="6643342070839862795">"မျက်နှာပြင်ကို ပင်ထိုးထား"</string> + <string name="lock_to_app_exit" msgid="8598219838213787430">"မျက်နှာပြင် ပင်ထိုးမှု ဖြတ်လိုက်ပြီ"</string> + <string name="lock_to_app_use_screen_lock" msgid="5732663305876339596">"ပင်ထိုးမှုကို မဖြုတ်မီမှာ %1$sကို မေးကြည့်ပါ"</string> <string name="lock_to_app_unlock_pin" msgid="7908385370846820001">"PIN"</string> <string name="lock_to_app_unlock_pattern" msgid="7763071104790758405">"သော့ဖွင့် ပုံစံဒီဇိုင်း"</string> <string name="lock_to_app_unlock_password" msgid="795224196583495868">"စကားဝှက်"</string> - <!-- no translation found for battery_saver_description (725676363406667978) --> - <skip /> - <!-- no translation found for downtime_condition_summary (8761776337475705749) --> - <skip /> + <string name="battery_saver_description" msgid="725676363406667978">"ဘက်ထရီ သက်တမ်းကို တိုးပေးရန်၊ ဘက်ထရီ ချွေတာသူက သင့်ကိရိယာ၏ လုပ်ကိုင်မှုများကို လျှော့ချလျက် တုန်ခါမှု နှင့် နောက်ခံ ဒေတာ အများစုကို ကန့်သတ်ပေးသည်။ စင့်ကို အားကိုးကြရသည့် အီးမေးလ်၊ စာပို့စနစ်၊ နှင့် အခြား appများသည် သင်က ၎င်းတို့ကို မဖွင့်မချင်း မွမ်းမံဖြစ်မည် မဟုတ်ပါ။ \n\nသင်၏ ကိရိယာက အားသွင်း နေချိန်မှာ ဘက်ထရီ ချွေတာသူကို အလိုအလျောက် ပိတ်ထားမည်။"</string> + <string name="downtime_condition_summary" msgid="8761776337475705749">"သင်၏ စက်ရပ်ချိန် <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> မှာ ပြီးဆုံးသည့် အထိ။"</string> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 0073ad1..db5c292 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Trykk for å deaktivere USB-feilsøking."</string> <string name="select_input_method" msgid="8547250819326693584">"Endre tastatur"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Velg tastatur"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysisk tastatur"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Maskinvare"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Velg tastaturoppsett"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Trykk for å velge et tastaturoppsett"</string> diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml index eb9c066..cee862a 100644 --- a/core/res/res/values-ne-rNP/strings.xml +++ b/core/res/res/values-ne-rNP/strings.xml @@ -1360,7 +1360,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डिबग गर्ने असक्षम पार्न छुनुहोस्।"</string> <string name="select_input_method" msgid="8547250819326693584">"कुञ्जीपाटी परिवर्तन गर्नुहोस्"</string> <string name="configure_input_methods" msgid="4769971288371946846">"कीबोर्ड छान्नुहोस्"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"भौतिक किबोर्ड"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"हार्डवेयर"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"किबोर्ड रूपरेखा चयन गर्नुहोस्"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"किबोर्ड रूपरेखा चयन गर्न टच गर्नुहोस्।"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 5b0c5f4..dc6c38c 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tik om USB-foutopsporing uit te schakelen."</string> <string name="select_input_method" msgid="8547250819326693584">"Toetsenbord wijzigen"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Toetsenborden kiezen"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysiek toetsenbord"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Toetsenbordindeling selecteren"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tik om een toetsenbordindeling te selecteren."</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 65616c2..505bd11 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknij, aby wyłączyć debugowanie USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Zmień klawiaturę"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Wybierz klawiatury"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Klawiatura fizyczna"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Sprzęt"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Wybierz układ klawiatury"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Kliknij, by wybrać układ klawiatury."</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index b54d6c0..7bcbd1f 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecionar esquema de teclado"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toque para selecionar um esquema de teclado."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 5c3e589..9674c78 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Escolher teclados"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Teclado físico"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecione o layout de teclado"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Toque para selecionar um layout de teclado."</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 325c0a9..74c9084 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1354,7 +1354,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeţi pentru a dezactiva depanarea USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Alegeți tastaturi"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Tastatură fizică"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selectaţi aspectul tastaturii"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Atingeţi pentru a selecta un aspect de tastatură."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 632bdda..d4872bb 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Нажмите, чтобы отключить отладку по USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Выбор раскладки"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Выбрать раскладку"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Физическая клавиатура"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Аппаратура"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Выберите раскладку клавиатуры"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Нажмите, чтобы выбрать раскладку клавиатуры."</string> diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml index 8db3349..230fbe7 100644 --- a/core/res/res/values-si-rLK/strings.xml +++ b/core/res/res/values-si-rLK/strings.xml @@ -1355,7 +1355,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB නිදොස්කරණය අබල කිරීමට ස්පර්ශ කරන්න."</string> <string name="select_input_method" msgid="8547250819326693584">"යතුරු පුවරු වෙනස් කිරීම"</string> <string name="configure_input_methods" msgid="4769971288371946846">"යතුරු පුවරු තෝරන්න"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"භෞතික යතුරු පුවරුව"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"දෘඨාංග"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"යතුරු පුවරුවට පිරිසැලැස්ම තෝරන්න"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"යතුරු පුවරුවට පිරිසැලැස්මක් තේරීමට ස්පර්ශ කරන්න."</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index e561d9b..f37e911 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknutím zakážete ladenie USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Zmeniť klávesnicu"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Vybrať klávesnice"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fyzická klávesnica"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardvér"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Zvoľte rozloženie klávesnice"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dotykom zvoľte rozloženie klávesnice."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 462dc19..a9e6011 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotaknite se, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Sprememba tipkovnice"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Izbira tipkovnic"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fizična tipkovnica"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Strojna oprema"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Izberite razporeditev tipkovnice"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Dotaknite se, da izberete razporeditev tipkovnice"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index c11e1ff..7e139c7 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string> <string name="select_input_method" msgid="8547250819326693584">"Промените тастатуру"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Изаберите тастатуре"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Физичка тастатура"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Хардвер"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избор распореда тастатуре"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Додирните да бисте изабрали распоред тастатуре."</string> @@ -1448,7 +1449,7 @@ <string name="submit" msgid="1602335572089911941">"Пошаљи"</string> <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Режим рада у аутомобилу је омогућен"</string> <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Додирните да бисте изашли из режима рада у аутомобилу."</string> - <string name="tethered_notification_title" msgid="3146694234398202601">"Активно повезивање са Интернетом преко мобилног уређаја или врућа тачка"</string> + <string name="tethered_notification_title" msgid="3146694234398202601">"Активно повезивање са интернетом преко мобилног уређаја или врућа тачка"</string> <string name="tethered_notification_message" msgid="6857031760103062982">"Додирните да бисте подесили."</string> <string name="back_button_label" msgid="2300470004503343439">"Назад"</string> <string name="next_button_label" msgid="1080555104677992408">"Next"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 9115c06..81625e7 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryck om du vill inaktivera USB-felsökning."</string> <string name="select_input_method" msgid="8547250819326693584">"Byt tangentbord"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Välj tangentbord"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fysiskt tangentbord"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Maskinvara"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Välj en tangentbordslayout"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Välj en tangentbordslayout genom att trycka."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 177730c..be1e0e6 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili uzime utatuaji wa USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Badilisha kibodi"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Chagua kibodi"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Kibodi halisi"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Maunzi"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Teua mpangilio wa kibodi"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Gusa ili kuchagua mpangilio wa kibodi."</string> diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml index a72e813..14a2dfc 100644 --- a/core/res/res/values-ta-rIN/strings.xml +++ b/core/res/res/values-ta-rIN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB பிழைத்திருத்தத்தை முடக்க, தொடவும்."</string> <string name="select_input_method" msgid="8547250819326693584">"விசைப்பலகையை மாற்று"</string> <string name="configure_input_methods" msgid="4769971288371946846">"விசைப்பலகைகளைத் தேர்வுசெய்க"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"கைமுறை விசைப்பலகை"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"வன்பொருள்"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"விசைப்பலகைத் தளவமைப்பைத் தேர்ந்தெடுக்கவும்"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"விசைப்பலகைத் தளவமைப்பைத் தேர்ந்தெடுக்க தொடவும்."</string> diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml index e7e24f7..9af8b76 100644 --- a/core/res/res/values-te-rIN/strings.xml +++ b/core/res/res/values-te-rIN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB డీబగ్గింగ్ను నిలిపివేయడానికి తాకండి."</string> <string name="select_input_method" msgid="8547250819326693584">"కీబోర్డ్ను మార్చు"</string> <string name="configure_input_methods" msgid="4769971288371946846">"కీబోర్డ్లను ఎంచుకోండి"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"భౌతిక కీబోర్డ్"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"హార్డ్వేర్"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"కీబోర్డ్ లేఅవుట్ను ఎంచుకోండి"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"కీబోర్డ్ లేఅవుట్ను ఎంచుకోవడానికి తాకండి."</string> diff --git a/core/res/res/values-television/styles.xml b/core/res/res/values-television/styles.xml new file mode 100644 index 0000000..4c0562f --- /dev/null +++ b/core/res/res/values-television/styles.xml @@ -0,0 +1,22 @@ +<!-- 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. +--> + +<resources> + <style name="Lighting"> + <item name="lightY">-300dp</item> + <item name="ambientShadowAlpha">0.4</item> + <item name="spotShadowAlpha">0.4</item> + </style> +</resources> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index b4a5fbe..87dbb13 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"แตะเพื่อปิดใช้งานการแก้ไขข้อบกพร่องของ USB"</string> <string name="select_input_method" msgid="8547250819326693584">"เปลี่ยนแป้นพิมพ์"</string> <string name="configure_input_methods" msgid="4769971288371946846">"เลือกแป้นพิมพ์"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"แป้นพิมพ์บนเครื่อง"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ฮาร์ดแวร์"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"เลือกรูปแบบแป้นพิมพ์"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"แตะเพื่อเลือกรูปแบบแป้นพิมพ์"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index bdb5172..8dd86b3 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Pindutin upang huwag paganahin ang pag-debug ng USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Baguhin ang keyboard"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Piliin ang mga keyboard"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Aktwal na keyboard"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pumili ng layout ng keyboard"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Pindutin upang pumili ng layout ng keyboard."</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 8f32ec5..7f80ea1 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string> <string name="select_input_method" msgid="8547250819326693584">"Klavyeyi değiştirin"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Klavyeleri seç"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Fiziksel klavye"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Donanım"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Klavye düzeni seçin"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Bir klavye düzeni seçmek için dokunun."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index f7583d6..dd716b0 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Торкніться, щоб вимкнути налагодження USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Змінити клавіатуру"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Вибрати клавіатури"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Фізична клавіатура"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Обладнання"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Виберіть розкладку клавіатури"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Торкніться, щоб вибрати розкладку клавіатури."</string> diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml index 99534fd..940ea9f 100644 --- a/core/res/res/values-ur-rPK/strings.xml +++ b/core/res/res/values-ur-rPK/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ڈیبگنگ کو غیر فعال کرنے کیلئے ٹچ کریں۔"</string> <string name="select_input_method" msgid="8547250819326693584">"کی بورڈ تبدیل کریں"</string> <string name="configure_input_methods" msgid="4769971288371946846">"کی بورڈز منتخب کریں"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"طبعی کی بورڈ"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"ہارڈ ویئر"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"کی بورڈ کا خاکہ منتخب کریں"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ایک کی بورڈ کا خاکہ منتخب کرنے کیلئے چھوئیں۔"</string> diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml index 206b2fc5..136e92c 100644 --- a/core/res/res/values-uz-rUZ/strings.xml +++ b/core/res/res/values-uz-rUZ/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB orqali sozlashni o‘chirib qo‘yish uchun bosing."</string> <string name="select_input_method" msgid="8547250819326693584">"Klaviaturani o‘zgartirish"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Klaviaturani tanlash"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Tashqi tugmatag"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Qurilma"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Tugmalar tartibini tanlash"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Tugmalar tartibini tanlash uchun bosing."</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 7428d89..e6fb44e 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Chạm để vô hiệu hóa gỡ lỗi USB."</string> <string name="select_input_method" msgid="8547250819326693584">"Thay đổi bàn phím"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Chọn bàn phím"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Bàn phím thực"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"Phần cứng"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Chọn bố cục bàn phím"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Chạm để chọn bố cục bàn phím."</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 557f709..3e69115 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"触摸可停用USB调试。"</string> <string name="select_input_method" msgid="8547250819326693584">"更改键盘"</string> <string name="configure_input_methods" msgid="4769971288371946846">"选择键盘"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"物理键盘"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"硬件"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"选择键盘布局"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"触摸可选择键盘布局。"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 1dfcad3..2879033 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string> <string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string> <string name="configure_input_methods" msgid="4769971288371946846">"選擇鍵盤"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"實體鍵盤"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"硬件"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"選取鍵盤配置"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"輕觸即可選取鍵盤配置。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index ec5a424..a8a736a 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string> <string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string> <string name="configure_input_methods" msgid="4769971288371946846">"選擇鍵盤"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"實體鍵盤"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"硬體"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"選取鍵盤配置"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"輕觸即可選取鍵盤配置。"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 2c461d2..16ac1d0 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1352,7 +1352,8 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Thinta ukwenza ukuthi ukudibhaga kwe-USB kungasebenzi."</string> <string name="select_input_method" msgid="8547250819326693584">"Shintsha ikhibhodi"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Khetha amakhibhodi"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"Ukwakheka kwekhibhodi"</string> + <!-- no translation found for show_ime (9157568568695230830) --> + <skip /> <string name="hardware" msgid="7517821086888990278">"I-Hardware"</string> <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Khetha isendlalelo sekhibhodi"</string> <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"Thinta ukuze ukhethe isendlalelo sekhibhodi."</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 3524636..cc8d7cf 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -6930,8 +6930,8 @@ <attr name="searchKeyphraseId" format="integer" /> <!-- The actual keyphrase/hint text, or empty if not keyphrase dependent. @hide @SystemApi --> <attr name="searchKeyphrase" format="string" /> - <!-- A comma separated list of java locales that are supported for this keyphrase, - or empty if not locale dependent. @hide @SystemApi --> + <!-- A comma separated list of BCP-47 language tag for locales that are supported + for this keyphrase, or empty if not locale dependent. @hide @SystemApi --> <attr name="searchKeyphraseSupportedLocales" format="string" /> <!-- Flags for supported recognition modes. @hide @SystemApi --> <attr name="searchKeyphraseRecognitionFlags"> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index df7268f..4f0757c 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -673,6 +673,37 @@ --> <integer name="config_doubleTapOnHomeBehavior">0</integer> + <!-- Minimum screen brightness setting allowed by the power manager. + The user is forbidden from setting the brightness below this level. --> + <integer name="config_screenBrightnessSettingMinimum">10</integer> + + <!-- Maximum screen brightness allowed by the power manager. + The user is forbidden from setting the brightness above this level. --> + <integer name="config_screenBrightnessSettingMaximum">255</integer> + + <!-- Default screen brightness setting. + Must be in the range specified by minimum and maximum. --> + <integer name="config_screenBrightnessSettingDefault">102</integer> + + <!-- Screen brightness used to dim the screen while dozing in a very low power state. + May be less than the minimum allowed brightness setting + that can be set by the user. --> + <integer name="config_screenBrightnessDoze">1</integer> + + <!-- Screen brightness used to dim the screen when the user activity + timeout expires. May be less than the minimum allowed brightness setting + that can be set by the user. --> + <integer name="config_screenBrightnessDim">10</integer> + + <!-- Minimum allowable screen brightness to use in a very dark room. + This value sets the floor for the darkest possible auto-brightness + adjustment. It is expected to be somewhat less than the first entry in + config_autoBrightnessLcdBacklightValues so as to allow the user to have + some range of adjustment to dim the screen further than usual in very + dark rooms. The contents of the screen must still be clearly visible + in darkness (although they may not be visible in a bright room). --> + <integer name="config_screenBrightnessDark">1</integer> + <!-- Array of light sensor LUX values to define our levels for auto backlight brightness support. The N entries of this array define N + 1 control points as follows: (1-based arrays) @@ -696,28 +727,6 @@ <integer-array name="config_autoBrightnessLevels"> </integer-array> - <!-- Minimum screen brightness setting allowed by the power manager. - The user is forbidden from setting the brightness below this level. --> - <integer name="config_screenBrightnessSettingMinimum">10</integer> - - <!-- Maximum screen brightness allowed by the power manager. - The user is forbidden from setting the brightness above this level. --> - <integer name="config_screenBrightnessSettingMaximum">255</integer> - - <!-- Default screen brightness setting. - Must be in the range specified by minimum and maximum. --> - <integer name="config_screenBrightnessSettingDefault">102</integer> - - <!-- Screen brightness used to dim the screen while dozing in a very low power state. - May be less than the minimum allowed brightness setting - that can be set by the user. --> - <integer name="config_screenBrightnessDoze">1</integer> - - <!-- Screen brightness used to dim the screen when the user activity - timeout expires. May be less than the minimum allowed brightness setting - that can be set by the user. --> - <integer name="config_screenBrightnessDim">10</integer> - <!-- Array of output values for LCD backlight corresponding to the LUX values in the config_autoBrightnessLevels array. This array should have size one greater than the size of the config_autoBrightnessLevels array. @@ -1378,6 +1387,14 @@ <string-array name="config_mobile_tcp_buffers"> </string-array> + <!-- Configure ethernet tcp buffersizes in the form: + rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max --> + <string name="config_ethernet_tcp_buffers" translatable="false">524288,1048576,3145728,524288,1048576,2097152</string> + + <!-- Configure wifi tcp buffersizes in the form: + rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max --> + <string name="config_wifi_tcp_buffers" translatable="false">524288,1048576,2097152,262144,524288,1048576</string> + <!-- Whether WiFi display is supported by this device. There are many prerequisites for this feature to work correctly. Here are a few of them: diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index b198329..b167c0a 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1815,6 +1815,11 @@ <string name="permdesc_devicePower" product="default">Allows the app to turn the phone on or off.</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_userActivity">reset display timeout</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_userActivity">Allows the app to reset the display timeout.</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_factoryTest">run in factory test mode</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_factoryTest" product="tablet">Run as a low-level manufacturer test, @@ -3958,7 +3963,7 @@ <string name="permission_request_notification_with_subtitle">Permission requested\nfor account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g>.</string> <!-- Message to show when an intent automatically switches users into the personal profile. --> - <string name="forward_intent_to_owner">You\'re using this app in your personal profile</string> + <string name="forward_intent_to_owner">You\'re using this app outside of your work profile</string> <!-- Message to show when an intent automatically switches users into a work profile. --> <string name="forward_intent_to_work">You\'re using this app in your work profile</string> @@ -4142,10 +4147,6 @@ <string name="time_picker_increment_set_pm_button">Set PM</string> <!-- Description of the button to decrease the TimePicker's set AM value. [CHAR LIMIT=NONE] --> <string name="time_picker_decrement_set_am_button">Set AM</string> - <!-- Label for the TimePicker's PM button. [CHAR LIMIT=2] --> - <string name="time_picker_pm_label">PM</string> - <!-- Label for the TimePicker's AM button. [CHAR LIMIT=2] --> - <string name="time_picker_am_label">AM</string> <!-- DatePicker - accessibility support --> <!-- Description of the button to increase the DatePicker's month value. [CHAR LIMIT=NONE] --> @@ -4325,7 +4326,7 @@ <!-- Text for the toast that is shown when the user clicks on a launcher that doesn't support the work profile. [CHAR LIMIT=100] --> - <string name="activity_resolver_work_profiles_support">%1$s doesn\'t support work profile.</string> + <string name="activity_resolver_work_profiles_support">%1$s doesn\'t support work profile</string> <!-- Name of the default audio route for tablets when nothing is connected to a headphone or other wired audio output jack. [CHAR LIMIT=50] --> @@ -4543,6 +4544,8 @@ <string name="enable_accessibility_canceled">Accessibility canceled.</string> <!-- Text spoken when the current user is switched if accessibility is enabled. [CHAR LIMIT=none] --> <string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string> + <!-- Message shown when switching to a user [CHAR LIMIT=none] --> + <string name="user_switching_message">Switching to user <xliff:g id="name" example="Bob">%1$s</xliff:g></string> <!-- Default name of the owner user [CHAR LIMIT=20] --> <string name="owner_name" msgid="3879126011135546571">Owner</string> <!-- Error message title [CHAR LIMIT=35] --> @@ -4821,7 +4824,7 @@ <string name="deleted_key"><xliff:g id="key" example="4">%1$s</xliff:g> deleted</string> <!-- - Used to wrap a label for content description for a managed profile, e.g. "Work Email" instead + Used to wrap a label for content description for a work profile, e.g. "Work Email" instead of email when there are two email apps. [CHAR LIMIT=20] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b32cd1e..3f373aa 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -216,7 +216,9 @@ <java-symbol type="id" name="pin_confirm_text" /> <java-symbol type="id" name="pin_error_message" /> <java-symbol type="id" name="timePickerLayout" /> - <java-symbol type="id" name="profile_icon" /> + <java-symbol type="id" name="profile_badge_large_template" /> + <java-symbol type="id" name="profile_badge_line2" /> + <java-symbol type="id" name="profile_badge_line3" /> <java-symbol type="id" name="transitionPosition" /> <java-symbol type="attr" name="actionModeShareDrawable" /> @@ -834,6 +836,7 @@ <java-symbol type="string" name="time_picker_increment_set_pm_button" /> <java-symbol type="string" name="upload_file" /> <java-symbol type="string" name="user_switched" /> + <java-symbol type="string" name="user_switching_message" /> <java-symbol type="string" name="volume_alarm" /> <java-symbol type="string" name="volume_icon_description_bluetooth" /> <java-symbol type="string" name="volume_icon_description_incall" /> @@ -987,6 +990,8 @@ <java-symbol type="string" name="ssl_ca_cert_warning" /> <java-symbol type="string" name="lockscreen_transport_play_description" /> <java-symbol type="string" name="lockscreen_transport_pause_description" /> + <java-symbol type="string" name="config_ethernet_tcp_buffers" /> + <java-symbol type="string" name="config_wifi_tcp_buffers" /> <java-symbol type="plurals" name="abbrev_in_num_days" /> <java-symbol type="plurals" name="abbrev_in_num_hours" /> @@ -1560,6 +1565,7 @@ <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" /> <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" /> <java-symbol type="integer" name="config_screenBrightnessSettingDefault" /> + <java-symbol type="integer" name="config_screenBrightnessDark" /> <java-symbol type="integer" name="config_screenBrightnessDim" /> <java-symbol type="integer" name="config_screenBrightnessDoze" /> <java-symbol type="integer" name="config_shutdownBatteryTemperature" /> @@ -1980,8 +1986,6 @@ <java-symbol type="attr" name="headerSelectedTextColor" /> <java-symbol type="attr" name="amPmSelectedBackgroundColor" /> <java-symbol type="bool" name="config_sms_decode_gsm_8bit_data" /> - <java-symbol type="string" name="time_picker_am_label" /> - <java-symbol type="string" name="time_picker_pm_label" /> <java-symbol type="dimen" name="text_size_small_material" /> <java-symbol type="attr" name="checkMarkGravity" /> <java-symbol type="layout" name="select_dialog_singlechoice_material" /> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index 23faba8..7a208f7 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -333,8 +333,7 @@ please see themes_device_defaults.xml. <item name="dividerVertical">?attr/listDivider</item> <item name="dividerHorizontal">?attr/listDivider</item> <item name="buttonBarStyle">@style/Widget.Material.ButtonBar</item> - <item name="buttonBarButtonStyle">@style/Widget.Material.Button.Borderless</item> - <item name="buttonBarPositiveButtonStyle">@style/Widget.Material.Button.Borderless.Colored</item> + <item name="buttonBarButtonStyle">@style/Widget.Material.Button.Borderless.Colored</item> <item name="segmentedButtonStyle">@style/Widget.Material.SegmentedButton</item> <!-- SearchView attributes --> @@ -680,8 +679,7 @@ please see themes_device_defaults.xml. <item name="dividerVertical">?attr/listDivider</item> <item name="dividerHorizontal">?attr/listDivider</item> <item name="buttonBarStyle">@style/Widget.Material.Light.ButtonBar</item> - <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.Borderless</item> - <item name="buttonBarPositiveButtonStyle">@style/Widget.Material.Light.Button.Borderless.Colored</item> + <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.Borderless.Colored</item> <item name="segmentedButtonStyle">@style/Widget.Material.Light.SegmentedButton</item> <!-- SearchView attributes --> diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java index b4b0e53..01995c7 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java @@ -127,10 +127,11 @@ public class ConnectivityManagerMobileTest extends assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint)); // assert that WifiManager reports correct state - assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)); + assertTrue("wifi not enabled", waitForWifiState( + WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)); // assert that ConnectivityManager reports correct state for Wifi - assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, - WIFI_CONNECTION_TIMEOUT)); + assertTrue("wifi not connected", waitForNetworkState( + ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT)); // below check disbabled since we have bug in what ConnectivityManager returns // if (!mWifiOnlyFlag) { // // assert that ConnectivityManager reports correct state for mobile @@ -267,8 +268,8 @@ public class ConnectivityManagerMobileTest extends // connect to Wifi assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint)); - assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, - WIFI_CONNECTION_TIMEOUT)); + assertTrue("wifi not connected", waitForNetworkState( + ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT)); // verify that connection actually works assertTrue("no network connectivity after wifi enable", checkNetworkConnectivity()); @@ -289,8 +290,8 @@ public class ConnectivityManagerMobileTest extends // connect to Wifi assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint)); - assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, - WIFI_CONNECTION_TIMEOUT)); + assertTrue("wifi not connected", waitForNetworkState( + ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT)); // enable airplane mode without clearing Wifi mCm.setAirplaneMode(true); @@ -322,8 +323,8 @@ public class ConnectivityManagerMobileTest extends // connect to Wifi assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint)); - assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, - WIFI_CONNECTION_TIMEOUT)); + assertTrue("wifi not connected", waitForNetworkState( + ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT)); assertNotNull("not associated with any AP", mWifiManager.getConnectionInfo().getBSSID()); // disconnect from the current AP diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java index 859c30c..6ef4f06 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java @@ -198,6 +198,9 @@ public class WifiStressTest extends ConnectivityManagerTestBase { // Stress Wifi reconnection to secure net after sleep @LargeTest public void testWifiReconnectionAfterSleep() { + // set always scan to false + Settings.Global.putInt(mRunner.getContext().getContentResolver(), + Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); // set wifi sleep policy to never on while in sleep Settings.Global.putInt(mRunner.getContext().getContentResolver(), Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_NEVER); diff --git a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java index 7ad35d0..06c495e 100644 --- a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java @@ -16,7 +16,7 @@ package android.content.pm; -import com.android.internal.content.PackageHelper; +import static android.net.TrafficStats.MB_IN_BYTES; import android.os.IBinder; import android.os.RemoteException; @@ -25,6 +25,8 @@ import android.os.storage.IMountService; import android.test.AndroidTestCase; import android.util.Log; +import com.android.internal.content.PackageHelper; + public class PackageHelperTests extends AndroidTestCase { private static final boolean localLOGV = true; public static final String TAG = "PackageHelperTests"; @@ -81,8 +83,8 @@ public class PackageHelperTests extends AndroidTestCase { public void testMountAndPullSdCard() { try { fullId = PREFIX; - fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid(), - true); + fullId2 = PackageHelper.createSdDir(1024 * MB_IN_BYTES, fullId, "none", + android.os.Process.myUid(), true); Log.d(TAG,PackageHelper.getSdDir(fullId)); PackageHelper.unMountSdDir(fullId); diff --git a/core/tests/coretests/src/android/os/storage/AsecTests.java b/core/tests/coretests/src/android/os/storage/AsecTests.java index abb8eae..4f724fe 100644 --- a/core/tests/coretests/src/android/os/storage/AsecTests.java +++ b/core/tests/coretests/src/android/os/storage/AsecTests.java @@ -90,7 +90,7 @@ public class AsecTests extends AndroidTestCase { String fullId = SECURE_CONTAINER_PREFIX + localId; IMountService ms = getMs(); - return ms.mountSecureContainer(fullId, key, android.os.Process.myUid()); + return ms.mountSecureContainer(fullId, key, android.os.Process.myUid(), true); } private int renameContainer(String localId1, String localId2) throws Exception { diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java index 265a564..6934955 100644 --- a/graphics/java/android/graphics/Shader.java +++ b/graphics/java/android/graphics/Shader.java @@ -28,8 +28,6 @@ public class Shader { */ private long native_instance; - private long native_with_local_matrix; - /** * Initialization step that should be called by subclasses in their * constructors. Calling again may result in memory leaks. @@ -80,24 +78,18 @@ public class Shader { * Set the shader's local matrix. Passing null will reset the shader's * matrix to identity. * - * Starting with {@link android.os.Build.VERSION_CODES#L}, this does not - * modify any Paints which use this Shader. In order to modify the Paint, - * you need to call {@link Paint#setShader} again. Further, any {@link ComposeShader}s - * created with this Shader will be unaffected. - * * @param localM The shader's new local matrix, or null to specify identity */ public void setLocalMatrix(Matrix localM) { mLocalMatrix = localM; - native_with_local_matrix = nativeSetLocalMatrix(native_instance, - native_with_local_matrix, localM == null ? 0 : localM.native_instance); + nativeSetLocalMatrix(native_instance, localM == null ? 0 : localM.native_instance); } protected void finalize() throws Throwable { try { super.finalize(); } finally { - nativeDestructor(native_instance, native_with_local_matrix); + nativeDestructor(native_instance); } } @@ -124,13 +116,9 @@ public class Shader { } /* package */ long getNativeInstance() { - if (native_with_local_matrix != 0) { - return native_with_local_matrix; - } return native_instance; } - private static native void nativeDestructor(long native_shader, long native_with_local_matrix); - private static native long nativeSetLocalMatrix(long native_shader, - long native_with_local_matrix, long matrix_instance); + private static native void nativeDestructor(long native_shader); + private static native void nativeSetLocalMatrix(long native_shader, long matrix_instance); } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 4dcbc40..ba22550 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -155,7 +155,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { @Override public void draw(Canvas canvas) { mAnimatedVectorState.mVectorDrawable.draw(canvas); - if (isRunning()) { + if (isStarted()) { invalidateSelf(); } } @@ -361,13 +361,25 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { return false; } + private boolean isStarted() { + final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators; + final int size = animators.size(); + for (int i = 0; i < size; i++) { + final Animator animator = animators.get(i); + if (animator.isStarted()) { + return true; + } + } + return false; + } + @Override public void start() { final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators; final int size = animators.size(); for (int i = 0; i < size; i++) { final Animator animator = animators.get(i); - if (!animator.isRunning()) { + if (!animator.isStarted()) { animator.start(); } } diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp index fc0e8a0..ff8ff73 100644 --- a/libs/hwui/Interpolator.cpp +++ b/libs/hwui/Interpolator.cpp @@ -110,7 +110,7 @@ float LUTInterpolator::interpolate(float input) { weight = modff(lutpos, &ipart); int i1 = (int) ipart; - int i2 = MathUtils::min(i1 + 1, mSize - 1); + int i2 = MathUtils::min(i1 + 1, (int) mSize - 1); LOG_ALWAYS_FATAL_IF(i1 < 0 || i2 < 0, "negatives in interpolation!" " i1=%d, i2=%d, input=%f, lutpos=%f, size=%zu, values=%p, ipart=%f, weight=%f", diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp index e71439d..6cff815 100644 --- a/libs/hwui/ShadowTessellator.cpp +++ b/libs/hwui/ShadowTessellator.cpp @@ -29,11 +29,6 @@ namespace android { namespace uirenderer { -template<typename T> -static inline T max(T a, T b) { - return a > b ? a : b; -} - void ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque, const Vector3* casterPolygon, int casterVertexCount, const Vector3& centroid3d, const Rect& casterBounds, @@ -66,7 +61,7 @@ void ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque, } void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque, - const Vector3* casterPolygon, int casterVertexCount, + const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid, const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius, const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer) { ATRACE_CALL(); @@ -109,9 +104,9 @@ void ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque, return; } - SpotShadow::createSpotShadow(isCasterOpaque, - casterPolygon, casterVertexCount, adjustedLightCenter, lightRadius, - lightVertexCount, shadowVertexBuffer); + SpotShadow::createSpotShadow(isCasterOpaque, adjustedLightCenter, lightRadius, + casterPolygon, casterVertexCount, casterCentroid, shadowVertexBuffer); + #if DEBUG_SHADOW if(shadowVertexBuffer.getVertexCount() <= 0) { ALOGD("Spot shadow generation failed %d", shadowVertexBuffer.getVertexCount()); @@ -180,6 +175,18 @@ Vector2 ShadowTessellator::centroid2d(const Vector2* poly, int polyLength) { return centroid; } +// Make sure p1 -> p2 is going CW around the poly. +Vector2 ShadowTessellator::calculateNormal(const Vector2& p1, const Vector2& p2) { + Vector2 result = p2 - p1; + if (result.x != 0 || result.y != 0) { + result.normalize(); + // Calculate the normal , which is CCW 90 rotate to the delta. + float tempy = result.y; + result.y = result.x; + result.x = -tempy; + } + return result; +} /** * Test whether the polygon is order in clockwise. * diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h index cb65df5..141dff6 100644 --- a/libs/hwui/ShadowTessellator.h +++ b/libs/hwui/ShadowTessellator.h @@ -72,7 +72,7 @@ public: const Rect& localClip, float maxZ, VertexBuffer& shadowVertexBuffer); static void tessellateSpotShadow(bool isCasterOpaque, - const Vector3* casterPolygon, int casterVertexCount, + const Vector3* casterPolygon, int casterVertexCount, const Vector3& casterCentroid, const mat4& receiverTransform, const Vector3& lightCenter, int lightRadius, const Rect& casterBounds, const Rect& localClip, VertexBuffer& shadowVertexBuffer); @@ -82,6 +82,7 @@ public: static bool isClockwise(const Vector2* polygon, int len); + static Vector2 calculateNormal(const Vector2& p1, const Vector2& p2); /** * Determine whether the path is clockwise, using the control points. * diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp index d726538..cb20a0b 100644 --- a/libs/hwui/SpotShadow.cpp +++ b/libs/hwui/SpotShadow.cpp @@ -17,6 +17,9 @@ #define LOG_TAG "OpenGLRenderer" #define SHADOW_SHRINK_SCALE 0.1f +#define CASTER_Z_CAP_RATIO 0.95f +#define FAKE_UMBRA_SIZE_RATIO 0.01f +#define OCLLUDED_UMBRA_SHRINK_FACTOR 0.95f #include <math.h> #include <stdlib.h> @@ -25,13 +28,29 @@ #include "ShadowTessellator.h" #include "SpotShadow.h" #include "Vertex.h" +#include "utils/MathUtils.h" +// TODO: After we settle down the new algorithm, we can remove the old one and +// its utility functions. +// Right now, we still need to keep it for comparison purpose and future expansion. namespace android { namespace uirenderer { static const double EPSILON = 1e-7; /** + * For each polygon's vertex, the light center will project it to the receiver + * as one of the outline vertex. + * For each outline vertex, we need to store the position and normal. + * Normal here is defined against the edge by the current vertex and the next vertex. + */ +struct OutlineData { + Vector2 position; + Vector2 normal; + float radius; +}; + +/** * Calculate the angle between and x and a y coordinate. * The atan2 range from -PI to PI. */ @@ -500,12 +519,13 @@ void SpotShadow::computeLightPolygon(int points, const Vector3& lightCenter, * empty strip if error. * */ -void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3* poly, + +void SpotShadow::createSpotShadow_old(bool isCasterOpaque, const Vector3* poly, int polyLength, const Vector3& lightCenter, float lightSize, int lightVertexCount, VertexBuffer& retStrips) { Vector3 light[lightVertexCount * 3]; computeLightPolygon(lightVertexCount, lightCenter, lightSize, light); - computeSpotShadow(isCasterOpaque, light, lightVertexCount, lightCenter, poly, + computeSpotShadow_old(isCasterOpaque, light, lightVertexCount, lightCenter, poly, polyLength, retStrips); } @@ -519,9 +539,9 @@ void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3* poly, * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return * empty strip if error. */ -void SpotShadow::computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly, - int lightPolyLength, const Vector3& lightCenter, const Vector3* poly, - int polyLength, VertexBuffer& shadowTriangleStrip) { +void SpotShadow::computeSpotShadow_old(bool isCasterOpaque, const Vector3* lightPoly, + int lightPolyLength, const Vector3& lightCenter, const Vector3* poly, int polyLength, + VertexBuffer& shadowTriangleStrip) { // Point clouds for all the shadowed vertices Vector2 shadowRegion[lightPolyLength * polyLength]; // Shadow polygon from one point light. @@ -616,10 +636,198 @@ void SpotShadow::computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly umbraLength = polyLength; } - generateTriangleStrip(isCasterOpaque, penumbra, penumbraLength, umbra, + generateTriangleStrip(isCasterOpaque, 1.0, penumbra, penumbraLength, umbra, umbraLength, poly, polyLength, shadowTriangleStrip); } +float SpotShadow::projectCasterToOutline(Vector2& outline, + const Vector3& lightCenter, const Vector3& polyVertex) { + float lightToPolyZ = lightCenter.z - polyVertex.z; + float ratioZ = CASTER_Z_CAP_RATIO; + if (lightToPolyZ != 0) { + // If any caster's vertex is almost above the light, we just keep it as 95% + // of the height of the light. + ratioZ = MathUtils::min(polyVertex.z / lightToPolyZ, CASTER_Z_CAP_RATIO); + } + + outline.x = polyVertex.x - ratioZ * (lightCenter.x - polyVertex.x); + outline.y = polyVertex.y - ratioZ * (lightCenter.y - polyVertex.y); + return ratioZ; +} + +/** + * Generate the shadow spot light of shape lightPoly and a object poly + * + * @param isCasterOpaque whether the caster is opaque + * @param lightCenter the center of the light + * @param lightSize the radius of the light + * @param poly x,y,z vertexes of a convex polygon that occludes the light source + * @param polyLength number of vertexes of the occluding polygon + * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return + * empty strip if error. + */ +void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter, + float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid, + VertexBuffer& shadowTriangleStrip) { + OutlineData outlineData[polyLength]; + Vector2 outlineCentroid; + // Calculate the projected outline for each polygon's vertices from the light center. + // + // O Light + // / + // / + // . Polygon vertex + // / + // / + // O Outline vertices + // + // Ratio = (Poly - Outline) / (Light - Poly) + // Outline.x = Poly.x - Ratio * (Light.x - Poly.x) + // Outline's radius / Light's radius = Ratio + + // Compute the last outline vertex to make sure we can get the normal and outline + // in one single loop. + projectCasterToOutline(outlineData[polyLength - 1].position, lightCenter, + poly[polyLength - 1]); + + // Take the outline's polygon, calculate the normal for each outline edge. + int currentNormalIndex = polyLength - 1; + int nextNormalIndex = 0; + + for (int i = 0; i < polyLength; i++) { + float ratioZ = projectCasterToOutline(outlineData[i].position, + lightCenter, poly[i]); + outlineData[i].radius = ratioZ * lightSize; + + outlineData[currentNormalIndex].normal = ShadowTessellator::calculateNormal( + outlineData[currentNormalIndex].position, + outlineData[nextNormalIndex].position); + currentNormalIndex = (currentNormalIndex + 1) % polyLength; + nextNormalIndex++; + } + + projectCasterToOutline(outlineCentroid, lightCenter, polyCentroid); + + int penumbraIndex = 0; + int penumbraLength = polyLength * 3; + Vector2 penumbra[penumbraLength]; + + Vector2 umbra[polyLength]; + float distOutline = 0; + float ratioVI = 0; + + bool hasValidUmbra = true; + // We need the maxRatioVI to decrease the spot shadow strength accordingly. + float maxRaitoVI = 1.0; + + for (int i = 0; i < polyLength; i++) { + // Generate all the penumbra's vertices only using the (outline vertex + normal * radius) + // There is no guarantee that the penumbra is still convex, but for + // each outline vertex, it will connect to all its corresponding penumbra vertices as + // triangle fans. And for neighber penumbra vertex, it will be a trapezoid. + // + // Penumbra Vertices marked as Pi + // Outline Vertices marked as Vi + // (P3) + // (P2) | ' (P4) + // (P1)' | | ' + // ' | | ' + // (P0) ------------------------------------------------(P5) + // | (V0) |(V1) + // | | + // | | + // | | + // | | + // | | + // | | + // | | + // | | + // (V3)-----------------------------------(V2) + int preNormalIndex = (i + polyLength - 1) % polyLength; + penumbra[penumbraIndex++] = outlineData[i].position + + outlineData[preNormalIndex].normal * outlineData[i].radius; + + int currentNormalIndex = i; + // (TODO) Depending on how roundness we want for each corner, we can subdivide + // further here and/or introduce some heuristic to decide how much the + // subdivision should be. + Vector2 avgNormal = + (outlineData[preNormalIndex].normal + outlineData[currentNormalIndex].normal) / 2; + + penumbra[penumbraIndex++] = outlineData[i].position + + avgNormal * outlineData[i].radius; + + penumbra[penumbraIndex++] = outlineData[i].position + + outlineData[currentNormalIndex].normal * outlineData[i].radius; + + // Compute the umbra by the intersection from the outline's centroid! + // + // (V) ------------------------------------ + // | ' | + // | ' | + // | ' (I) | + // | ' | + // | ' (C) | + // | | + // | | + // | | + // | | + // ------------------------------------ + // + // Connect a line b/t the outline vertex (V) and the centroid (C), it will + // intersect with the outline vertex's circle at point (I). + // Now, ratioVI = VI / VC, ratioIC = IC / VC + // Then the intersetion point can be computed as Ixy = Vxy * ratioIC + Cxy * ratioVI; + // + // When one of the outline circle cover the the outline centroid, (like I is + // on the other side of C), there is no real umbra any more, so we just fake + // a small area around the centroid as the umbra, and tune down the spot + // shadow's umbra strength to simulate the effect the whole shadow will + // become lighter in this case. + // The ratio can be simulated by using the inverse of maximum of ratioVI for + // all (V). + distOutline = (outlineData[i].position - outlineCentroid).length(); + if (distOutline == 0) { + // If the outline has 0 area, then there is no spot shadow anyway. + ALOGW("Outline has 0 area, no spot shadow!"); + return; + } + ratioVI = outlineData[i].radius / distOutline; + if (ratioVI >= 1.0) { + maxRaitoVI = ratioVI; + hasValidUmbra = false; + } + // When we know we don't have valid umbra, don't bother to compute the + // values below. But we can't skip the loop yet since we want to know the + // maximum ratio. + if (hasValidUmbra) { + float ratioIC = (distOutline - outlineData[i].radius) / distOutline; + umbra[i] = outlineData[i].position * ratioIC + outlineCentroid * ratioVI; + } + } + + float shadowStrengthScale = 1.0; + if (!hasValidUmbra) { + ALOGW("The object is too close to the light or too small, no real umbra!"); + for (int i = 0; i < polyLength; i++) { + umbra[i] = outlineData[i].position * FAKE_UMBRA_SIZE_RATIO + + outlineCentroid * (1 - FAKE_UMBRA_SIZE_RATIO); + } + shadowStrengthScale = 1.0 / maxRaitoVI; + } + +#if DEBUG_SHADOW + dumpPolygon(poly, polyLength, "input poly"); + dumpPolygon(outline, polyLength, "outline"); + dumpPolygon(penumbra, penumbraLength, "penumbra"); + dumpPolygon(umbra, polyLength, "umbra"); + ALOGD("hasValidUmbra is %d and shadowStrengthScale is %f", hasValidUmbra, shadowStrengthScale); +#endif + + generateTriangleStrip(isCasterOpaque, shadowStrengthScale, penumbra, + penumbraLength, umbra, polyLength, poly, polyLength, shadowTriangleStrip); +} + /** * Converts a polygon specified with CW vertices into an array of distance-from-centroid values. * @@ -697,7 +905,6 @@ int SpotShadow::calculateOccludedUmbra(const Vector2* umbra, int umbraLength, occludedUmbra, polyLength); } -#define OCLLUDED_UMBRA_SHRINK_FACTOR 0.95f /** * Generate a triangle strip given two convex polygons * @@ -708,8 +915,8 @@ int SpotShadow::calculateOccludedUmbra(const Vector2* umbra, int umbraLength, * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return * empty strip if error. **/ -void SpotShadow::generateTriangleStrip(bool isCasterOpaque, const Vector2* penumbra, - int penumbraLength, const Vector2* umbra, int umbraLength, +void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale, + const Vector2* penumbra, int penumbraLength, const Vector2* umbra, int umbraLength, const Vector3* poly, int polyLength, VertexBuffer& shadowTriangleStrip) { const int rays = SHADOW_RAY_COUNT; const int size = 2 * rays; @@ -750,13 +957,12 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, const Vector2* penum } } } - AlphaVertex* shadowVertices = shadowTriangleStrip.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT); // NOTE: Shadow alpha values are transformed when stored in alphavertices, // so that they can be consumed directly by gFS_Main_ApplyVertexAlphaShadowInterp - float transformedMaxAlpha = M_PI; + float transformedMaxAlpha = M_PI * shadowStrengthScale; // Calculate the vertices (x, y, alpha) in the shadow area. AlphaVertex centroidXYA; @@ -789,7 +995,6 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, const Vector2* penum shadowVertices[2 * rays + rayIndex] = centroidXYA; } } - shadowTriangleStrip.setMode(VertexBuffer::kTwoPolyRingShadow); shadowTriangleStrip.computeBounds<AlphaVertex>(); } @@ -844,7 +1049,16 @@ void SpotShadow::updateBound(const Vector2 inVector, Vector2& lowerBound, /** * For debug purpose, when things go wrong, dump the whole polygon data. */ -static void dumpPolygon(const Vector2* poly, int polyLength, const char* polyName) { +void SpotShadow::dumpPolygon(const Vector2* poly, int polyLength, const char* polyName) { + for (int i = 0; i < polyLength; i++) { + ALOGD("polygon %s i %d x %f y %f", polyName, i, poly[i].x, poly[i].y); + } +} + +/** + * For debug purpose, when things go wrong, dump the whole polygon data. + */ +void SpotShadow::dumpPolygon(const Vector3* poly, int polyLength, const char* polyName) { for (int i = 0; i < polyLength; i++) { ALOGD("polygon %s i %d x %f y %f", polyName, i, poly[i].x, poly[i].y); } @@ -885,8 +1099,8 @@ void SpotShadow::testIntersection(const Vector2* poly1, int poly1Length, const Vector2* poly2, int poly2Length, const Vector2* intersection, int intersectionLength) { // Find the min and max of x and y. - Vector2 lowerBound(FLT_MAX, FLT_MAX); - Vector2 upperBound(-FLT_MAX, -FLT_MAX); + Vector2 lowerBound = {FLT_MAX, FLT_MAX}; + Vector2 upperBound = {-FLT_MAX, -FLT_MAX}; for (int i = 0; i < poly1Length; i++) { updateBound(poly1[i], lowerBound, upperBound); } diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h index d65ea89..355be8d 100644 --- a/libs/hwui/SpotShadow.h +++ b/libs/hwui/SpotShadow.h @@ -26,16 +26,22 @@ namespace uirenderer { class SpotShadow { public: - static void createSpotShadow(bool isCasterOpaque, const Vector3* poly, + static void createSpotShadow_old(bool isCasterOpaque, const Vector3* poly, int polyLength, const Vector3& lightCenter, float lightSize, int lightVertexCount, VertexBuffer& retStrips); + static void createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter, + float lightSize, const Vector3* poly, int polyLength, + const Vector3& polyCentroid, VertexBuffer& retstrips); private: + static float projectCasterToOutline(Vector2& outline, + const Vector3& lightCenter, const Vector3& polyVertex); static int calculateOccludedUmbra(const Vector2* umbra, int umbraLength, const Vector3* poly, int polyLength, Vector2* occludedUmbra); - static void computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly, + + static void computeSpotShadow_old(bool isCasterOpaque, const Vector3* lightPoly, int lightPolyLength, const Vector3& lightCenter, const Vector3* poly, - int polyLength, VertexBuffer& retstrips); + int polyLength, VertexBuffer& shadowTriangleStrip); static void computeLightPolygon(int points, const Vector3& lightCenter, float size, Vector3* ret); @@ -60,8 +66,8 @@ private: static inline bool lineIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, Vector2& ret); - static void generateTriangleStrip(bool isCasterOpaque, const Vector2* penumbra, - int penumbraLength, const Vector2* umbra, int umbraLength, + static void generateTriangleStrip(bool isCasterOpaque, float shadowStrengthScale, + const Vector2* penumbra, int penumbraLength, const Vector2* umbra, int umbraLength, const Vector3* poly, int polyLength, VertexBuffer& retstrips); #if DEBUG_SHADOW @@ -72,6 +78,8 @@ private: const Vector2* poly2, int poly2Length, const Vector2* intersection, int intersectionLength); static void updateBound(const Vector2 inVector, Vector2& lowerBound, Vector2& upperBound ); + static void dumpPolygon(const Vector2* poly, int polyLength, const char* polyName); + static void dumpPolygon(const Vector3* poly, int polyLength, const char* polyName); #endif }; // SpotShadow diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index 0a9aeb8..9e62f36 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -267,7 +267,7 @@ static void tessellateShadows( casterBounds, *localClip, maxZ, ambientBuffer); ShadowTessellator::tessellateSpotShadow( - isCasterOpaque, casterPolygon, casterVertexCount, + isCasterOpaque, casterPolygon, casterVertexCount, centroid3d, *drawTransform, lightCenter, lightRadius, casterBounds, *localClip, spotBuffer); } diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h index 6fb0411..00448b8 100644 --- a/libs/hwui/utils/MathUtils.h +++ b/libs/hwui/utils/MathUtils.h @@ -66,11 +66,13 @@ public: return isZero(valueA - valueB); } - inline static int max(int a, int b) { + template<typename T> + static inline T max(T a, T b) { return a > b ? a : b; } - inline static int min(int a, int b) { + template<typename T> + static inline T min(T a, T b) { return a < b ? a : b; } diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp index 5701678..621de18 100644 --- a/libs/storage/IMountService.cpp +++ b/libs/storage/IMountService.cpp @@ -295,6 +295,8 @@ public: data.writeString16(id); data.writeString16(key); data.writeInt32(ownerUid); + // Assume read-only + data.writeInt32(1); if (remote()->transact(TRANSACTION_mountSecureContainer, data, &reply) != NO_ERROR) { ALOGD("mountSecureContainer couldn't call remote"); return -1; diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index ae2d024..acb2186 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -959,6 +959,23 @@ public final class MediaCodecInfo { } } } + // for now this just means using the smaller max size as 2nd + // upper limit. + // for now we are keeping the profile specific "width/height + // in macroblocks" limits. + if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) { + if (widths != null) { + mSmallerDimensionUpperLimit = + Math.min(widths.getUpper(), heights.getUpper()); + widths = heights = widths.extend(heights); + } else { + Log.w(TAG, "feature can-swap-width-height is best used with size-range"); + mSmallerDimensionUpperLimit = + Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()); + mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange); + } + } + ratios = Utils.parseRationalRange( map.get("block-aspect-ratio-range"), null); blockRatios = Utils.parseRationalRange( @@ -1124,9 +1141,17 @@ public final class MediaCodecInfo { private void updateLimits() { // pixels -> blocks <- counts mHorizontalBlockRange = mHorizontalBlockRange.intersect( - Utils.factorRange(mWidthRange, mBlockWidth)).intersect(mBlockCountRange); + Utils.factorRange(mWidthRange, mBlockWidth)); + mHorizontalBlockRange = mHorizontalBlockRange.intersect( + Range.create( + mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(), + mBlockCountRange.getUpper() / mVerticalBlockRange.getLower())); mVerticalBlockRange = mVerticalBlockRange.intersect( - Utils.factorRange(mHeightRange, mBlockHeight)).intersect(mBlockCountRange); + Utils.factorRange(mHeightRange, mBlockHeight)); + mVerticalBlockRange = mVerticalBlockRange.intersect( + Range.create( + mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(), + mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower())); mBlockCountRange = mBlockCountRange.intersect( Range.create( mHorizontalBlockRange.getLower() diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java index c4a81cc..93622ab 100644 --- a/media/java/android/media/tv/TvContentRating.java +++ b/media/java/android/media/tv/TvContentRating.java @@ -17,7 +17,6 @@ package android.media.tv; import android.annotation.SystemApi; -import android.net.Uri; import android.text.TextUtils; import java.util.Arrays; @@ -26,19 +25,22 @@ import java.util.List; import java.util.Objects; /** - * A class representing a TV content rating. - * When a TV input service provides the content rating information of a program into TV provider, - * TvContentRating class will be used for generating the value of {@link - * TvContract.Programs#COLUMN_CONTENT_RATING}. To create an object of {@link TvContentRating}, use - * the {@link #createRating} method with valid arguments. The arguments could be a system defined - * strings, or a TV input service defined strings. - * TV input service defined strings are in an xml file defined in <code><{@link - * android.R.styleable#TvInputService tv-input}></code> with the {@link - * android.R.attr#tvContentRatingDescription tvContentRatingDescription} attribute by the TV input - * service. - * + * A class representing a TV content rating. When a TV input service inserts the content rating + * information on a program into the database, this class can be used to generate the formatted + * string for + * {@link TvContract.Programs#COLUMN_CONTENT_RATING TvContract.Programs.COLUMN_CONTENT_RATING}. + * To create a {@code TvContentRating} object, use the + * {@link #createRating TvContentRating.createRating} method with valid rating system string + * constants. + * <p> + * It is possible for a TV input to define its own content rating system by supplying a content + * rating system definition XML resource (see example below) and having the + * {@link android.R.attr#tvContentRatingDescription tvContentRatingDescription} attribute in + * {@link TvInputService#SERVICE_META_DATA} of the TV input point to it. + * </p> * <h3> Example: Rating system definition for the TV Parental Guidelines</h3> - * The following XML example shows how the TV Parental Guidelines in United States can be defined: + * The following XML example shows how the TV Parental Guidelines in the United States can be + * defined: * <p><pre class="prettyprint"> * {@literal * <rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android" @@ -118,24 +120,36 @@ import java.util.Objects; * </rating-system-definitions>}</pre></p> * * <h3>System defined rating strings</h3> - * - * <u>System defined string for {@code domain}</u> - * <table border="0" cellspacing="0" cellpadding="0"> - * <tr> - * <td width=10%>String value</td> - * <td>Comments</td> - * </tr> - * <tr> - * <td>android.media.tv</td> + * The following strings are defined by the system to provide a standard way to create + * {@code TvContentRating} objects. + * <p>For example, to create an object that represents TV-PG rating with suggestive dialogue and + * coarse language from the TV Parental Guidelines in the United States, one can use the following + * code snippet: + * </p> + * <pre> + * String rating = TvContentRating.createRating( + * "com.android.tv", + * "US_TV", + * "US_TV_PG", + * "US_TV_D", "US_TV_L"); + * </pre> + * <h4>System defined string for domains</h4> + * <table> + * <tr> + * <th>Constant Value</th> + * <th>Comment</th> + * </tr> + * <tr> + * <td>com.android.tv</td> * <td>Used for creating system defined content ratings</td> * </tr> * </table> * - * <u>System defined string for {@code ratingSystem}</u> - * <table border="1" cellspacing="0" cellpadding="0"> + * <h4>System defined strings for rating systems</h4> + * <table> * <tr> - * <td width="10%">String value</td> - * <td>Comments</td> + * <th>Constant Value</th> + * <th>Comment</th> * </tr> * <tr> * <td>AM_TV_RS</td> @@ -316,7 +330,7 @@ import java.util.Objects; * </tr> * <tr> * <td>US_TV</td> - * <td>TV content rating system for United States</td> + * <td>TV content rating system for the United States</td> * </tr> * <tr> * <td>VE_TV</td> @@ -328,12 +342,12 @@ import java.util.Objects; * </tr> * </table> * - * <u>System defined string for {@code rating}</u> - * <table border="1" cellspacing="0" cellpadding="0"> + * <h4>System defined strings for ratings</h4> + * <table> * <tr> - * <td width="10%">RatingSystem code</td> - * <td width="10%">Rating string value</td> - * <td>Comments</td> + * <th>Rating System</th> + * <th>Constant Value</th> + * <th>Comment</th> * </tr> * <tr> * <td valign="top" rowspan="6">AM_TV_RS</td> @@ -1401,12 +1415,12 @@ import java.util.Objects; * </tr> * </table> * - * <u>System defined string for {@code subRating}</u> - * <table border="1" cellspacing="0" cellpadding="0"> + * <h4>System defined strings for sub-ratings</h4> + * <table> * <tr> - * <td width="10%">RatingSystem code</td> - * <td width="10%">Rating string value</td> - * <td>Comments</td> + * <th>Rating System</th> + * <th>Constant Value</th> + * <th>Comment</th> * </tr> * <tr> * <td valign="top" rowspan="6">NL_TV</td> @@ -1518,13 +1532,15 @@ public final class TvContentRating { private final int mHashCode; /** - * Creates a TvContentRating object. + * Creates a {@code TvContentRating} object with predefined content rating strings. * - * @param domain The domain name. - * @param ratingSystem The rating system id. - * @param rating The content rating string. - * @param subRatings The string array of sub-ratings. - * @return A TvContentRating object, or null if creation failed. + * @param domain The domain string. For example, "com.android.tv". + * @param ratingSystem The rating system string. For example, "US_TV". + * @param rating The content rating string. For example, "US_TV_PG". + * @param subRatings The sub-rating strings. For example, "US_TV_D" and "US_TV_L". + * @return A {@code TvContentRating} object. + * @throws IllegalArgumentException If {@code domain}, {@code ratingSystem} or {@code rating} is + * {@code null}. */ public static TvContentRating createRating(String domain, String ratingSystem, String rating, String... subRatings) { @@ -1541,12 +1557,12 @@ public final class TvContentRating { } /** - * Recovers a TvContentRating from a String that was previously created with + * Recovers a {@code TvContentRating} object from the string that was previously created from * {@link #flattenToString}. * - * @param ratingString The String that was returned by flattenToString(). - * @return a new TvContentRating containing the domain, rating system, rating and - * sub-ratings information was encoded in {@code ratingString}. + * @param ratingString The string returned by {@link #flattenToString}. + * @return the {@code TvContentRating} object containing the domain, rating system, rating and + * sub-ratings information encoded in {@code ratingString}. * @see #flattenToString */ public static TvContentRating unflattenFromString(String ratingString) { @@ -1568,10 +1584,10 @@ public final class TvContentRating { /** * Constructs a TvContentRating object from a given rating and sub-rating constants. * - * @param domain The domain name. - * @param ratingSystem The rating system id. - * @param rating The content rating string. - * @param subRatings The String array of sub-rating constants defined in this class. + * @param domain The string for domain of the content rating system such as "com.android.tv". + * @param ratingSystem The rating system string such as "US_TV". + * @param rating The content rating string such as "US_TV_PG". + * @param subRatings The sub-rating strings such as "US_TV_D" and "US_TV_L". */ private TvContentRating( String domain, String ratingSystem, String rating, String[] subRatings) { @@ -1588,28 +1604,29 @@ public final class TvContentRating { } /** - * Returns the domain. + * Returns the domain of this {@code TvContentRating} object. */ public String getDomain() { return mDomain; } /** - * Returns the rating system id. + * Returns the rating system of this {@code TvContentRating} object. */ public String getRatingSystem() { return mRatingSystem; } /** - * Returns the main rating. + * Returns the main rating of this {@code TvContentRating} object. */ public String getMainRating() { return mRating; } /** - * Returns the unmodifiable {@code List} of sub-rating strings. + * Returns the unmodifiable sub-rating string {@link List} of this {@code TvContentRating} + * object. */ public List<String> getSubRatings() { if (mSubRatings == null) { @@ -1619,12 +1636,12 @@ public final class TvContentRating { } /** - * Returns a String that unambiguously describes both the rating and sub-rating information - * contained in the TvContentRating. You can later recover the TvContentRating from this string - * through {@link #unflattenFromString}. + * Returns a string that unambiguously describes the rating information contained in a + * {@code TvContentRating} object. One can later recover the object from this string through + * {@link #unflattenFromString}. * - * @return a new String holding rating/sub-rating information, which can later be stored in the - * database and settings. + * @return a string containing the rating information, which can later be stored in the + * database. * @see #unflattenFromString */ public String flattenToString() { @@ -1644,11 +1661,11 @@ public final class TvContentRating { } /** - * Returns true if this rating has the same main rating as the specified rating and when this - * rating's sub-ratings contain the other's. + * Returns {@code true} if this rating has the same main rating as the specified rating and when + * this rating's sub-ratings contain the other's. * <p> - * For example, a TvContentRating object that represents TV-PG with S(Sexual content) and - * V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself. + * For example, a {@code TvContentRating} object that represents TV-PG with S(Sexual content) + * and V(Violence) contains TV-PG, TV-PG/S, TV-PG/V and itself. * </p> * * @param rating The {@link TvContentRating} to check. diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index e3292b6..4efbc30 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -300,7 +300,7 @@ public abstract class TvInputService extends Service { if (eventType == null) { throw new IllegalArgumentException("eventType should not be null."); } - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -319,7 +319,7 @@ public abstract class TvInputService extends Service { * @param channelUri The URI of a channel. */ public void notifyChannelRetuned(final Uri channelUri) { - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -351,7 +351,7 @@ public abstract class TvInputService extends Service { trackIdSet.clear(); // TODO: Validate the track list. - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -375,7 +375,7 @@ public abstract class TvInputService extends Service { * @see #onSelectTrack */ public void notifyTrackSelected(final int type, final String trackId) { - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -393,7 +393,7 @@ public abstract class TvInputService extends Service { * been started. */ public void notifyVideoAvailable() { - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -423,7 +423,7 @@ public abstract class TvInputService extends Service { || reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) { throw new IllegalArgumentException("Unknown reason: " + reason); } - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -462,7 +462,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentAllowed() { - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -502,7 +502,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentBlocked(final TvContentRating rating) { - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -531,7 +531,7 @@ public abstract class TvInputService extends Service { if (left > right || top > bottm) { throw new IllegalArgumentException("Invalid parameter"); } - mHandler.post(new Runnable() { + runOnMainThread(new Runnable() { @Override public void run() { try { @@ -1049,6 +1049,14 @@ public abstract class TvInputService extends Service { private void setSessionCallback(ITvInputSessionCallback callback) { mSessionCallback = callback; } + + private final void runOnMainThread(Runnable action) { + if (mHandler.getLooper().isCurrentThread()) { + action.run(); + } else { + mHandler.post(action); + } + } } /** diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml index 5c90fd0..3fb3fd4 100644 --- a/packages/BackupRestoreConfirmation/res/values/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values/strings.xml @@ -44,6 +44,8 @@ <string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string> <!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. --> <string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string> + <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. --> + <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string> <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. --> <string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string> diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java index 82ac8cb..c2bb90c 100644 --- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java +++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java @@ -28,6 +28,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.storage.IMountService; +import android.os.storage.StorageManager; import android.util.Log; import android.util.Slog; import android.view.View; @@ -182,25 +183,14 @@ public class BackupRestoreConfirmation extends Activity { // We vary the password prompt depending on whether one is predefined, and whether // the device is encrypted. mIsEncrypted = deviceIsEncrypted(); - if (mIsEncrypted) { - Log.d(TAG, "Device is encrypted: requiring encryption pw"); - TextView pwPrompt = (TextView) findViewById(R.id.password_desc); - // this password is mandatory; we hide the other options during backup - if (layoutId == R.layout.confirm_backup) { - pwPrompt.setText(R.string.device_encryption_backup_text); - TextView tv = (TextView) findViewById(R.id.enc_password); - tv.setVisibility(View.GONE); - tv = (TextView) findViewById(R.id.enc_password_desc); - tv.setVisibility(View.GONE); - } else { - pwPrompt.setText(R.string.device_encryption_restore_text); - } - } else if (!haveBackupPassword()) { + if (!haveBackupPassword()) { curPwDesc.setVisibility(View.GONE); mCurPassword.setVisibility(View.GONE); if (layoutId == R.layout.confirm_backup) { TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc); - encPwDesc.setText(R.string.backup_enc_password_optional); + encPwDesc.setText(mIsEncrypted + ? R.string.backup_enc_password_required + : R.string.backup_enc_password_optional); } } @@ -246,8 +236,7 @@ public class BackupRestoreConfirmation extends Activity { mDidAcknowledge = true; try { - CharSequence encPassword = (mIsEncrypted) - ? mCurPassword.getText() : mEncPassword.getText(); + CharSequence encPassword = mEncPassword.getText(); mBackupManager.acknowledgeFullBackupOrRestore(mToken, allow, String.valueOf(mCurPassword.getText()), @@ -261,7 +250,10 @@ public class BackupRestoreConfirmation extends Activity { boolean deviceIsEncrypted() { try { - return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE); + return mMountService.getEncryptionState() + != IMountService.ENCRYPTION_STATE_NONE + && mMountService.getPasswordType() + != StorageManager.CRYPT_TYPE_DEFAULT; } catch (Exception e) { // If we can't talk to the mount service we have a serious problem; fail // "secure" i.e. assuming that the device is encrypted. diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index fae30e5..1f28324 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -16,7 +16,7 @@ package com.android.defcontainer; -import static android.net.TrafficStats.MB_IN_BYTES; +import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; import android.app.IntentService; import android.content.Context; @@ -67,8 +67,6 @@ import java.io.OutputStream; public class DefaultContainerService extends IntentService { private static final String TAG = "DefContainer"; - private static final String LIB_DIR_NAME = "lib"; - // TODO: migrate native code unpacking to always be a derivative work private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() { @@ -168,7 +166,7 @@ public class DefaultContainerService extends IntentService { final long sizeBytes; try { pkg = PackageParser.parsePackageLite(packageFile, 0); - sizeBytes = calculateInstalledSizeInner(pkg, isForwardLocked, abiOverride); + sizeBytes = PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride); } catch (PackageParserException | IOException e) { Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e); @@ -253,7 +251,7 @@ public class DefaultContainerService extends IntentService { final PackageParser.PackageLite pkg; try { pkg = PackageParser.parsePackageLite(packageFile, 0); - return calculateInstalledSizeInner(pkg, isForwardLocked, abiOverride); + return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, abiOverride); } catch (PackageParserException | IOException e) { Slog.w(TAG, "Failed to calculate installed size: " + e); return Long.MAX_VALUE; @@ -315,13 +313,12 @@ public class DefaultContainerService extends IntentService { // Calculate container size, rounding up to nearest MB and adding an // extra MB for filesystem overhead - final long sizeBytes = calculateInstalledSizeInner(pkg, handle, isForwardLocked, - abiOverride); - final int sizeMb = ((int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES)) + 1; + final long sizeBytes = PackageHelper.calculateInstalledSize(pkg, handle, + isForwardLocked, abiOverride); // Create new container - final String newMountPath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(), - isExternal); + final String newMountPath = PackageHelper.createSdDir(sizeBytes, newCid, key, + Process.myUid(), isExternal); if (newMountPath == null) { throw new IOException("Failed to create container " + newCid); } @@ -339,8 +336,8 @@ public class DefaultContainerService extends IntentService { // Extract native code final File libraryRoot = new File(targetDir, LIB_DIR_NAME); - final int res = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot, - abiOverride, pkg.multiArch); + final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, + abiOverride); if (res != PackageManager.INSTALL_SUCCEEDED) { throw new IOException("Failed to extract native code, res=" + res); } @@ -415,35 +412,4 @@ public class DefaultContainerService extends IntentService { Os.chmod(targetFile.getAbsolutePath(), 0644); } } - - private long calculateInstalledSizeInner(PackageLite pkg, boolean isForwardLocked, - String abiOverride) throws IOException { - NativeLibraryHelper.Handle handle = null; - try { - handle = NativeLibraryHelper.Handle.create(pkg); - return calculateInstalledSizeInner(pkg, handle, isForwardLocked, abiOverride); - } finally { - IoUtils.closeQuietly(handle); - } - } - - private long calculateInstalledSizeInner(PackageLite pkg, NativeLibraryHelper.Handle handle, - boolean isForwardLocked, String abiOverride) throws IOException { - long sizeBytes = 0; - - // Include raw APKs, and possibly unpacked resources - for (String codePath : pkg.getAllCodePaths()) { - final File codeFile = new File(codePath); - sizeBytes += codeFile.length(); - - if (isForwardLocked) { - sizeBytes += PackageHelper.extractPublicFiles(codeFile, null); - } - } - - // Include all relevant native code - sizeBytes += NativeLibraryHelper.sumNativeBinaries(handle, abiOverride, pkg.multiArch); - - return sizeBytes; - } } diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml index 0d7e6c9..1858261 100644 --- a/packages/Keyguard/res/layout/keyguard_status_view.xml +++ b/packages/Keyguard/res/layout/keyguard_status_view.xml @@ -29,11 +29,11 @@ androidprv:layout_maxHeight="@dimen/keyguard_security_height" android:gravity="center_horizontal|top"> <LinearLayout + android:id="@+id/keyguard_clock_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|top" - android:orientation="vertical" - android:focusable="true"> + android:orientation="vertical" > <TextClock android:id="@+id/clock_view" android:layout_width="wrap_content" diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java index 4ea1c77..c650a0f 100644 --- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java +++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java @@ -76,6 +76,12 @@ public class SampleTrustAgent extends TrustAgentService } @Override + public void onTrustTimeout() { + super.onTrustTimeout(); + Toast.makeText(this, "onTrustTimeout(): timeout expired", Toast.LENGTH_SHORT).show(); + } + + @Override public void onUnlockAttempt(boolean successful) { if (getReportUnlockAttempts(this)) { Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")", diff --git a/packages/SystemUI/res/drawable/ic_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_ringer_mute.xml new file mode 100644 index 0000000..dee6018 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ringer_mute.xml @@ -0,0 +1,24 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z"/> +</vector> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index ca07c87..ef0c9bb 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -67,6 +67,6 @@ android:src="@drawable/ic_lock_24dp" android:scaleType="center" android:tint="#ffffffff" - android:contentDescription="@string/accessibility_unlock_button" /> + android:contentDescription="@string/accessibility_unlock_button_not_secured" /> </com.android.systemui.statusbar.phone.KeyguardBottomAreaView> diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index 5869bf3..5cdf819 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -41,7 +41,8 @@ android:layout_marginEnd="8dp" android:minWidth="132dp" android:text="@string/quick_settings_more_settings" - android:textAppearance="@style/TextAppearance.QS.DetailButton" /> + android:textAppearance="@style/TextAppearance.QS.DetailButton" + android:focusable="true" /> <TextView android:id="@android:id/button1" @@ -50,7 +51,8 @@ android:layout_height="wrap_content" android:minWidth="88dp" android:text="@string/quick_settings_done" - android:textAppearance="@style/TextAppearance.QS.DetailButton" /> + android:textAppearance="@style/TextAppearance.QS.DetailButton" + android:focusable="true"/> </LinearLayout> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml index f3f1918..48bb213 100644 --- a/packages/SystemUI/res/layout/qs_detail_header.xml +++ b/packages/SystemUI/res/layout/qs_detail_header.xml @@ -19,6 +19,7 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:padding="@dimen/qs_panel_padding" + android:visibility="invisible" android:background="@drawable/btn_borderless_rect" > <TextView diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index cc449c5..96f9b91 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -50,10 +50,6 @@ android:visibility="gone" /> - <include - layout="@layout/keyguard_bottom_area" - android:visibility="gone" /> - <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer android:layout_width="match_parent" android:layout_height="match_parent" @@ -101,7 +97,7 @@ android:layout_width="@dimen/notification_panel_width" android:layout_height="match_parent" android:layout_gravity="@integer/notification_panel_layout_gravity" - android:layout_marginBottom="@dimen/close_handle_underlap"/> + android:layout_marginBottom="@dimen/close_handle_underlap" /> <ViewStub android:id="@+id/keyguard_user_switcher" @@ -117,6 +113,10 @@ </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer> + <include + layout="@layout/keyguard_bottom_area" + android:visibility="gone" /> + <include layout="@layout/status_bar_expanded_header" /> <com.android.systemui.statusbar.AlphaOptimizedView diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index aa276bc..f4f26a2 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -36,7 +36,7 @@ android:layout_width="@dimen/multi_user_switch_width_collapsed" android:layout_height="@dimen/status_bar_header_height" android:layout_alignParentEnd="true" - android:background="@drawable/ripple_drawable"> + android:background="@drawable/ripple_drawable" > <ImageView android:id="@+id/multi_user_avatar" android:layout_width="24dp" android:layout_height="24dp" @@ -51,7 +51,7 @@ android:layout_height="@dimen/status_bar_header_height" android:background="@drawable/ripple_drawable" android:src="@drawable/ic_settings" - android:contentDescription="@string/accessibility_desc_settings"/> + android:contentDescription="@string/accessibility_desc_settings" /> <LinearLayout android:id="@+id/system_icons_super_container" android:layout_width="wrap_content" @@ -60,11 +60,11 @@ android:layout_alignWithParentIfMissing="true" android:layout_marginStart="16dp" android:background="@drawable/ripple_drawable" - android:paddingEnd="2dp"> + android:paddingEnd="2dp" > <FrameLayout android:id="@+id/system_icons_container" android:layout_width="wrap_content" android:layout_height="@dimen/status_bar_height" - android:layout_gravity="center_vertical"/> + android:layout_gravity="center_vertical" /> <TextView android:id="@+id/battery_level" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml index f506adc..902b837 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml @@ -21,7 +21,7 @@ android:layout_height="wrap_content" android:visibility="gone" > - <ImageButton + <com.android.systemui.statusbar.DismissViewImageButton android:id="@+id/dismiss_text" android:layout_width="48dp" android:layout_height="48dp" diff --git a/packages/SystemUI/res/layout/volume_panel_item.xml b/packages/SystemUI/res/layout/volume_panel_item.xml index 18b496c..85e3fb3 100644 --- a/packages/SystemUI/res/layout/volume_panel_item.xml +++ b/packages/SystemUI/res/layout/volume_panel_item.xml @@ -29,14 +29,30 @@ android:background="@drawable/btn_borderless_rect" android:contentDescription="@null" /> - <SeekBar - android:id="@+id/seekbar" + <FrameLayout android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="1" - android:paddingBottom="0dp" - android:paddingEnd="16dp" - android:paddingStart="8dp" - android:paddingTop="0dip" /> + android:layout_weight="1" > + <TextView + android:id="@+id/suppressor" + android:visibility="gone" + android:textAppearance="@style/TextAppearance.QS.VolumeSuppressor" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <SeekBar + android:id="@+id/seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="0dp" + android:paddingEnd="16dp" + android:paddingStart="8dp" + android:paddingTop="0dp" /> + + </FrameLayout> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 49169e6..eee7f24 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -23,8 +23,7 @@ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string> <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Κατάργηση από τη λίστα"</string> <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Πληροφορίες εφαρμογής"</string> - <!-- no translation found for status_bar_no_recent_apps (7374907845131203189) --> - <skip /> + <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Οι πρόσφατες οθόνες σας εμφανίζονται εδώ"</string> <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Παράβλεψη πρόσφατων εφαρμογών"</string> <plurals name="status_bar_accessibility_recent_apps"> <item quantity="one" msgid="5854176083865845541">"1 πρόσφατη εφαρμογή"</item> @@ -81,8 +80,7 @@ <string name="accessibility_back" msgid="567011538994429120">"Πίσω"</string> <string name="accessibility_home" msgid="8217216074895377641">"Αρχική σελίδα"</string> <string name="accessibility_menu" msgid="316839303324695949">"Μενού"</string> - <!-- no translation found for accessibility_recent (1606470783629913980) --> - <skip /> + <string name="accessibility_recent" msgid="1606470783629913980">"Πρόσφατες οθόνες"</string> <string name="accessibility_search_light" msgid="1103867596330271848">"Αναζήτηση"</string> <string name="accessibility_camera_button" msgid="8064671582820358152">"Φωτογραφική μηχανή"</string> <string name="accessibility_phone_button" msgid="6738112589538563574">"Τηλέφωνο"</string> @@ -160,8 +158,7 @@ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Πλαίσιο σκίασης ειδοποιήσεων."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Γρήγορες ρυθμίσεις."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"Ρυθμίσεις"</string> - <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> - <skip /> + <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"Πρόσφατες οθόνες."</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Χρήστης <xliff:g id="USER">%s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string> <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Κινητό <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string> @@ -173,8 +170,7 @@ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Κλείσιμο παραθύρου"</string> <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Περισσότερος χρόνος"</string> <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Λιγότερος χρόνος"</string> - <!-- no translation found for accessibility_brightness (8003681285547803095) --> - <skip /> + <string name="accessibility_brightness" msgid="8003681285547803095">"Φωτεινότητα οθόνης"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Τα δεδομένα 2G-3G είναι ανενεργά"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Τα δεδομένα 4G είναι ανενεργά"</string> <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Τα δεδομένα κινητής τηλεφωνίας είναι ανενεργά"</string> @@ -246,8 +242,7 @@ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Χρησιμοποιούνται <xliff:g id="DATA_USED">%s</xliff:g>"</string> <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Όριο <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string> - <!-- no translation found for recents_empty_message (8682129509540827999) --> - <skip /> + <string name="recents_empty_message" msgid="8682129509540827999">"Οι πρόσφατες οθόνες σας εμφανίζονται εδώ"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string> <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string> @@ -267,8 +262,7 @@ <string name="zen_alarm_warning" msgid="6873910860111498041">"Δεν θα ακούτε το ξυπνητήρι σας στις <xliff:g id="ALARM_TIME">%s</xliff:g>"</string> <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string> <string name="speed_bump_explanation" msgid="1288875699658819755">"Λιγότερο επείγουσες ειδοποιήσεις παρακάτω"</string> - <!-- no translation found for notification_tap_again (8524949573675922138) --> - <skip /> + <string name="notification_tap_again" msgid="8524949573675922138">"Αγγίξτε ξανά για άνοιγμα"</string> <string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string> <string name="phone_hint" msgid="3101468054914424646">"Σύρετε προς τα δεξιά για το τηλέφωνο"</string> <string name="camera_hint" msgid="5241441720959174226">"Σύρετε αριστερά για τη φωτογραφική μηχανή"</string> @@ -277,25 +271,19 @@ <string name="interruption_level_priority" msgid="6517366750688942030">"Προτεραιότητα"</string> <string name="interruption_level_all" msgid="1330581184930945764">"Όλα"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string> - <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) --> - <skip /> - <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) --> - <skip /> + <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Εναλλαγή χρήστη"</string> + <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Εμφάνιση προφίλ"</string> <string name="user_add_user" msgid="5110251524486079492">"Προσθήκη χρήστη"</string> <string name="user_new_user_name" msgid="426540612051178753">"Νέος χρήστης"</string> <string name="guest_nickname" msgid="8059989128963789678">"Επισκέπτης"</string> - <!-- no translation found for guest_new_guest (600537543078847803) --> - <skip /> + <string name="guest_new_guest" msgid="600537543078847803">"Προσθήκη επισκέπτη"</string> <string name="guest_exit_guest" msgid="7187359342030096885">"Κατάργηση επισκέπτη"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Έξοδος από την περίοδο σύνδεσης επισκέπτη;"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Η έξοδος από την περίοδο σύνδεσης επισκέπτη θα καταργήσει τα τοπικά δεδομένα."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"Επισκέπτη , καλώς όρισες ξανά!"</string> - <!-- no translation found for guest_wipe_session_message (8476238178270112811) --> - <skip /> - <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) --> - <skip /> - <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) --> - <skip /> + <string name="guest_wipe_session_message" msgid="8476238178270112811">"Θέλετε να συνεχίσετε την περίοδο σύνδεσής σας;"</string> + <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Έναρξη από την αρχή"</string> + <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Ναι, συνέχεια"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Για ένα λεπτό"</item> <item quantity="other" msgid="6924190729213550991">"Για %d λεπτά"</item> @@ -325,6 +313,5 @@ <string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"Είστε συνδεδεμένοι σε VPN (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\").\n\nΟ πάροχος της υπηρεσίας VPN μπορεί να παρακολουθεί τη δραστηριότητα της συσκευής σας και του δικτύου, συμπεριλαμβανομένων των μηνυμάτων ηλεκτρονικού ταχυδρομείου, των εφαρμογών και των ασφαλών ιστότοπων."</string> <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Η διαχ. της συσκευής γίνεται από:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nΟ διαχειριστής μπορεί να παρακ. τη δραστ. του δικτύου, όπως τα μην. ηλ. ταχυδρ., τις εφαρ. και τους ασφ. ιστότ. Για περισ. πληροφορίες, επικοιν. με το διαχειριστή.\n\nΕπίσης, επιτρέψατε στο \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" να ρυθμίσει σύνδεση VPN. Αυτή η εφαρ. μπορεί να παρακ. τη δραστ. του δικτύου."</string> <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Η διαχείριση της συσκευής γίνεται από:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nΟ διαχειριστής μπορεί να παρακολ. τη δραστ. του δικτύου, όπως τα μην. ηλεκ. ταχυδρ., τις εφαρμογές και τους ασφαλείς ιστότοπους. Για περισ. πληροφορίες, επικοιν. με το διαχειριστή.\n\nΕπίσης, είστε συνδεδ. σε VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Ο παροχέας VPN μπορεί να παρακολ. τη δραστ. του δικτύου."</string> - <!-- no translation found for keyguard_indication_trust_disabled (7412534203633528135) --> - <skip /> + <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Η συσκευή θα παραμείνει κλειδωμένη έως ότου την ξεκλειδώσετε μη αυτόματα"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 37c3b7d..bc4bbe0 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ilmoitusalue."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Pika-asetukset."</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"Asetukset"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Käyttäjä: <xliff:g id="USER">%s</xliff:g>."</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"Vieras"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"Poista vieras"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Lopetetaanko vierasistunto?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Vierasistunnon lopettaminen poistaa paikalliset tiedot."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"Tervetuloa takaisin!"</string> diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml index 7a8e741..1ea9cce 100644 --- a/packages/SystemUI/res/values-hy-rAM/strings.xml +++ b/packages/SystemUI/res/values-hy-rAM/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ծանուցումների վահանակ:"</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Արագ կարգավորումներ:"</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"Կարգավորումներ"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Օգտվող <xliff:g id="USER">%s</xliff:g>:"</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"Հյուր"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"Հեռացնել հյուրին"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Դուրս գա՞լ հյուրի ռեժիմից:"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Հյուրի ռեժիմից դուրս գալուց հետո ձեր տեղական տվյալները կջնջվեն:"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"Բարի վերադարձ, հյուր:"</string> diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml index 5ca2339..4041dab 100644 --- a/packages/SystemUI/res/values-km-rKH/strings.xml +++ b/packages/SystemUI/res/values-km-rKH/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"បានបដិសេធការជូនដំណឹង"</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ពណ៌ការជូនដំណឹង"</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ការកំណត់រហ័ស។"</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"ការកំណត់"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"អ្នកប្រើ <xliff:g id="USER">%s</xliff:g> ។"</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"ភ្ញៀវ"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"លុបសម័យភ្ញៀវ"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"ចេញពីសម័យភ្ញៀវ?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"ការចេញពីសម័យភ្ញៀវនឹងលុបទិន្នន័យមូលដ្ឋាន។"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"សូមស្វាគមន៍ការត្រឡប់មកវិញ, ភ្ញៀវ!"</string> diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml index f7dfb89..ab76d24 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings.xml @@ -168,8 +168,7 @@ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ປິດແຖບ"</string> <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"ເພີ່ມເວລາ"</string> <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"ຫຼຸດເວລາ"</string> - <!-- no translation found for accessibility_brightness (8003681285547803095) --> - <skip /> + <string name="accessibility_brightness" msgid="8003681285547803095">"ຄວາມແຈ້ງຂອງຈໍ"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"ຂໍ້ມູນ 2G-3G ແມ່ນປິດ"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"ຂໍ້ມູນ 4G ແມ່ນປິດ"</string> <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ຂໍ້ມູນມືຖືຖືກປິດ"</string> @@ -261,8 +260,7 @@ <string name="zen_alarm_warning" msgid="6873910860111498041">"ທ່ານຈະບໍ່ໄດ້ຍິນສຽງໂມງປຸກໃນເວລາ <xliff:g id="ALARM_TIME">%s</xliff:g>"</string> <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string> <string name="speed_bump_explanation" msgid="1288875699658819755">"ການແຈ້ງເຕືອນທີ່ສຳຄັນໜ້ອຍກວ່າຢູ່ດ້ານລຸ່ມ"</string> - <!-- no translation found for notification_tap_again (8524949573675922138) --> - <skip /> + <string name="notification_tap_again" msgid="8524949573675922138">"ແຕະອີກເທື່ອນຶ່ງເພື່ອເປີດ"</string> <string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນຂຶ້ນເພື່ອປົດລັອກ"</string> <string name="phone_hint" msgid="3101468054914424646">"ປັດຂວາເພື່ອໃຊ້ໂທລະສັບ"</string> <string name="camera_hint" msgid="5241441720959174226">"ປັດຊ້າຍເພື່ອໃຊ້ກ້ອງ"</string> @@ -271,10 +269,8 @@ <string name="interruption_level_priority" msgid="6517366750688942030">"ລະດັບຄວາມສຳຄັນ"</string> <string name="interruption_level_all" msgid="1330581184930945764">"ທັງໝົດ"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳລັງສາກໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າຈະເຕັມ)"</string> - <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) --> - <skip /> - <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) --> - <skip /> + <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ສະລັບຜູ່ໃຊ້"</string> + <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ສະແດງໂປຣໄຟລ໌"</string> <string name="user_add_user" msgid="5110251524486079492">"ເພີ່ມຜູ່ໃຊ້"</string> <string name="user_new_user_name" msgid="426540612051178753">"ຜູ່ໃຊ້ໃໝ່"</string> <string name="guest_nickname" msgid="8059989128963789678">"ແຂກ"</string> @@ -283,12 +279,9 @@ <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"ສິ້ນສຸດການນຳໃຊ້ຂອງຜູ່ຢ້ຽມຢາມບໍ່?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"ການອອກຈາກເຊດຊັນຜູ່ຢ້ຽມຢາມຈະເປັນການລຶບຂໍ້ມູນໃນເຄື່ອງອອ."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"ຍິນດີຕ້ອນຮັບກັບມາ, ຜູ່ຢ້ຽມຢາມ!"</string> - <!-- no translation found for guest_wipe_session_message (8476238178270112811) --> - <skip /> - <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) --> - <skip /> - <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) --> - <skip /> + <string name="guest_wipe_session_message" msgid="8476238178270112811">"ທ່ານຕ້ອງການສືບຕໍ່ເຊດຊັນຂອງທ່ານບໍ່?"</string> + <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"ເລີ່ມຕົ້ນໃຫມ່"</string> + <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"ຕົກລົງ, ດຳເນີນການຕໍ່"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"ເປັນເວລານຶ່ງນາທີ"</item> <item quantity="other" msgid="6924190729213550991">"ເປັນເວລາ %d ນາທີ"</item> diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml index 7cd48a0..4a665b6 100644 --- a/packages/SystemUI/res/values-mn-rMN/strings.xml +++ b/packages/SystemUI/res/values-mn-rMN/strings.xml @@ -168,8 +168,7 @@ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Самбарыг хаах"</string> <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Цаг нэмэх"</string> <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Цаг хасах"</string> - <!-- no translation found for accessibility_brightness (8003681285547803095) --> - <skip /> + <string name="accessibility_brightness" msgid="8003681285547803095">"Дэлгэцийн гэрэлтэлт"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G дата идэвхгүй"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G дата идэвхгүй"</string> <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Үүрэн дата идэвхгүй"</string> @@ -261,8 +260,7 @@ <string name="zen_alarm_warning" msgid="6873910860111498041">"Та <xliff:g id="ALARM_TIME">%s</xliff:g>-д өөрийн сэрүүлгээ сонсохгүй"</string> <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string> <string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string> - <!-- no translation found for notification_tap_again (8524949573675922138) --> - <skip /> + <string name="notification_tap_again" msgid="8524949573675922138">"Нээхийн тулд дахин хүрнэ үү"</string> <string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string> <string name="phone_hint" msgid="3101468054914424646">"Утас гаргахын тулд баруун шударна уу"</string> <string name="camera_hint" msgid="5241441720959174226">"Камер гаргахын тулд зүүн шударна уу"</string> @@ -271,10 +269,8 @@ <string name="interruption_level_priority" msgid="6517366750688942030">"Нэн тэргүүний"</string> <string name="interruption_level_all" msgid="1330581184930945764">"Бүгд"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> - <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) --> - <skip /> - <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) --> - <skip /> + <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Хэрэглэгчийг сэлгэх"</string> + <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"Профайлыг харуулах"</string> <string name="user_add_user" msgid="5110251524486079492">"Хэрэглэгч нэмэх"</string> <string name="user_new_user_name" msgid="426540612051178753">"Шинэ хэрэглэгч"</string> <string name="guest_nickname" msgid="8059989128963789678">"Зочин"</string> @@ -283,12 +279,9 @@ <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Зочны нэвтрэлтээс гарч байна уу?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Зочны нэвтрэлтээс гарснаар локал датаг арилгах болно."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"Тавтай морилно уу!"</string> - <!-- no translation found for guest_wipe_session_message (8476238178270112811) --> - <skip /> - <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) --> - <skip /> - <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) --> - <skip /> + <string name="guest_wipe_session_message" msgid="8476238178270112811">"Та үргэлжлүүлэхийг хүсэж байна уу?"</string> + <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Дахин эхлүүлэх"</string> + <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Тийм, үргэлжлүүлэх"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item> <item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item> diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml index f4b29f6..2effb6b 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bidai pemberitahuan."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Tetapan pantas."</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"Tetapan"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Pengguna <xliff:g id="USER">%s</xliff:g>."</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"Tetamu"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"Alih keluar tetamu"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Keluar dari sesi tetamu?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Data tempatan akan dialih keluar apabila anda keluar dari sesi tetamu."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"Selamat kembali, tetamu!"</string> diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml index f6a89e0..d8d71a8 100644 --- a/packages/SystemUI/res/values-my-rMM/strings.xml +++ b/packages/SystemUI/res/values-my-rMM/strings.xml @@ -23,8 +23,7 @@ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"ရှင်းလင်းရန်"</string> <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"စာရင်းမှ ဖယ်မည်"</string> <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"အပ်ပလီကေးရှင်း အချက်အလက်များ"</string> - <!-- no translation found for status_bar_no_recent_apps (7374907845131203189) --> - <skip /> + <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"သင်၏ မကြာမီက မျက်နှာပြင်များ ဒီမှာ ပေါ်လာကြမည်"</string> <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"လတ်တလောအပ်ပလီကေးရှင်းများအား ဖယ်ထုတ်မည်"</string> <!-- String.format failed for translation --> <!-- no translation found for status_bar_accessibility_recent_apps:other (1040784359794890744) --> @@ -79,8 +78,7 @@ <string name="accessibility_back" msgid="567011538994429120">"နောက်သို့"</string> <string name="accessibility_home" msgid="8217216074895377641">"ပင်မစာမျက်နှာ"</string> <string name="accessibility_menu" msgid="316839303324695949">"မီနူး"</string> - <!-- no translation found for accessibility_recent (1606470783629913980) --> - <skip /> + <string name="accessibility_recent" msgid="1606470783629913980">"မကြာမီက မျက်နှာပြင်များ"</string> <string name="accessibility_search_light" msgid="1103867596330271848">"ရှာဖွေရန်"</string> <string name="accessibility_camera_button" msgid="8064671582820358152">"ကင်မရာ"</string> <string name="accessibility_phone_button" msgid="6738112589538563574">"ဖုန်း"</string> @@ -156,8 +154,7 @@ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"အကြောင်းကြားစာအကွက်"</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"အမြန်လုပ် အပြင်အဆင်"</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"ဆက်တင်များ"</string> - <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> - <skip /> + <string name="accessibility_desc_recent_apps" msgid="8376953390514779637">"မကြာမီက မျက်နှာပြင်များ"</string> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"သုံးစွဲသူ <xliff:g id="USER">%s</xliff:g>."</string> <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string> <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"မိုဘိုင်းလ် <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string> @@ -169,8 +166,7 @@ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ပိတ်ရန် အကွက်"</string> <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"အချိန် တိုးရန်"</string> <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"အချိန် လျှော့ရန်"</string> - <!-- no translation found for accessibility_brightness (8003681285547803095) --> - <skip /> + <string name="accessibility_brightness" msgid="8003681285547803095">"တောက်ပမှုကို ပြရန်"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ဒေတာ ပိတ်ထား"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ဒေတာ ပိတ်ထား"</string> <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ဆယ်လူလာ ဒေတာကို ပိတ်ထား"</string> @@ -242,8 +238,7 @@ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> သုံးထား"</string> <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ကန့်သတ်ချက်"</string> <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string> - <!-- no translation found for recents_empty_message (8682129509540827999) --> - <skip /> + <string name="recents_empty_message" msgid="8682129509540827999">"သင်၏ မကြာမီက မျက်နှာပြင်များ ဒီမှာ ပေါ်လာကြမည်"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"အပလီကေးရှင်း အင်ဖို"</string> <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"appသို့ သော့ခတ်ထားရန်"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string> @@ -263,8 +258,7 @@ <string name="zen_alarm_warning" msgid="6873910860111498041">"သင်သည် သင်၏ <xliff:g id="ALARM_TIME">%s</xliff:g> နှိုးစက်ကို ကြားရမည် မဟုတ်"</string> <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string> <string name="speed_bump_explanation" msgid="1288875699658819755">"အရေးပါမှု နည်းသည့် အကြောင်းကြားချက်များ အောက်မှာ"</string> - <!-- no translation found for notification_tap_again (8524949573675922138) --> - <skip /> + <string name="notification_tap_again" msgid="8524949573675922138">"ဖွင့်ရန် ထပ်ပြီး ထိပါ"</string> <string name="keyguard_unlock" msgid="8043466894212841998">"သော့ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string> <string name="phone_hint" msgid="3101468054914424646">"ဖုန်း အတွက် ညာသို့ ပွတ်ဆွဲပါ"</string> <string name="camera_hint" msgid="5241441720959174226">"ကင်မရာ အတွက် ဘယ်သို့ ပွတ်ဆွဲပါ"</string> @@ -273,25 +267,19 @@ <string name="interruption_level_priority" msgid="6517366750688942030">"ဦးစားပေးမှု"</string> <string name="interruption_level_all" msgid="1330581184930945764">"အားလုံး"</string> <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> အပြည့် အထိ) အားသွင်းနေ"</string> - <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) --> - <skip /> - <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) --> - <skip /> + <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string> + <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"ပရိုဖိုင်ကို ပြရန်"</string> <string name="user_add_user" msgid="5110251524486079492">"သုံးသူ ထပ်ထည့်ရန်"</string> <string name="user_new_user_name" msgid="426540612051178753">"အသုံးပြုသူ အသစ်"</string> <string name="guest_nickname" msgid="8059989128963789678">"ဧည့်သည်"</string> - <!-- no translation found for guest_new_guest (600537543078847803) --> - <skip /> + <string name="guest_new_guest" msgid="600537543078847803">"ဧည့်သည့်ကို ထည့်ပေးရန်"</string> <string name="guest_exit_guest" msgid="7187359342030096885">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"ဧည့်သည် ချိတ်ဆက်မှုထဲက ထွက်မလား?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"ဧည့်သည် ချိတ်ဆက်မှု ထဲမှ ထွက်လိုက်ခြင်းက စက်တွင်း ဒေတာကို ဖယ်ရှားပစ်မည်။"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"ပြန်လာတာ ကြိုဆိုပါသည်၊ ဧည့်သည်!"</string> - <!-- no translation found for guest_wipe_session_message (8476238178270112811) --> - <skip /> - <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) --> - <skip /> - <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) --> - <skip /> + <string name="guest_wipe_session_message" msgid="8476238178270112811">"သင်သည် သင်၏ ချိတ်ဆက်မှုကို ဆက်ပြုလုပ် လိုပါသလား?"</string> + <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"အစမှ ပြန်စပါ"</string> + <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"ဟုတ်ကဲ့၊ ဆက်လုပ်ပါ"</string> <plurals name="zen_mode_duration_minutes"> <item quantity="one" msgid="9040808414992812341">"တစ်မိနစ် အတွင်း"</item> <item quantity="other" msgid="6924190729213550991">"%d မိနစ် အတွင်း"</item> @@ -319,6 +307,5 @@ <string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"VPN (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\") ကို သင်ချိတ်ဆက်မိ၏။\n\nသင့် VPN ဝန်ဆောင်မှုပေးသူသည် သင့်စက်ပစ္စည်းနှင့် အီးမေးများ၊ app များ နှင့် လုံခြုံသည့်ဝက်ဘ်ဆိုက် အပါအဝင် ကွန်ယက် လှုပ်ှရားမှုများကို စောင့်ကြည့်နိုင်သည်။"</string> <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"ဒီကိရိယာကို စီမံကွပ်ကဲသူမှာ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nသင်၏ စီမံအုပ်ချုပ်သူက သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို၊ အီးမေးလ်များ၊ appများ နှင့် လုံခြုံသည့် ဝက်ဘ်ဆိုက်များ အပါအဝင်ကို၊ စောင့်ကြပ် နိုင်ပါသည်။ အချက်အလက်များ ပိုပြီး ရယူရန်၊ သင်၏ စီမံအုပ်ချုပ်သူကို ဆက်သွယ်ပါ။\n\n ထို့အပြင် သင်သည် \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" အား VPN ချိတ်ဆက်မှု စဖွင့်လုပ်ကိုင်ရန် ခွင့်ပြုခဲ့သည်။ ဒီ appကပါ သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို စောင့်ကြပ် နိုင်ပါသည်။"</string> <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"ဒီကိရိယာကို စီမံကွပ်ကဲသူမှာ:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nသင်၏ စီမံအုပ်ချုပ်သူက သင်၏ ကွန်ရက် လှုပ်ရှားမှုကို၊ အီးမေးလ်များ၊ appများ နှင့် လုံခြုံသည့် ဝက်ဘ်ဆိုက်များ အပါအဝင်ကို၊ စောင့်ကြပ် နိုင်ပါသည်။ အချက်အလက်များ ပိုပြီး ရယူရန်၊ သင်၏ စီမံအုပ်ချုပ်သူကို ဆက်သွယ်ပါ။\n\nထို့အပြင်၊ သင်သည် VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") သို့ ချိတ်ဆက်ထားသည်။ သင်၏ VPN ဝန်ဆောင်မှုကို စီမံပေးသူကပါ ကွန်ရက် လှုပ်ရှားမှုများကို စောင့်ကြပ်နိုင်သေးသည်။"</string> - <!-- no translation found for keyguard_indication_trust_disabled (7412534203633528135) --> - <skip /> + <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"သင်က လက်ဖြင့် သော့မဖွင့်မချင်း ကိရိယာမှာ သော့ပိတ်လျက် ရှိနေမည်"</string> </resources> diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml index 5f2c7ba..e44a5bc 100644 --- a/packages/SystemUI/res/values-ne-rNP/strings.xml +++ b/packages/SystemUI/res/values-ne-rNP/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना कक्ष।"</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"द्रुत सेटिङहरू"</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"सेटिङहरू"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"प्रयोगकर्ता <xliff:g id="USER">%s</xliff:g>।"</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"अतिथि"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"अतिथि हटाउनुहोस्"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"अतिथि सत्र बाहिरिंदै छ?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"अतिथि सत्र अन्त्यले स्थानीय डेटा हटाउने छ।"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"पुनः स्वागत, अतिथि!"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 51c0526..4f6ccc8 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -159,8 +159,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Aba de notificações."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configurações rápidas."</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"Configurações"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuário <xliff:g id="USER">%s</xliff:g>."</string> @@ -287,8 +286,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"Convidado"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"Remover convidado"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"Sair da sessão de convidado?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"Sair da sessão de convidado removerá os dados locais."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"Bem-vindo, convidado."</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 9da5cc5..dba66e7 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Fereastră pentru notificări."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Setări rapide."</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"Setări"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilizatorul <xliff:g id="USER">%s</xliff:g>."</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"Invitat"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"Eliminați invitatul"</string> <!-- no translation found for guest_exit_guest_dialog_title (7587460301980067285) --> <skip /> <!-- no translation found for guest_exit_guest_dialog_message (10255285459589280) --> diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml index 18601a0..d65d765 100644 --- a/packages/SystemUI/res/values-si-rLK/strings.xml +++ b/packages/SystemUI/res/values-si-rLK/strings.xml @@ -157,8 +157,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්රභා කරඇත."</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"දැනුම්දීම් ආවරණය."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ක්ෂණික සැකසීම්."</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"සැකසීම්"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"පරිශීලකයා <xliff:g id="USER">%s</xliff:g>."</string> @@ -285,8 +284,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"අමුත්තා"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"අමුත්තාන් ඉවත් කරන්න"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"අමුත්තාගේ සැසියෙන් පිටවෙයිද?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"අමුත්තාගේ සැසිය අවසන් කිරීමෙන් පෙදෙසි දත්ත සියල්ලම පිට කරයි."</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"නැවත සාදරයෙන් පිළිගනිමු, අමුත්තා!"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index c09209c..bca8966 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -159,8 +159,7 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知栏。"</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快捷设置。"</string> - <!-- no translation found for accessibility_desc_settings (3417884241751434521) --> - <skip /> + <string name="accessibility_desc_settings" msgid="3417884241751434521">"设置"</string> <!-- no translation found for accessibility_desc_recent_apps (8376953390514779637) --> <skip /> <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用户:<xliff:g id="USER">%s</xliff:g>。"</string> @@ -287,8 +286,7 @@ <string name="guest_nickname" msgid="8059989128963789678">"访客"</string> <!-- no translation found for guest_new_guest (600537543078847803) --> <skip /> - <!-- no translation found for guest_exit_guest (7187359342030096885) --> - <skip /> + <string name="guest_exit_guest" msgid="7187359342030096885">"移除访客"</string> <string name="guest_exit_guest_dialog_title" msgid="7587460301980067285">"要退出访客模式吗?"</string> <string name="guest_exit_guest_dialog_message" msgid="10255285459589280">"退出访客模式将移除本地数据。"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"访客,欢迎回来!"</string> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 40870bf..dea14e9 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -105,4 +105,5 @@ <color name="search_panel_card_color">#ffffff</color> <color name="keyguard_user_switcher_background_gradient_color">#77000000</color> + <color name="doze_small_icon_background_color">#ff434343</color> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 42d9734..52dc000 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -189,6 +189,9 @@ <!-- Doze: interval between pulses when following the notification light --> <integer name="doze_notification_pulse_interval">30000</integer> + <!-- Doze: alpha to apply to small icons when dozing --> + <integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff --> + <!-- Volume: time to delay dismissing the volume panel after a click is performed --> <integer name="volume_panel_dismiss_delay">200</integer> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 6418930..4e93cd8 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -34,5 +34,6 @@ <item type="id" name="alpha_animator_start_value_tag"/> <item type="id" name="top_inset_animator_start_value_tag"/> <item type="id" name="height_animator_start_value_tag"/> + <item type="id" name="doze_saved_filter_tag"/> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8f05f7b..120af1d 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -213,8 +213,6 @@ <string name="accessibility_camera_button">Camera</string> <!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_button">Phone</string> - <!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_unlock_button">Unlock</string> <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] --> <string name="unlock_label">unlock</string> <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] --> @@ -222,6 +220,17 @@ <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] --> <string name="camera_label">open camera</string> + <!-- Content description of the lock icon when device is secured (lock closed) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_unlock_button_secured">Device secured.</string> + <!-- Content description of the lock icon when device is not secured (lock open) and trust not managed (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_unlock_button_not_secured">Device not secured.</string> + <!-- Content description of the lock icon when device is secured (lock closed) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_unlock_button_secured_trust_managed">Device secured, trust agent active.</string> + <!-- Content description of the lock icon when device is not secured (lock open) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_unlock_button_not_secured_trust_managed">Device not secured, trust agent active.</string> + <!-- Content description of the lock icon when face unlock is running (face icon) and trust managed (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_unlock_button_face_unlock_running">Face detection running, trust agent active.</string> + <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_ime_switch_button">Switch input method button.</string> <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> @@ -858,4 +867,6 @@ <!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] --> <string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string> + <!-- Indication that the current volume and other effects (vibration) are being suppressed by a third party, such as a notification listener. [CHAR LIMIT=30] --> + <string name="muted_by">Muted by <xliff:g id="third_party">%1$s</xliff:g></string> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 48a031a..8c1ac9f 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -141,6 +141,11 @@ <item name="android:textColor">@color/system_accent_color</item> </style> + <style name="TextAppearance.QS.VolumeSuppressor"> + <item name="android:textSize">14sp</item> + <item name="android:textColor">@color/qs_tile_text</item> + </style> + <style name="TextAppearance.QS.DetailButton"> <item name="android:textSize">14sp</item> <item name="android:textAllCaps">true</item> diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index 74c0328..fe1e5db 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -76,6 +76,7 @@ public class DozeService extends DreamService { private PendingIntent mNotificationPulseIntent; private int mMultipulseCount; private int mNotificationPulseInterval; + private boolean mPowerSaveActive; public DozeService() { if (DEBUG) Log.d(mTag, "new DozeService()"); @@ -94,6 +95,7 @@ public class DozeService extends DreamService { pw.print(" mNotificationLightOn: "); pw.println(mNotificationLightOn); pw.print(" mMultipulseCount: "); pw.println(mMultipulseCount); pw.print(" mNotificationPulseInterval: "); pw.println(mNotificationPulseInterval); + pw.print(" mPowerSaveActive: "); pw.println(mPowerSaveActive); } @Override @@ -141,7 +143,13 @@ public class DozeService extends DreamService { @Override public void onDreamingStarted() { super.onDreamingStarted(); - if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze()); + mPowerSaveActive = mHost != null && mHost.isPowerSaveActive(); + if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze() + " mPowerSaveActive=" + + mPowerSaveActive); + if (mPowerSaveActive) { + finishToSavePower(); + return; + } mDreaming = true; listenForPulseSignals(true); requestDoze(); @@ -232,6 +240,11 @@ public class DozeService extends DreamService { } } + private void finishToSavePower() { + Log.w(mTag, "Exiting ambient mode due to low power battery saver"); + finish(); + } + private void listenForPulseSignals(boolean listen) { if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen); mSigMotionSensor.setListening(listen); @@ -329,6 +342,14 @@ public class DozeService extends DreamService { mNotificationLightOn = on; rescheduleNotificationPulse(); } + + @Override + public void onPowerSaveChanged(boolean active) { + mPowerSaveActive = active; + if (mPowerSaveActive && mDreaming) { + finishToSavePower(); + } + } }; public interface Host { @@ -337,11 +358,13 @@ public class DozeService extends DreamService { void requestDoze(DozeService dozeService); void requestPulse(int pulses, boolean delayed, DozeService dozeService); void dozingStopped(DozeService dozeService); + boolean isPowerSaveActive(); public interface Callback { void onNewNotifications(); void onBuzzBeepBlinked(); void onNotificationLight(boolean on); + void onPowerSaveChanged(boolean active); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index c1fd509..a2136d2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -71,6 +71,7 @@ public class QSPanel extends ViewGroup { private QSTileHost mHost; private QSFooter mFooter; + private boolean mGridContentVisible = true; public QSPanel(Context context) { this(context, null); @@ -189,13 +190,13 @@ public class QSPanel extends ViewGroup { mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget(); } - private void setTileVisibility(View v, boolean visible) { - mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visible ? 1 : 0, 0, v).sendToTarget(); + private void setTileVisibility(View v, int visibility) { + mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visibility, 0, v).sendToTarget(); } - private void handleSetTileVisibility(View v, boolean visible) { - if (visible == (v.getVisibility() == VISIBLE)) return; - v.setVisibility(visible ? VISIBLE : GONE); + private void handleSetTileVisibility(View v, int visibility) { + if (visibility == v.getVisibility()) return; + v.setVisibility(visibility); } public void setTiles(Collection<QSTile<?>> tiles) { @@ -219,7 +220,14 @@ public class QSPanel extends ViewGroup { final QSTile.Callback callback = new QSTile.Callback() { @Override public void onStateChanged(QSTile.State state) { - setTileVisibility(r.tileView, state.visible); + int visibility = state.visible ? VISIBLE : GONE; + if (state.visible && !mGridContentVisible) { + + // We don't want to show it if the content is hidden, + // then we just set it to invisible, to ensure that it gets visible again + visibility = INVISIBLE; + } + setTileVisibility(r.tileView, visibility); r.tileView.onStateChanged(state); } @Override @@ -317,7 +325,9 @@ public class QSPanel extends ViewGroup { mDetail.bringToFront(); mDetailContent.addView(r.detailView); setDetailRecord(r); + listener = mHideGridContentWhenDone; } else { + setGridContentVisibility(true); listener = mTeardownDetailWhenDone; fireScanStateChanged(false); } @@ -325,6 +335,18 @@ public class QSPanel extends ViewGroup { mClipper.animateCircularClip(x, y, show, listener); } + private void setGridContentVisibility(boolean visible) { + int newVis = visible ? VISIBLE : INVISIBLE; + for (int i = 0; i < mRecords.size(); i++) { + TileRecord tileRecord = mRecords.get(i); + if (tileRecord.tileView.getVisibility() != GONE) { + tileRecord.tileView.setVisibility(newVis); + } + } + mBrightnessView.setVisibility(newVis); + mGridContentVisible = visible; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); @@ -448,7 +470,7 @@ public class QSPanel extends ViewGroup { if (msg.what == SHOW_DETAIL) { handleShowDetail((Record)msg.obj, msg.arg1 != 0); } else if (msg.what == SET_TILE_VISIBILITY) { - handleSetTileVisibility((View)msg.obj, msg.arg1 != 0); + handleSetTileVisibility((View)msg.obj, msg.arg1); } } } @@ -473,6 +495,13 @@ public class QSPanel extends ViewGroup { }; }; + private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + setGridContentVisibility(false); + } + }; + public interface Callback { void onShowingDetail(QSTile.DetailAdapter detail); void onToggleStateChanged(boolean state); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index 2cc1f07..20fd5a0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -50,6 +50,7 @@ public class QSTileView extends ViewGroup { private final int mTilePaddingTopPx; private final int mTilePaddingBelowIconPx; private final int mDualTileVerticalPaddingPx; + private final View mTopBackgroundView; private TextView mLabel; private QSDualTileLabel mDualLabel; @@ -72,6 +73,9 @@ public class QSTileView extends ViewGroup { recreateLabel(); setClipChildren(false); + mTopBackgroundView = new View(context); + addView(mTopBackgroundView); + mIcon = createIcon(); addView(mIcon); @@ -82,7 +86,6 @@ public class QSTileView extends ViewGroup { addView(mDivider); setClickable(true); - setBackground(getTileBackground()); } private void recreateLabel() { @@ -104,7 +107,6 @@ public class QSTileView extends ViewGroup { mDualLabel = new QSDualTileLabel(mContext); mDualLabel.setId(android.R.id.title); mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect); - mDualLabel.setFirstLineCaret(res.getDrawable(R.drawable.qs_dual_tile_caret)); mDualLabel.setTextColor(res.getColor(R.color.qs_tile_text)); mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx); mDualLabel.setTypeface(CONDENSED); @@ -112,6 +114,7 @@ public class QSTileView extends ViewGroup { res.getDimensionPixelSize(R.dimen.qs_tile_text_size)); mDualLabel.setClickable(true); mDualLabel.setOnClickListener(mClickSecondary); + mDualLabel.setFocusable(true); if (labelText != null) { mDualLabel.setText(labelText); } @@ -143,11 +146,36 @@ public class QSTileView extends ViewGroup { if (changed) { recreateLabel(); } - setOnClickListener(mClickPrimary); + Drawable tileBackground = getTileBackground(); + if (tileBackground instanceof RippleDrawable) { + setRipple((RippleDrawable) tileBackground); + } + if (dual) { + mTopBackgroundView.setOnClickListener(mClickPrimary); + setOnClickListener(null); + setClickable(false); + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + mTopBackgroundView.setBackground(tileBackground); + } else { + mTopBackgroundView.setOnClickListener(null); + mTopBackgroundView.setClickable(false); + setOnClickListener(mClickPrimary); + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + setBackground(tileBackground); + } + mTopBackgroundView.setFocusable(dual); + setFocusable(!dual); mDivider.setVisibility(dual ? VISIBLE : GONE); postInvalidate(); } + private void setRipple(RippleDrawable tileBackground) { + mRipple = tileBackground; + if (getWidth() != 0) { + updateRippleSize(getWidth(), getHeight()); + } + } + public void init(OnClickListener clickPrimary, OnClickListener clickSecondary) { mClickPrimary = clickPrimary; mClickSecondary = clickSecondary; @@ -165,9 +193,6 @@ public class QSTileView extends ViewGroup { final TypedArray ta = mContext.obtainStyledAttributes(attrs); final Drawable d = ta.getDrawable(0); ta.recycle(); - if (d instanceof RippleDrawable) { - mRipple = (RippleDrawable) d; - } return d; } @@ -185,6 +210,9 @@ public class QSTileView extends ViewGroup { if (mDual) { mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height)); } + int heightSpec = exactly( + mIconSizePx + mTilePaddingBelowIconPx + mTilePaddingTopPx); + mTopBackgroundView.measure(widthMeasureSpec, heightSpec); setMeasuredDimension(w, h); } @@ -197,17 +225,16 @@ public class QSTileView extends ViewGroup { final int w = getMeasuredWidth(); final int h = getMeasuredHeight(); + layout(mTopBackgroundView, 0, mTileSpacingPx); + int top = 0; top += mTileSpacingPx; top += mTilePaddingTopPx; final int iconLeft = (w - mIcon.getMeasuredWidth()) / 2; layout(mIcon, iconLeft, top); if (mRipple != null) { - // center the touch feedback on the center of the icon, and dial it down a bit - final int cx = w / 2; - final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() / 2 : h / 2; - final int rad = (int)(mIcon.getHeight() * 1.25); - mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad); + updateRippleSize(w, h); + } top = mIcon.getBottom(); top += mTilePaddingBelowIconPx; @@ -218,6 +245,14 @@ public class QSTileView extends ViewGroup { layout(labelView(), 0, top); } + private void updateRippleSize(int width, int height) { + // center the touch feedback on the center of the icon, and dial it down a bit + final int cx = width / 2; + final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() / 2 : height / 2; + final int rad = (int)(mIcon.getHeight() * 1.25f); + mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad); + } + private static void layout(View child, int left, int top) { child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight()); } @@ -256,4 +291,4 @@ public class QSTileView extends ViewGroup { } } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 63c880f..109237b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -77,7 +77,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { @Override protected void handleSecondaryClick() { - showDetail(true); + mHost.startSettingsActivity(BLUETOOTH_SETTINGS); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index b12c6c1..4fc2ee4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -87,11 +87,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { @Override protected void handleSecondaryClick() { - if (!mState.enabled) { - mController.setWifiEnabled(true); - mState.enabled = true; - } - showDetail(true); + mHost.startSettingsActivity(WIFI_SETTINGS); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 3a20b00..e3f034d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1169,8 +1169,8 @@ public abstract class BaseStatusBar extends SystemUI implements final ImageView icon = (ImageView) publicViewLocal.findViewById( com.android.internal.R.id.icon); - final ImageView profileIcon = (ImageView) publicViewLocal.findViewById( - com.android.internal.R.id.profile_icon); + final ImageView profileBadge = (ImageView) publicViewLocal.findViewById( + com.android.internal.R.id.profile_badge_line3); final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(), entry.notification.getUser(), @@ -1189,14 +1189,14 @@ public abstract class BaseStatusBar extends SystemUI implements icon.setPadding(padding, padding, padding, padding); } - if (profileIcon != null) { + if (profileBadge != null) { Drawable profileDrawable = mUserManager.getBadgeForUser(entry.notification.getUser(), 0); if (profileDrawable != null) { - profileIcon.setImageDrawable(profileDrawable); - profileIcon.setVisibility(View.VISIBLE); + profileBadge.setImageDrawable(profileDrawable); + profileBadge.setVisibility(View.VISIBLE); } else { - profileIcon.setVisibility(View.GONE); + profileBadge.setVisibility(View.GONE); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java new file mode 100644 index 0000000..d55b0b3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewImageButton.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import com.android.systemui.R; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; + +public class DismissViewImageButton extends ImageButton { + public DismissViewImageButton(Context context) { + super(context); + } + + public DismissViewImageButton(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public DismissViewImageButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public DismissViewImageButton(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + /** + * This method returns the drawing rect for the view which is different from the regular + * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at + * position 0 and usually the translation is neglected. The standard implementation doesn't + * account for translation. + * + * @param outRect The (scrolled) drawing bounds of the view. + */ + @Override + public void getDrawingRect(Rect outRect) { + super.getDrawingRect(outRect); + float translationX = ((ViewGroup) mParent).getTranslationX(); + float translationY = ((ViewGroup) mParent).getTranslationY(); + outRect.left += translationX; + outRect.right += translationX; + outRect.top += translationY; + outRect.bottom += translationY; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 9ac20a6..7d64325 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -120,6 +120,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { return false; } + @Override + public void setDark(boolean dark, boolean fade) { + super.setDark(dark, fade); + final NotificationContentView showing = getShowingLayout(); + if (showing != null) { + showing.setDark(dark, fade); + } + } + public void setHeightRange(int rowMinHeight, int rowMaxHeight) { mRowMinHeight = rowMinHeight; mRowMaxHeight = rowMaxHeight; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 127ff6c..5c66660 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -17,12 +17,14 @@ package com.android.systemui.statusbar; import android.content.Context; +import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.systemui.R; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import java.util.ArrayList; @@ -262,6 +264,24 @@ public abstract class ExpandableView extends FrameLayout { } /** + * This method returns the drawing rect for the view which is different from the regular + * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at + * position 0 and usually the translation is neglected. Since we are manually clipping this + * view,we also need to subtract the clipTopAmount from the top. This is needed in order to + * ensure that accessibility and focusing work correctly. + * + * @param outRect The (scrolled) drawing bounds of the view. + */ + @Override + public void getDrawingRect(Rect outRect) { + super.getDrawingRect(outRect); + outRect.left += getTranslationX(); + outRect.right += getTranslationX(); + outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight()); + outRect.top += getTranslationY() + getClipTopAmount(); + } + + /** * A listener notifying when {@link #getActualHeight} changes. */ public interface OnHeightChangedListener { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index a030f61..548e7d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -17,15 +17,20 @@ package com.android.systemui.statusbar; import android.content.Context; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; +import android.widget.ImageView; import com.android.systemui.R; @@ -37,6 +42,8 @@ import com.android.systemui.R; public class NotificationContentView extends FrameLayout { private static final long ANIMATION_DURATION_LENGTH = 170; + private static final Paint INVERT_PAINT = createInvertPaint(); + private static final ColorFilter NO_COLOR_FILTER = new ColorFilter(); private final Rect mClipBounds = new Rect(); @@ -50,6 +57,7 @@ public class NotificationContentView extends FrameLayout { private final Interpolator mLinearInterpolator = new LinearInterpolator(); private boolean mContractedVisible = true; + private boolean mDark; private final Paint mFadePaint = new Paint(); @@ -192,4 +200,49 @@ public class NotificationContentView extends FrameLayout { public boolean isContentExpandable() { return mExpandedChild != null; } + + public void setDark(boolean dark, boolean fade) { + if (mDark == dark) return; + mDark = dark; + setImageViewDark(dark, fade, com.android.internal.R.id.right_icon); + setImageViewDark(dark, fade, com.android.internal.R.id.icon); + } + + private void setImageViewDark(boolean dark, boolean fade, int imageViewId) { + // TODO: implement fade + final ImageView v = (ImageView) mContractedChild.findViewById(imageViewId); + final Drawable d = v.getBackground(); + if (dark) { + v.setLayerType(LAYER_TYPE_HARDWARE, INVERT_PAINT); + if (d != null) { + v.setTag(R.id.doze_saved_filter_tag, d.getColorFilter() != null ? d.getColorFilter() + : NO_COLOR_FILTER); + d.setColorFilter(getResources().getColor(R.color.doze_small_icon_background_color), + PorterDuff.Mode.SRC_ATOP); + v.setImageAlpha(getResources().getInteger(R.integer.doze_small_icon_alpha)); + } + } else { + v.setLayerType(LAYER_TYPE_NONE, null); + if (d != null) { + final ColorFilter filter = (ColorFilter) v.getTag(R.id.doze_saved_filter_tag); + if (filter != null) { + d.setColorFilter(filter == NO_COLOR_FILTER ? null : filter); + v.setTag(R.id.doze_saved_filter_tag, null); + } + v.setImageAlpha(0xff); + } + } + } + + private static Paint createInvertPaint() { + final Paint p = new Paint(); + final float[] invert = { + -1f, 0f, 0f, 1f, 1f, + 0f, -1f, 0f, 1f, 1f, + 0f, 0f, -1f, 1f, 1f, + 0f, 0f, 0f, 1f, 0f + }; + p.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(invert))); + return p; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 9408042..7fefa64 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -252,18 +252,21 @@ public class NotificationData { int N = mSortedAndFiltered.size(); pw.print(indent); pw.println("active notifications: " + N); - for (int i = 0; i < N; i++) { - NotificationData.Entry e = mSortedAndFiltered.get(i); - dumpEntry(pw, indent, i, e); + int active; + for (active = 0; active < N; active++) { + NotificationData.Entry e = mSortedAndFiltered.get(active); + dumpEntry(pw, indent, active, e); } int M = mEntries.size(); pw.print(indent); - pw.println("inactive notifications: " + M); + pw.println("inactive notifications: " + (M - active)); + int inactiveCount = 0; for (int i = 0; i < M; i++) { Entry entry = mEntries.valueAt(i); if (!mSortedAndFiltered.contains(entry)) { - dumpEntry(pw, indent, i, entry); + dumpEntry(pw, indent, inactiveCount, entry); + inactiveCount++; } } } @@ -273,8 +276,8 @@ public class NotificationData { pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon); StatusBarNotification n = e.notification; pw.print(indent); - pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" + n - .getScore()); + pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" + + n.getScore()); pw.print(indent); pw.println(" notification=" + n.getNotification()); pw.print(indent); 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 44d8d23..cb2d40a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -377,11 +377,20 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL boolean trustManaged = mUnlockMethodCache.isTrustManaged(); mTrustDrawable.setTrustManaged(trustManaged); - // TODO: Update content description depending on state updateLockIconClickability(); + updateLockIconContentDescription(mUnlockMethodCache.isFaceUnlockRunning(), + mUnlockMethodCache.isMethodInsecure(), trustManaged); } - + private void updateLockIconContentDescription(boolean faceUnlockRunning, boolean insecure, + boolean trustManaged) { + mLockIcon.setContentDescription(getResources().getString( + faceUnlockRunning ? R.string.accessibility_unlock_button_face_unlock_running + : insecure && !trustManaged ? R.string.accessibility_unlock_button_not_secured + : insecure ? R.string.accessibility_unlock_button_not_secured_trust_managed + : !trustManaged ? R.string.accessibility_unlock_button_secured + : R.string.accessibility_unlock_button_secured_trust_managed)); + } public KeyguardAffordanceView getPhoneView() { return mPhoneImageView; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 9188457..e1beb08 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -182,6 +182,7 @@ public class NotificationPanelView extends PanelView implements mClockView = (TextView) findViewById(R.id.clock_view); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); mScrollView.setListener(this); + mScrollView.setFocusable(false); mReserveNotificationSpace = findViewById(R.id.reserve_notification_space); mNotificationContainerParent = findViewById(R.id.notification_container_parent); mNotificationStackScroller = (NotificationStackScrollLayout) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index b3042b9..7158ba1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -752,6 +752,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void onPowerSaveChanged() { mHandler.post(mCheckBarModes); + if (mDozeServiceHost != null) { + mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave()); + } } @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { @@ -2131,6 +2134,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Expand the window to encompass the full screen in anticipation of the drag. // This is only possible to do atomically because the status bar is at the top of the screen! mStatusBarWindowManager.setStatusBarExpanded(true); + mStatusBarView.setFocusable(false); visibilityChanged(true); mWaitingForKeyguardExit = false; @@ -2305,6 +2309,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Shrink the window to the size of the status bar only mStatusBarWindowManager.setStatusBarExpanded(false); + mStatusBarView.setFocusable(true); // Close any "App info" popups that might have snuck on-screen dismissPopups(); @@ -3920,6 +3925,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private DozeService mCurrentDozeService; + public void firePowerSaveChanged(boolean active) { + for (Callback callback : mCallbacks) { + callback.onPowerSaveChanged(active); + } + } + public void fireBuzzBeepBlinked() { for (Callback callback : mCallbacks) { callback.onBuzzBeepBlinked(); @@ -3970,6 +3981,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mHandler.obtainMessage(H.DOZING_STOPPED, dozeService).sendToTarget(); } + @Override + public boolean isPowerSaveActive() { + return mBatteryController != null && mBatteryController.isPowerSave(); + } + private void handleRequestDoze(DozeService dozeService) { mCurrentDozeService = dozeService; if (!mDozing) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index 807a37b..3a110bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -114,6 +114,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private final LayoutValues mCurrentValues = new LayoutValues(); private float mCurrentT; + private boolean mShowingDetail; public StatusBarHeaderView(Context context, AttributeSet attrs) { super(context, attrs); @@ -282,7 +283,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE); mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE); mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE); - mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE); + mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE); if (mSignalCluster != null) { updateSignalClusterDetachment(); } @@ -375,7 +376,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private void updateClickTargets() { mMultiUserSwitch.setClickable(mExpanded); + mMultiUserSwitch.setFocusable(mExpanded); mSystemIconsSuperContainer.setClickable(mExpanded); + mSystemIconsSuperContainer.setFocusable(mExpanded); mAlarmStatus.setClickable(mNextAlarm != null && mNextAlarm.getShowIntent() != null); } @@ -716,6 +719,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL transition(mDateGroup, !showingDetail); transition(mAlarmStatus, !showingDetail); transition(mQsDetailHeader, showingDetail); + mShowingDetail = showingDetail; if (showingDetail) { mQsDetailHeaderTitle.setText(detail.getTitle()); final Boolean toggleState = detail.getToggleState(); @@ -741,8 +745,20 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private void transition(final View v, final boolean in) { if (in) { v.bringToFront(); + v.setVisibility(VISIBLE); } - v.animate().alpha(in ? 1 : 0).withLayer().start(); + v.animate() + .alpha(in ? 1 : 0) + .withLayer() + .withEndAction(new Runnable() { + @Override + public void run() { + if (!in) { + v.setVisibility(INVISIBLE); + } + } + }) + .start(); } }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index ae0291b..499fe0b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -17,11 +17,11 @@ package com.android.systemui.statusbar.policy; import android.app.admin.DevicePolicyManager; import android.content.Context; -import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.IConnectivityManager; +import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.os.RemoteException; @@ -45,6 +45,8 @@ public class SecurityControllerImpl implements SecurityController { .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) .build(); + private static final int NO_NETWORK = -1; + private final Context mContext; private final ConnectivityManager mConnectivityManager; private final IConnectivityManager mConnectivityService = IConnectivityManager.Stub.asInterface( @@ -52,9 +54,9 @@ public class SecurityControllerImpl implements SecurityController { private final DevicePolicyManager mDevicePolicyManager; private final ArrayList<VpnCallback> mCallbacks = new ArrayList<VpnCallback>(); - private boolean mIsVpnEnabled; private VpnConfig mVpnConfig; private String mVpnName; + private int mCurrentVpnNetworkId = NO_NETWORK; public SecurityControllerImpl(Context context) { mContext = context; @@ -69,7 +71,7 @@ public class SecurityControllerImpl implements SecurityController { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("SecurityController state:"); - pw.print(" mIsVpnEnabled="); pw.println(mIsVpnEnabled); + pw.print(" mCurrentVpnNetworkId="); pw.println(mCurrentVpnNetworkId); pw.print(" mVpnConfig="); pw.println(mVpnConfig); pw.print(" mVpnName="); pw.println(mVpnName); } @@ -86,10 +88,7 @@ public class SecurityControllerImpl implements SecurityController { @Override public boolean isVpnEnabled() { - // TODO: Remove once using NetworkCallback for updates. - updateState(); - - return mIsVpnEnabled; + return mCurrentVpnNetworkId != NO_NETWORK; } @Override @@ -138,6 +137,14 @@ public class SecurityControllerImpl implements SecurityController { mCallbacks.add(callback); } + private void setCurrentNetid(int netId) { + if (netId != mCurrentVpnNetworkId) { + mCurrentVpnNetworkId = netId; + updateState(); + fireCallbacks(); + } + } + private void fireCallbacks() { for (VpnCallback callback : mCallbacks) { callback.onVpnStateChanged(); @@ -148,9 +155,6 @@ public class SecurityControllerImpl implements SecurityController { try { mVpnConfig = mConnectivityService.getVpnConfig(); - // TODO: Remove once using NetworkCallback for updates. - mIsVpnEnabled = mVpnConfig != null; - if (mVpnConfig != null && !mVpnConfig.legacy) { mVpnName = VpnConfig.getVpnLabel(mContext, mVpnConfig.user).toString(); } @@ -160,13 +164,25 @@ public class SecurityControllerImpl implements SecurityController { } private final NetworkCallback mNetworkCallback = new NetworkCallback() { - public void onCapabilitiesChanged(android.net.Network network, - android.net.NetworkCapabilities networkCapabilities) { - if (DEBUG) Log.d(TAG, "onCapabilitiesChanged " + networkCapabilities); - mIsVpnEnabled = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); - updateState(); - fireCallbacks(); - } + @Override + public void onAvailable(Network network) { + NetworkCapabilities networkCapabilities = + mConnectivityManager.getNetworkCapabilities(network); + if (DEBUG) Log.d(TAG, "onAvailable " + network.netId + " : " + networkCapabilities); + if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { + setCurrentNetid(network.netId); + } + }; + + // TODO Find another way to receive VPN lost. This may be delayed depending on + // how long the VPN connection is held on to. + @Override + public void onLost(Network network) { + if (DEBUG) Log.d(TAG, "onLost " + network.netId); + if (mCurrentVpnNetworkId == network.netId) { + setCurrentNetid(NO_NETWORK); + } + }; }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 735fbfc..adb71e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -246,7 +246,6 @@ public class UserSwitcherController { private void switchToUserId(int id) { try { - WindowManagerGlobal.getWindowManagerService().lockNow(null); ActivityManagerNative.getDefault().switchUser(id); } catch (RemoteException e) { Log.e(TAG, "Couldn't switch user.", e); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java index 7d102ba..600b750 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy; +import android.content.ComponentName; import android.service.notification.Condition; public interface ZenModeController { @@ -29,6 +30,7 @@ public interface ZenModeController { long getNextAlarm(); void setUserId(int userId); boolean isZenAvailable(); + ComponentName getEffectsSuppressor(); public static class Callback { public void onZenChanged(int zen) {} @@ -36,5 +38,6 @@ public interface ZenModeController { public void onConditionsChanged(Condition[] conditions) {} public void onNextAlarmChanged() {} public void onZenAvailableChanged(boolean available) {} + public void onEffectsSupressorChanged() {} } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index b0c8f26..415eb27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -18,7 +18,9 @@ package com.android.systemui.statusbar.policy; import android.app.AlarmManager; import android.app.INotificationManager; +import android.app.NotificationManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -161,12 +163,23 @@ public class ZenModeControllerImpl implements ZenModeController { mSetupObserver.register(); } + @Override + public ComponentName getEffectsSuppressor() { + return NotificationManager.from(mContext).getEffectsSuppressor(); + } + private void fireNextAlarmChanged() { for (Callback cb : mCallbacks) { cb.onNextAlarmChanged(); } } + private void fireEffectsSuppressorChanged() { + for (Callback cb : mCallbacks) { + cb.onEffectsSupressorChanged(); + } + } + private void fireZenChanged(int zen) { for (Callback cb : mCallbacks) { cb.onZenChanged(zen); @@ -219,6 +232,9 @@ public class ZenModeControllerImpl implements ZenModeController { if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) { fireNextAlarmChanged(); } + if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) { + fireEffectsSuppressorChanged(); + } } }; diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java index 8a14288..f03c5eb 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java @@ -19,11 +19,15 @@ package com.android.systemui.volume; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ServiceInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -57,6 +61,7 @@ import android.view.WindowManager.LayoutParams; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; import com.android.internal.R; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -109,6 +114,7 @@ public class VolumePanel extends Handler { private static final int MSG_LAYOUT_DIRECTION = 12; private static final int MSG_ZEN_MODE_AVAILABLE_CHANGED = 13; private static final int MSG_USER_ACTIVITY = 14; + private static final int MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED = 15; // Pseudo stream type for master volume private static final int STREAM_MASTER = -100; @@ -234,8 +240,10 @@ public class VolumePanel extends Handler { ViewGroup group; ImageView icon; SeekBar seekbarView; + TextView suppressorView; int iconRes; int iconMuteRes; + int iconSuppressedRes; } // Synchronize when accessing this @@ -613,8 +621,12 @@ public class VolumePanel extends Handler { toggle(sc); } }); + sc.iconSuppressedRes = com.android.systemui.R.drawable.ic_ringer_mute; } sc.seekbarView = (SeekBar) sc.group.findViewById(com.android.systemui.R.id.seekbar); + sc.suppressorView = + (TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor); + sc.suppressorView.setVisibility(View.GONE); final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO || streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0; sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne); @@ -678,6 +690,40 @@ public class VolumePanel extends Handler { sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes); } + private void updateSliderSupressor(StreamControl sc) { + final ComponentName suppressor = isNotificationOrRing(sc.streamType) + ? mZenController.getEffectsSuppressor() : null; + if (suppressor == null) { + sc.seekbarView.setVisibility(View.VISIBLE); + sc.suppressorView.setVisibility(View.GONE); + } else { + sc.seekbarView.setVisibility(View.GONE); + sc.suppressorView.setVisibility(View.VISIBLE); + sc.suppressorView.setText(mContext.getString(com.android.systemui.R.string.muted_by, + getSuppressorCaption(suppressor))); + sc.icon.setImageResource(sc.iconSuppressedRes); + } + } + + private String getSuppressorCaption(ComponentName suppressor) { + final PackageManager pm = mContext.getPackageManager(); + try { + final ServiceInfo info = pm.getServiceInfo(suppressor, 0); + if (info != null) { + final CharSequence seq = info.loadLabel(pm); + if (seq != null) { + final String str = seq.toString().trim(); + if (str.length() > 0) { + return str; + } + } + } + } catch (Throwable e) { + Log.w(TAG, "Error loading suppressor caption", e); + } + return suppressor.getPackageName(); + } + /** Update the mute and progress state of a slider */ private void updateSlider(StreamControl sc) { updateSliderProgress(sc, -1); @@ -686,6 +732,7 @@ public class VolumePanel extends Handler { sc.icon.setImageDrawable(null); updateSliderIcon(sc, muted); updateSliderEnabled(sc, muted, false); + updateSliderSupressor(sc); } private void updateSliderEnabled(final StreamControl sc, boolean muted, boolean fixedVolume) { @@ -1275,7 +1322,9 @@ public class VolumePanel extends Handler { } break; } - case MSG_RINGER_MODE_CHANGED: { + + case MSG_RINGER_MODE_CHANGED: + case MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED: { if (isShowing()) { updateStates(); } @@ -1356,9 +1405,15 @@ public class VolumePanel extends Handler { }; private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() { + @Override public void onZenAvailableChanged(boolean available) { obtainMessage(MSG_ZEN_MODE_AVAILABLE_CHANGED, available ? 1 : 0, 0).sendToTarget(); } + @Override + public void onEffectsSupressorChanged() { + obtainMessage(MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED, + mZenController.getEffectsSuppressor()).sendToTarget(); + } }; private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() { diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml index 1768400..03d920a 100644 --- a/packages/VpnDialogs/AndroidManifest.xml +++ b/packages/VpnDialogs/AndroidManifest.xml @@ -28,5 +28,14 @@ <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> + + <activity android:name=".ManageDialog" + android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" + android:noHistory="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> + </activity> </application> </manifest> diff --git a/packages/VpnDialogs/res/layout/manage.xml b/packages/VpnDialogs/res/layout/manage.xml new file mode 100644 index 0000000..6b504e4 --- /dev/null +++ b/packages/VpnDialogs/res/layout/manage.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="3mm" + android:stretchColumns="0,1" + android:shrinkColumns="1"> + + <TableRow> + <TextView android:text="@string/session" style="@style/label"/> + <TextView android:id="@+id/session" style="@style/value"/> + </TableRow> + + <TableRow> + <TextView android:text="@string/duration" style="@style/label"/> + <TextView android:id="@+id/duration" style="@style/value"/> + </TableRow> + + <TableRow android:id="@+id/data_transmitted_row" android:visibility="gone"> + <TextView android:text="@string/data_transmitted" style="@style/label"/> + <TextView android:id="@+id/data_transmitted" style="@style/value"/> + </TableRow> + + <TableRow android:id="@+id/data_received_row" android:visibility="gone"> + <TextView android:text="@string/data_received" style="@style/label"/> + <TextView android:id="@+id/data_received" style="@style/value"/> + </TableRow> + +</TableLayout> + diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml index 84206a1..406bcc3 100644 --- a/packages/VpnDialogs/res/values/strings.xml +++ b/packages/VpnDialogs/res/values/strings.xml @@ -28,4 +28,26 @@ <img src="vpn_icon" /> ]]> appears at the top of your screen when VPN is active. </string> + + <!-- Dialog title for built-in VPN. [CHAR LIMIT=40] --> + <string name="legacy_title">VPN is connected</string> + <!-- Button label to configure the current VPN session. [CHAR LIMIT=20] --> + <string name="configure">Configure</string> + <!-- Button label to disconnect the current VPN session. [CHAR LIMIT=20] --> + <string name="disconnect">Disconnect</string> + + <!-- Label for the name of the current VPN session. [CHAR LIMIT=20] --> + <string name="session">Session:</string> + <!-- Label for the duration of the current VPN session. [CHAR LIMIT=20] --> + <string name="duration">Duration:</string> + <!-- Label for the network usage of data transmitted over VPN. [CHAR LIMIT=20] --> + <string name="data_transmitted">Sent:</string> + <!-- Label for the network usage of data received over VPN. [CHAR LIMIT=20] --> + <string name="data_received">Received:</string> + + <!-- Formatted string for the network usage over VPN. [CHAR LIMIT=40] --> + <string name="data_value_format"> + <xliff:g id="number">%1$s</xliff:g> bytes / + <xliff:g id="number">%2$s</xliff:g> packets + </string> </resources> diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java new file mode 100644 index 0000000..cc8500a --- /dev/null +++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.vpndialogs; + +import android.content.Context; +import android.content.DialogInterface; +import android.net.IConnectivityManager; +import android.os.Handler; +import android.os.Message; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import com.android.internal.app.AlertActivity; +import com.android.internal.net.VpnConfig; + +import java.io.DataInputStream; +import java.io.FileInputStream; + +public class ManageDialog extends AlertActivity implements + DialogInterface.OnClickListener, Handler.Callback { + private static final String TAG = "VpnManage"; + + private VpnConfig mConfig; + + private IConnectivityManager mService; + + private TextView mDuration; + private TextView mDataTransmitted; + private TextView mDataReceived; + private boolean mDataRowsHidden; + + private Handler mHandler; + + @Override + protected void onResume() { + super.onResume(); + + if (getCallingPackage() != null) { + Log.e(TAG, getCallingPackage() + " cannot start this activity"); + finish(); + return; + } + + try { + + mService = IConnectivityManager.Stub.asInterface( + ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + + mConfig = mService.getVpnConfig(); + + // mConfig can be null if we are a restricted user, in that case don't show this dialog + if (mConfig == null) { + finish(); + return; + } + + View view = View.inflate(this, R.layout.manage, null); + if (mConfig.session != null) { + ((TextView) view.findViewById(R.id.session)).setText(mConfig.session); + } + mDuration = (TextView) view.findViewById(R.id.duration); + mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted); + mDataReceived = (TextView) view.findViewById(R.id.data_received); + mDataRowsHidden = true; + + if (mConfig.legacy) { + mAlertParams.mTitle = getText(R.string.legacy_title); + } else { + mAlertParams.mTitle = VpnConfig.getVpnLabel(this, mConfig.user); + } + if (mConfig.configureIntent != null) { + mAlertParams.mPositiveButtonText = getText(R.string.configure); + mAlertParams.mPositiveButtonListener = this; + } + mAlertParams.mNeutralButtonText = getText(R.string.disconnect); + mAlertParams.mNeutralButtonListener = this; + mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); + mAlertParams.mNegativeButtonListener = this; + mAlertParams.mView = view; + setupAlert(); + + if (mHandler == null) { + mHandler = new Handler(this); + } + mHandler.sendEmptyMessage(0); + } catch (Exception e) { + Log.e(TAG, "onResume", e); + finish(); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (!isFinishing()) { + finish(); + } + } + + @Override + public void onClick(DialogInterface dialog, int which) { + try { + if (which == DialogInterface.BUTTON_POSITIVE) { + mConfig.configureIntent.send(); + } else if (which == DialogInterface.BUTTON_NEUTRAL) { + if (mConfig.legacy) { + mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); + } else { + mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN); + } + } + } catch (Exception e) { + Log.e(TAG, "onClick", e); + finish(); + } + } + + @Override + public boolean handleMessage(Message message) { + mHandler.removeMessages(0); + + if (!isFinishing()) { + if (mConfig.startTime != -1) { + long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000; + mDuration.setText(String.format("%02d:%02d:%02d", + seconds / 3600, seconds / 60 % 60, seconds % 60)); + } + + String[] numbers = getNumbers(); + if (numbers != null) { + // First unhide the related data rows. + if (mDataRowsHidden) { + findViewById(R.id.data_transmitted_row).setVisibility(View.VISIBLE); + findViewById(R.id.data_received_row).setVisibility(View.VISIBLE); + mDataRowsHidden = false; + } + + // [1] and [2] are received data in bytes and packets. + mDataReceived.setText(getString(R.string.data_value_format, + numbers[1], numbers[2])); + + // [9] and [10] are transmitted data in bytes and packets. + mDataTransmitted.setText(getString(R.string.data_value_format, + numbers[9], numbers[10])); + } + mHandler.sendEmptyMessageDelayed(0, 1000); + } + return true; + } + + private String[] getNumbers() { + DataInputStream in = null; + try { + // See dev_seq_printf_stats() in net/core/dev.c. + in = new DataInputStream(new FileInputStream("/proc/net/dev")); + String prefix = mConfig.interfaze + ':'; + + while (true) { + String line = in.readLine().trim(); + if (line.startsWith(prefix)) { + String[] numbers = line.substring(prefix.length()).split(" +"); + for (int i = 1; i < 17; ++i) { + if (!numbers[i].equals("0")) { + return numbers; + } + } + break; + } + } + } catch (Exception e) { + // ignore + } finally { + try { + in.close(); + } catch (Exception e) { + // ignore + } + } + return null; + } +} diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 3f7c72e..9e268c3 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -70,6 +70,7 @@ import android.provider.Settings; import android.service.dreams.DreamManagerInternal; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; +import android.speech.RecognizerIntent; import android.telecomm.TelecommManager; import android.util.DisplayMetrics; import android.util.EventLog; @@ -2338,6 +2339,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } return -1; + } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) { + if (!down) { + Intent voiceIntent; + if (!keyguardOn && mPowerManager.isInteractive()) { + voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); + } else { + voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); + voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardOn); + } + mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); + } } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) { if (down && repeatCount == 0) { mHandler.post(mScreenshotRunnable); diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java index 394c196..38827d0 100644 --- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java @@ -60,15 +60,17 @@ class DisplayAdjustmentUtils { public static boolean hasAdjustments(Context context, int userId) { final ContentResolver cr = context.getContentResolver(); - boolean hasColorTransform = Settings.Secure.getIntForUser( - cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1; + if (Settings.Secure.getIntForUser(cr, + Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) { + return true; + } - if (!hasColorTransform) { - hasColorTransform |= Settings.Secure.getIntForUser( - cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) == 1; + if (Settings.Secure.getIntForUser(cr, + Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { + return true; } - return hasColorTransform; + return false; } /** @@ -76,52 +78,39 @@ class DisplayAdjustmentUtils { */ public static void applyAdjustments(Context context, int userId) { final ContentResolver cr = context.getContentResolver(); - float[] colorMatrix = new float[16]; - float[] outputMatrix = new float[16]; - boolean hasColorTransform = false; - - Matrix.setIdentityM(colorMatrix, 0); - - final boolean inversionEnabled = Settings.Secure.getIntForUser( - cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1; - if (inversionEnabled) { - final float[] inversionMatrix = INVERSION_MATRIX_VALUE_ONLY; - Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, inversionMatrix, 0); + float[] colorMatrix = null; - colorMatrix = outputMatrix; - outputMatrix = colorMatrix; - - hasColorTransform = true; + if (Settings.Secure.getIntForUser(cr, + Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) { + colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY); } - final boolean daltonizerEnabled = Settings.Secure.getIntForUser( - cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0; - if (daltonizerEnabled) { + if (Settings.Secure.getIntForUser(cr, + Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { final int daltonizerMode = Settings.Secure.getIntForUser(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER, userId); // Monochromacy isn't supported by the native Daltonizer. if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) { - Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, GRAYSCALE_MATRIX, 0); - - final float[] temp = colorMatrix; - colorMatrix = outputMatrix; - outputMatrix = temp; - - hasColorTransform = true; - nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); + colorMatrix = multiply(colorMatrix, GRAYSCALE_MATRIX); + setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); } else { - nativeSetDaltonizerMode(daltonizerMode); + setDaltonizerMode(daltonizerMode); } } else { - nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); + setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); } - if (hasColorTransform) { - nativeSetColorTransform(colorMatrix); - } else { - nativeSetColorTransform(null); + setColorTransform(colorMatrix); + } + + private static float[] multiply(float[] matrix, float[] other) { + if (matrix == null) { + return other; } + float[] result = new float[16]; + Matrix.multiplyMM(result, 0, matrix, 0, other, 0); + return result; } /** @@ -130,7 +119,7 @@ class DisplayAdjustmentUtils { * * @param mode new Daltonization mode */ - private static void nativeSetDaltonizerMode(int mode) { + private static void setDaltonizerMode(int mode) { try { final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); if (flinger != null) { @@ -152,7 +141,7 @@ class DisplayAdjustmentUtils { * @param m the float array that holds the transformation matrix, or null to * disable transformation */ - private static void nativeSetColorTransform(float[] m) { + private static void setColorTransform(float[] m) { try { final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); if (flinger != null) { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index b576324..9674ca2 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -75,6 +75,7 @@ import android.os.UserHandle; import android.os.WorkSource; import android.os.Environment.UserEnvironment; import android.os.storage.IMountService; +import android.os.storage.StorageManager; import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; @@ -1064,31 +1065,19 @@ public class BackupManagerService extends IBackupManager.Stub { } if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport); - // Find transport hosts and bind to their services + // Find all transport hosts and bind to their services List<ResolveInfo> hosts = mPackageManager.queryIntentServicesAsUser( mTransportServiceIntent, 0, UserHandle.USER_OWNER); if (DEBUG) { Slog.v(TAG, "Found transports: " + ((hosts == null) ? "null" : hosts.size())); } if (hosts != null) { - if (MORE_DEBUG) { - for (int i = 0; i < hosts.size(); i++) { - ServiceInfo info = hosts.get(i).serviceInfo; - Slog.v(TAG, " " + info.packageName + "/" + info.name); - } - } for (int i = 0; i < hosts.size(); i++) { - try { - ServiceInfo info = hosts.get(i).serviceInfo; - PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0); - if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) { - bindTransport(info); - } else { - Slog.w(TAG, "Transport package not privileged: " + info.packageName); - } - } catch (Exception e) { - Slog.e(TAG, "Problem resolving transport service: " + e.getMessage()); + final ServiceInfo transport = hosts.get(i).serviceInfo; + if (MORE_DEBUG) { + Slog.v(TAG, " " + transport.packageName + "/" + transport.name); } + tryBindTransport(transport); } } @@ -1442,43 +1431,7 @@ public class BackupManagerService extends IBackupManager.Stub { return array; } - // Backup password management boolean passwordMatchesSaved(String algorithm, String candidatePw, int rounds) { - // First, on an encrypted device we require matching the device pw - final boolean isEncrypted; - try { - isEncrypted = (mMountService.getEncryptionState() != - IMountService.ENCRYPTION_STATE_NONE); - if (isEncrypted) { - if (DEBUG) { - Slog.i(TAG, "Device encrypted; verifying against device data pw"); - } - // 0 means the password validated - // -2 means device not encrypted - // Any other result is either password failure or an error condition, - // so we refuse the match - final int result = mMountService.verifyEncryptionPassword(candidatePw); - if (result == 0) { - if (MORE_DEBUG) Slog.d(TAG, "Pw verifies"); - return true; - } else if (result != -2) { - if (MORE_DEBUG) Slog.d(TAG, "Pw mismatch"); - return false; - } else { - // ...else the device is supposedly not encrypted. HOWEVER, the - // query about the encryption state said that the device *is* - // encrypted, so ... we may have a problem. Log it and refuse - // the backup. - Slog.e(TAG, "verified encryption state mismatch against query; no match allowed"); - return false; - } - } - } catch (Exception e) { - // Something went wrong talking to the mount service. This is very bad; - // assume that we fail password validation. - return false; - } - if (mPasswordHash == null) { // no current password case -- require that 'currentPw' be null or empty if (candidatePw == null || "".equals(candidatePw)) { @@ -1583,14 +1536,7 @@ public class BackupManagerService extends IBackupManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "hasBackupPassword"); - try { - return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE) - || (mPasswordHash != null && mPasswordHash.length() > 0); - } catch (Exception e) { - // If we can't talk to the mount service we have a serious problem; fail - // "secure" i.e. assuming that we require a password - return true; - } + return mPasswordHash != null && mPasswordHash.length() > 0; } private boolean backupPasswordMatches(String currentPw) { @@ -1789,8 +1735,8 @@ public class BackupManagerService extends IBackupManager.Stub { scheduleNextFullBackupJob(); } - // if this was the PACKAGE_ADDED conclusion of an upgrade of the package - // hosting one of our transports, we need to explicitly rebind now. + // Transport maintenance: rebind to known existing transports that have + // just been updated; and bind to any newly-installed transport services. if (rebind) { synchronized (mTransportConnections) { final TransportConnection conn = mTransportConnections.get(packageName); @@ -1799,9 +1745,12 @@ public class BackupManagerService extends IBackupManager.Stub { Slog.i(TAG, "Transport package changed; rebinding"); } bindTransport(conn.mTransport); + } else { + checkForTransportAndBind(app); } } } + } catch (NameNotFoundException e) { // doesn't really exist; ignore it if (DEBUG) { @@ -1853,7 +1802,36 @@ public class BackupManagerService extends IBackupManager.Stub { } }; - void bindTransport(ServiceInfo transport) { + // Check whether the given package hosts a transport, and bind if so + void checkForTransportAndBind(PackageInfo pkgInfo) { + Intent intent = new Intent(mTransportServiceIntent) + .setPackage(pkgInfo.packageName); + List<ResolveInfo> hosts = mPackageManager.queryIntentServicesAsUser( + intent, 0, UserHandle.USER_OWNER); + final int N = hosts.size(); + for (int i = 0; i < N; i++) { + final ServiceInfo info = hosts.get(i).serviceInfo; + tryBindTransport(info); + } + } + + // Verify that the service exists and is hosted by a privileged app, then proceed to bind + boolean tryBindTransport(ServiceInfo info) { + try { + PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0); + if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) { + return bindTransport(info); + } else { + Slog.w(TAG, "Transport package " + info.packageName + " not privileged"); + } + } catch (NameNotFoundException e) { + Slog.w(TAG, "Problem resolving transport package " + info.packageName); + } + return false; + } + + // Actually bind; presumes that we have already validated the transport service + boolean bindTransport(ServiceInfo transport) { ComponentName svcName = new ComponentName(transport.packageName, transport.name); if (DEBUG) { Slog.i(TAG, "Binding to transport host " + svcName); @@ -1874,7 +1852,7 @@ public class BackupManagerService extends IBackupManager.Stub { mContext.unbindService(connection); } } - mContext.bindServiceAsUser(intent, + return mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, UserHandle.OWNER); } @@ -3321,6 +3299,20 @@ public class BackupManagerService extends IBackupManager.Stub { } } + boolean deviceIsEncrypted() { + try { + return mMountService.getEncryptionState() + != IMountService.ENCRYPTION_STATE_NONE + && mMountService.getPasswordType() + != StorageManager.CRYPT_TYPE_DEFAULT; + } catch (Exception e) { + // If we can't talk to the mount service we have a serious problem; fail + // "secure" i.e. assuming that the device is encrypted. + Slog.e(TAG, "Unable to communicate with mount service: " + e.getMessage()); + return true; + } + } + // Full backup task variant used for adb backup class PerformAdbBackupTask extends FullBackupTask { FullBackupEngine mBackupEngine; @@ -3338,7 +3330,7 @@ public class BackupManagerService extends IBackupManager.Stub { ArrayList<String> mPackages; String mCurrentPassword; String mEncryptPassword; - + PerformAdbBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer, boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets, String curPassword, String encryptPassword, boolean doAllApps, @@ -3535,6 +3527,13 @@ public class BackupManagerService extends IBackupManager.Stub { PackageInfo pkg = null; try { boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0); + + // Only allow encrypted backups of encrypted devices + if (deviceIsEncrypted() && !encrypting) { + Slog.e(TAG, "Unencrypted backup of encrypted device; aborting"); + return; + } + OutputStream finalOutput = ofstream; // Verify that the given password matches the currently-active @@ -8315,17 +8314,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF params.observer = observer; params.curPassword = curPassword; - boolean isEncrypted; - try { - isEncrypted = (mMountService.getEncryptionState() != - IMountService.ENCRYPTION_STATE_NONE); - if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password"); - } catch (RemoteException e) { - // couldn't contact the mount service; fail "safe" and assume encryption - Slog.e(TAG, "Unable to contact mount service!"); - isEncrypted = true; - } - params.encryptPassword = (isEncrypted) ? curPassword : encPpassword; + params.encryptPassword = encPpassword; if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb); mWakelock.acquire(); @@ -8470,7 +8459,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // name is not one of the available transports, no action is taken and the method // returns null. public String selectBackupTransport(String transport) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "selectBackupTransport"); + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, + "selectBackupTransport"); synchronized (mTransports) { String prevTransport = null; @@ -9130,19 +9120,22 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF pw.println(" next scheduled: " + mNextBackupPass); pw.println("Available transports:"); - for (String t : listAllTransports()) { - pw.println((t.equals(mCurrentTransport) ? " * " : " ") + t); - try { - IBackupTransport transport = getTransport(t); - File dir = new File(mBaseStateDir, transport.transportDirName()); - pw.println(" destination: " + transport.currentDestinationString()); - pw.println(" intent: " + transport.configurationIntent()); - for (File f : dir.listFiles()) { - pw.println(" " + f.getName() + " - " + f.length() + " state bytes"); + final String[] transports = listAllTransports(); + if (transports != null) { + for (String t : listAllTransports()) { + pw.println((t.equals(mCurrentTransport) ? " * " : " ") + t); + try { + IBackupTransport transport = getTransport(t); + File dir = new File(mBaseStateDir, transport.transportDirName()); + pw.println(" destination: " + transport.currentDestinationString()); + pw.println(" intent: " + transport.configurationIntent()); + for (File f : dir.listFiles()) { + pw.println(" " + f.getName() + " - " + f.length() + " state bytes"); + } + } catch (Exception e) { + Slog.e(TAG, "Error in transport", e); + pw.println(" Error: " + e); } - } catch (Exception e) { - Slog.e(TAG, "Error in transport", e); - pw.println(" Error: " + e); } } diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java index deb2293..601f15e 100644 --- a/services/backup/java/com/android/server/backup/FullBackupJob.java +++ b/services/backup/java/com/android/server/backup/FullBackupJob.java @@ -20,10 +20,8 @@ import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; -import android.app.job.JobInfo.NetworkType; import android.content.ComponentName; import android.content.Context; -import android.util.Slog; public class FullBackupJob extends JobService { private static final String TAG = "FullBackupJob"; @@ -40,7 +38,7 @@ public class FullBackupJob extends JobService { JobScheduler js = (JobScheduler) ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, sIdleService) .setRequiresDeviceIdle(true) - .setRequiredNetworkCapabilities(NetworkType.UNMETERED) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true); if (minDelay > 0) { builder.setMinimumLatency(minDelay); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1005bd7..7655e92 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2160,7 +2160,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) { NetworkRequestInfo nri = mNetworkRequests.get(request); if (nri != null) { - if (nri.mUid != callingUid) { + if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) { if (DBG) log("Attempt to release unowned NetworkRequest " + request); return; } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 50f2ae9..ea24d7c 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -33,7 +33,6 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.hardware.usb.UsbManager; -import android.app.admin.DevicePolicyManager; import android.net.Uri; import android.os.Binder; import android.os.Environment; @@ -1761,6 +1760,21 @@ class MountService extends IMountService.Stub return rc; } + @Override + public int resizeSecureContainer(String id, int sizeMb, String key) { + validatePermission(android.Manifest.permission.ASEC_CREATE); + waitForReady(); + warnOnNotMounted(); + + int rc = StorageResultCode.OperationSucceeded; + try { + mConnector.execute("asec", "resize", id, sizeMb, new SensitiveArg(key)); + } catch (NativeDaemonConnectorException e) { + rc = StorageResultCode.OperationFailedInternalError; + } + return rc; + } + public int finalizeSecureContainer(String id) { validatePermission(android.Manifest.permission.ASEC_CREATE); warnOnNotMounted(); @@ -1835,7 +1849,7 @@ class MountService extends IMountService.Stub return rc; } - public int mountSecureContainer(String id, String key, int ownerUid) { + public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) { validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT); waitForReady(); warnOnNotMounted(); @@ -1848,7 +1862,8 @@ class MountService extends IMountService.Stub int rc = StorageResultCode.OperationSucceeded; try { - mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid); + mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid, + readOnly ? "ro" : "rw"); } catch (NativeDaemonConnectorException e) { int code = e.getCode(); if (code != VoldResponseCode.OpFailedStorageBusy) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f36f25f..dd3d862 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1179,6 +1179,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int SYSTEM_USER_CURRENT_MSG = 43; static final int ENTER_ANIMATION_COMPLETE_MSG = 44; static final int ENABLE_SCREEN_AFTER_BOOT_MSG = 45; + static final int START_USER_SWITCH_MSG = 46; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1771,6 +1772,10 @@ public final class ActivityManagerService extends ActivityManagerNative thread.start(); break; } + case START_USER_SWITCH_MSG: { + showUserSwitchDialog(msg.arg1, (String) msg.obj); + break; + } case REPORT_USER_SWITCH_MSG: { dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); break; @@ -15566,10 +15571,14 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) { - ActivityRecord srec = ActivityRecord.forToken(token); - return srec != null && srec.task.affinity != null && - srec.task.affinity.equals(destAffinity); + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) { + synchronized (this) { + ActivityRecord srec = ActivityRecord.forToken(token); + if (srec.task != null && srec.task.stack != null) { + return srec.task.stack.shouldUpRecreateTaskLocked(srec, destAffinity); + } + } + return false; } public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode, @@ -17439,6 +17448,15 @@ public final class ActivityManagerService extends ActivityManagerNative } /** + * Start user, if its not already running, and bring it to foreground. + */ + boolean startUserInForeground(final int userId, Dialog dlg) { + boolean result = startUser(userId, /* foreground */ true); + dlg.dismiss(); + return result; + } + + /** * Refreshes the list of users related to the current user when either a * user switch happens or when a new related user is started in the * background. @@ -17476,7 +17494,29 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public boolean switchUser(final int userId) { - return startUser(userId, /* foregound */ true); + String userName; + synchronized (this) { + UserInfo userInfo = getUserManagerLocked().getUserInfo(userId); + if (userInfo == null) { + Slog.w(TAG, "No user info for user #" + userId); + return false; + } + if (userInfo.isManagedProfile()) { + Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user"); + return false; + } + userName = userInfo.name; + } + mHandler.removeMessages(START_USER_SWITCH_MSG); + mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); + return true; + } + + private void showUserSwitchDialog(int userId, String userName) { + // The dialog will show and then initiate the user switch by calling startUserInForeground + Dialog d = new UserSwitchingDialog(this, mContext, userId, userName, + true /* above system */); + d.show(); } private boolean startUser(final int userId, boolean foreground) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 5ad84d4..4bd86e4 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2806,6 +2806,42 @@ final class ActivityStack { } } + final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) { + // Basic case: for simple app-centric recents, we need to recreate + // the task if the affinity has changed. + if (srec == null || srec.task.affinity == null || + !srec.task.affinity.equals(destAffinity)) { + return true; + } + // Document-centric case: an app may be split in to multiple documents; + // they need to re-create their task if this current activity is the root + // of a document, unless simply finishing it will return them to the the + // correct app behind. + if (srec.frontOfTask && srec.task != null) { + // Okay, this activity is at the root of its task. What to do, what to do... + if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) { + // Finishing won't return to an application, so we need to recreate. + return true; + } + // We now need to get the task below it to determine what to do. + int taskIdx = mTaskHistory.indexOf(srec.task); + if (taskIdx <= 0) { + Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec); + return false; + } + if (taskIdx == 0) { + // At the bottom of the stack, nothing to go back to. + return true; + } + TaskRecord prevTask = mTaskHistory.get(taskIdx); + if (!srec.task.affinity.equals(prevTask.affinity)) { + // These are different apps, so need to recreate. + return true; + } + } + return false; + } + final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode, Intent resultData) { final ActivityRecord srec = ActivityRecord.forToken(token); diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java new file mode 100644 index 0000000..59d53ec --- /dev/null +++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java @@ -0,0 +1,79 @@ +/* + * 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; + +import android.app.Service; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Handler; +import android.os.Message; +import android.util.Slog; +import android.view.WindowManager; + +/** + * Dialog to show when a user switch it about to happen. The intent is to snapshot the screen + * immediately after the dialog shows so that the user is informed that something is happening + * in the background rather than just freeze the screen and not know if the user-switch affordance + * was being handled. + */ +final class UserSwitchingDialog extends BaseErrorDialog { + private static final String TAG = "ActivityManagerUserSwitchingDialog"; + + private static final int MSG_START_USER = 1; + + private final ActivityManagerService mService; + private final int mUserId; + + public UserSwitchingDialog(ActivityManagerService service, Context context, + int userId, String userName, boolean aboveSystem) { + super(context); + + mService = service; + mUserId = userId; + Resources res = context.getResources(); + setCancelable(false); + setMessage(res.getString(com.android.internal.R.string.user_switching_message, userName)); + if (aboveSystem) { + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + } + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR | + WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; + getWindow().setAttributes(attrs); + } + + @Override + public void show() { + super.show(); + // TODO: Instead of just an arbitrary delay, wait for a signal that the window was fully + // displayed by the window manager + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER), 250); + } + + private final Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_START_USER: + mService.startUserInForeground(mUserId, UserSwitchingDialog.this); + break; + } + } + }; +} diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 69caab9..94aa421 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -22,6 +22,7 @@ import static android.system.OsConstants.AF_INET6; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -105,6 +106,7 @@ public class Vpn { private boolean mAllowIPv6; private Connection mConnection; private LegacyVpnRunner mLegacyVpnRunner; + private PendingIntent mStatusIntent; private volatile boolean mEnableTeardown = true; private final IConnectivityManager mConnService; private final INetworkManagementService mNetd; @@ -237,6 +239,7 @@ public class Vpn { // Reset the interface. if (mInterface != null) { + mStatusIntent = null; agentDisconnect(); jniReset(mInterface); mInterface = null; @@ -567,17 +570,20 @@ public class Vpn { // add the user mVpnUsers.add(UidRange.createForUser(user)); + + prepareStatusIntent(); } private void removeVpnUserLocked(int user) { - if (!isRunningLocked()) { - throw new IllegalStateException("VPN is not active"); - } - UidRange uidRange = UidRange.createForUser(user); - if (mNetworkAgent != null) { - mNetworkAgent.removeUidRanges(new UidRange[] { uidRange }); - } - mVpnUsers.remove(uidRange); + if (!isRunningLocked()) { + throw new IllegalStateException("VPN is not active"); + } + UidRange uidRange = UidRange.createForUser(user); + if (mNetworkAgent != null) { + mNetworkAgent.removeUidRanges(new UidRange[] { uidRange }); + } + mVpnUsers.remove(uidRange); + mStatusIntent = null; } private void onUserAdded(int userId) { @@ -645,6 +651,7 @@ public class Vpn { public void interfaceRemoved(String interfaze) { synchronized (Vpn.this) { if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { + mStatusIntent = null; mVpnUsers = null; mInterface = null; if (mConnection != null) { @@ -702,6 +709,15 @@ public class Vpn { } } + private void prepareStatusIntent() { + final long token = Binder.clearCallingIdentity(); + try { + mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext); + } finally { + Binder.restoreCallingIdentity(token); + } + } + public synchronized boolean addAddress(String address, int prefixLength) { if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { return false; @@ -911,6 +927,9 @@ public class Vpn { final LegacyVpnInfo info = new LegacyVpnInfo(); info.key = mConfig.user; info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); + if (mNetworkInfo.isConnected()) { + info.intent = mStatusIntent; + } return info; } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 2a1ceaa..38077eb 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -139,6 +139,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The dim screen brightness. private final int mScreenBrightnessDimConfig; + // The minimum screen brightness to use in a very dark room. + private final int mScreenBrightnessDarkConfig; + // The minimum allowed brightness. private final int mScreenBrightnessRangeMinimum; @@ -247,6 +250,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mContext = context; final Resources resources = context.getResources(); + final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger( + com.android.internal.R.integer.config_screenBrightnessSettingMinimum)); mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger( com.android.internal.R.integer.config_screenBrightnessDoze)); @@ -254,9 +259,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger( com.android.internal.R.integer.config_screenBrightnessDim)); - int screenBrightnessRangeMinimum = clampAbsoluteBrightness(Math.min(resources.getInteger( - com.android.internal.R.integer.config_screenBrightnessSettingMinimum), - mScreenBrightnessDimConfig)); + mScreenBrightnessDarkConfig = clampAbsoluteBrightness(resources.getInteger( + com.android.internal.R.integer.config_screenBrightnessDark)); + if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) { + Slog.w(TAG, "Expected config_screenBrightnessDark (" + + mScreenBrightnessDarkConfig + ") to be less than or equal to " + + "config_screenBrightnessDim (" + mScreenBrightnessDimConfig + ")."); + } + if (mScreenBrightnessDarkConfig > mScreenBrightnessDimConfig) { + Slog.w(TAG, "Expected config_screenBrightnessDark (" + + mScreenBrightnessDarkConfig + ") to be less than or equal to " + + "config_screenBrightnessSettingMinimum (" + + screenBrightnessSettingMinimum + ")."); + } + + int screenBrightnessRangeMinimum = Math.min(Math.min( + screenBrightnessSettingMinimum, mScreenBrightnessDimConfig), + mScreenBrightnessDarkConfig); mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; @@ -280,8 +299,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call + "Auto-brightness will be disabled."); mUseSoftwareAutoBrightnessConfig = false; } else { - if (screenBrightness[0] < screenBrightnessRangeMinimum) { - screenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightness[0]); + int bottom = clampAbsoluteBrightness(screenBrightness[0]); + if (mScreenBrightnessDarkConfig > bottom) { + Slog.w(TAG, "config_screenBrightnessDark (" + mScreenBrightnessDarkConfig + + ") should be less than or equal to the first value of " + + "config_autoBrightnessLcdBacklightValues (" + + bottom + ")."); + } + if (bottom < screenBrightnessRangeMinimum) { + screenBrightnessRangeMinimum = bottom; } mAutomaticBrightnessController = new AutomaticBrightnessController(this, handler.getLooper(), sensorManager, screenAutoBrightnessSpline, @@ -905,6 +931,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println("Display Power Controller Configuration:"); pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig); pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig); + pw.println(" mScreenBrightnessDarkConfig=" + mScreenBrightnessDarkConfig); pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum); pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); pw.println(" mUseSoftwareAutoBrightnessConfig=" diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 6771cce..379ec94 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -117,6 +117,8 @@ public class JobSchedulerService extends com.android.server.SystemService */ final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>(); + final ArrayList<Integer> mStartedUsers = new ArrayList(); + final JobHandler mHandler; final JobSchedulerStub mJobSchedulerStub; @@ -151,6 +153,18 @@ public class JobSchedulerService extends com.android.server.SystemService } }; + @Override + public void onStartUser(int userHandle) { + mStartedUsers.add(userHandle); + // Let's kick any outstanding jobs for this user. + mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); + } + + @Override + public void onStopUser(int userHandle) { + mStartedUsers.remove(Integer.valueOf(userHandle)); + } + /** * Entry point from client to schedule the provided job. * This cancels the job if it's already been scheduled, and replaces it with the one provided. @@ -393,26 +407,26 @@ public class JobSchedulerService extends com.android.server.SystemService final JobInfo job = failureToReschedule.getJob(); final long initialBackoffMillis = job.getInitialBackoffMillis(); - final int backoffAttempt = failureToReschedule.getNumFailures() + 1; - long newEarliestRuntimeElapsed = elapsedNowMillis; + final int backoffAttempts = failureToReschedule.getNumFailures() + 1; + long delayMillis; switch (job.getBackoffPolicy()) { - case JobInfo.BackoffPolicy.LINEAR: - newEarliestRuntimeElapsed += initialBackoffMillis * backoffAttempt; + case JobInfo.BACKOFF_POLICY_LINEAR: + delayMillis = initialBackoffMillis * backoffAttempts; break; default: if (DEBUG) { Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential."); } - case JobInfo.BackoffPolicy.EXPONENTIAL: - newEarliestRuntimeElapsed += - Math.pow(initialBackoffMillis * 0.001, backoffAttempt) * 1000; + case JobInfo.BACKOFF_POLICY_EXPONENTIAL: + delayMillis = + (long) Math.scalb(initialBackoffMillis, backoffAttempts - 1); break; } - newEarliestRuntimeElapsed = - Math.min(newEarliestRuntimeElapsed, JobInfo.MAX_BACKOFF_DELAY_MILLIS); - return new JobStatus(failureToReschedule, newEarliestRuntimeElapsed, - JobStatus.NO_LATEST_RUNTIME, backoffAttempt); + delayMillis = + Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS); + return new JobStatus(failureToReschedule, elapsedNowMillis + delayMillis, + JobStatus.NO_LATEST_RUNTIME, backoffAttempts); } /** @@ -610,9 +624,20 @@ public class JobSchedulerService extends com.android.server.SystemService * - It's ready. * - It's not pending. * - It's not already running on a JSC. + * - The user that requested the job is running. */ private boolean isReadyToBeExecutedLocked(JobStatus job) { - return job.isReady() && !mPendingJobs.contains(job) && !isCurrentlyActiveLocked(job); + final boolean jobReady = job.isReady(); + final boolean jobPending = mPendingJobs.contains(job); + final boolean jobActive = isCurrentlyActiveLocked(job); + final boolean userRunning = mStartedUsers.contains(job.getUserId()); + + if (DEBUG) { + Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() + + " ready=" + jobReady + " pending=" + jobPending + + " active=" + jobActive + " userRunning=" + userRunning); + } + return userRunning && jobReady && !jobPending && !jobActive; } /** @@ -795,6 +820,11 @@ public class JobSchedulerService extends com.android.server.SystemService void dumpInternal(PrintWriter pw) { synchronized (mJobs) { + pw.print("Started users: "); + for (int i=0; i<mStartedUsers.size(); i++) { + pw.print("u" + mStartedUsers.get(i) + " "); + } + pw.println(); pw.println("Registered jobs:"); if (mJobs.size() > 0) { ArraySet<JobStatus> jobs = mJobs.getJobs(); diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 46f557f..df12e1a 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -515,7 +515,7 @@ public class JobStore { // Read out job identifier attributes. try { jobBuilder = buildBuilderFromXml(parser); - jobBuilder.setIsPersisted(true); + jobBuilder.setPersisted(true); uid = Integer.valueOf(parser.getAttributeValue(null, "uid")); } catch (NumberFormatException e) { Slog.e(TAG, "Error parsing job's required fields, skipping"); @@ -622,11 +622,11 @@ public class JobStore { private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) { String val = parser.getAttributeValue(null, "unmetered"); if (val != null) { - jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED); + jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } val = parser.getAttributeValue(null, "connectivity"); if (val != null) { - jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY); + jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } val = parser.getAttributeValue(null, "idle"); if (val != null) { diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index 652d8f8..6f5d3c2 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -21,6 +21,7 @@ import android.content.ComponentName; import android.os.PersistableBundle; import android.os.SystemClock; import android.os.UserHandle; +import android.text.format.DateUtils; import java.io.PrintWriter; import java.util.concurrent.atomic.AtomicBoolean; @@ -41,6 +42,7 @@ public class JobStatus { public static final long NO_EARLIEST_RUNTIME = 0L; final JobInfo job; + /** Uid of the package requesting this job. */ final int uId; final String name; final String tag; @@ -157,11 +159,11 @@ public class JobStatus { } public boolean hasConnectivityConstraint() { - return job.getNetworkCapabilities() == JobInfo.NetworkType.ANY; + return job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY; } public boolean hasUnmeteredConstraint() { - return job.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED; + return job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED; } public boolean hasChargingConstraint() { @@ -214,12 +216,39 @@ public class JobStatus { return String.valueOf(hashCode()).substring(0, 3) + ".." + ":[" + job.getService() + ",jId=" + job.getId() - + ",R=(" + earliestRunTimeElapsedMillis + "," + latestRunTimeElapsedMillis + ")" - + ",N=" + job.getNetworkCapabilities() + ",C=" + job.isRequireCharging() + + ",u" + getUserId() + + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME) + + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")" + + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging() + ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures + + ",P=" + job.isPersisted() + (isReady() ? "(READY)" : "") + "]"; } + + private String formatRunTime(long runtime, long defaultValue) { + if (runtime == defaultValue) { + return "none"; + } else { + long elapsedNow = SystemClock.elapsedRealtime(); + long nextRuntime = runtime - elapsedNow; + if (nextRuntime > 0) { + return DateUtils.formatElapsedTime(nextRuntime / 1000); + } else { + return "-" + DateUtils.formatElapsedTime(nextRuntime / -1000); + } + } + } + + /** + * Convenience function to identify a job uniquely without pulling all the data that + * {@link #toString()} returns. + */ + public String toShortString() { + return job.getService().flattenToShortString() + " jId=" + job.getId() + + ", u" + getUserId(); + } + // Dumpsys infrastructure public void dump(PrintWriter pw, String prefix) { pw.println(this.toString()); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 45bd812..c390f9b 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -29,6 +29,7 @@ import android.app.IActivityManager; import android.app.INotificationManager; import android.app.ITransientNotification; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; import android.content.BroadcastReceiver; @@ -56,6 +57,7 @@ import android.os.IBinder; import android.os.IInterface; import android.os.Looper; import android.os.Message; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -109,6 +111,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; +import java.util.Objects; /** {@hide} */ public class NotificationManagerService extends SystemService { @@ -173,6 +176,7 @@ public class NotificationManagerService extends SystemService { NotificationRecord mVibrateNotification; private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>(); + private ComponentName mEffectsSuppressor; private int mListenerHints; // right now, all hints are global // for enabling and disabling notification pulse behavior @@ -941,6 +945,15 @@ public class NotificationManagerService extends SystemService { scheduleListenerHintsChanged(hints); } + private void updateEffectsSuppressorLocked() { + final ComponentName suppressor = !mListenersDisablingEffects.isEmpty() + ? mListenersDisablingEffects.valueAt(0).component : null; + if (Objects.equals(suppressor, mEffectsSuppressor)) return; + mEffectsSuppressor = suppressor; + getContext().sendBroadcast(new Intent(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)); + } + private final IBinder mService = new INotificationManager.Stub() { // Toasts // ============================================================================ @@ -1299,6 +1312,7 @@ public class NotificationManagerService extends SystemService { } mZenModeHelper.requestFromListener(hints); updateListenerHintsLocked(); + updateEffectsSuppressorLocked(); } } finally { Binder.restoreCallingIdentity(identity); @@ -1384,6 +1398,12 @@ public class NotificationManagerService extends SystemService { dumpImpl(pw, DumpFilter.parseFromArguments(args)); } + + @Override + public ComponentName getEffectsSuppressor() { + enforceSystemOrSystemUI("INotificationManager.getEffectsSuppressor"); + return mEffectsSuppressor; + } }; private String[] getActiveNotificationKeys(INotificationListener token) { diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java index 4a7a971..3d13d21 100644 --- a/services/core/java/com/android/server/notification/NotificationUsageStats.java +++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java @@ -46,8 +46,13 @@ import java.util.Map; * {@hide} */ public class NotificationUsageStats { + // WARNING: Aggregated stats can grow unboundedly with pkg+id+tag. + // Don't enable on production builds. + private static final boolean ENABLE_AGGREGATED_IN_MEMORY_STATS = false; private static final boolean ENABLE_SQLITE_LOG = true; + private static final AggregatedStats[] EMPTY_AGGREGATED_STATS = new AggregatedStats[0]; + // Guarded by synchronized(this). private final Map<String, AggregatedStats> mStats = new HashMap<String, AggregatedStats>(); private final SQLiteLog mSQLiteLog; @@ -147,6 +152,10 @@ public class NotificationUsageStats { // Locked by this. private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) { + if (!ENABLE_AGGREGATED_IN_MEMORY_STATS) { + return EMPTY_AGGREGATED_STATS; + } + StatusBarNotification n = record.sbn; String user = String.valueOf(n.getUserId()); @@ -171,9 +180,12 @@ public class NotificationUsageStats { } public synchronized void dump(PrintWriter pw, String indent, DumpFilter filter) { - for (AggregatedStats as : mStats.values()) { - if (filter != null && !filter.matches(as.key)) continue; - as.dump(pw, indent); + if (ENABLE_AGGREGATED_IN_MEMORY_STATS) { + for (AggregatedStats as : mStats.values()) { + if (filter != null && !filter.matches(as.key)) + continue; + as.dump(pw, indent); + } } if (ENABLE_SQLITE_LOG) { mSQLiteLog.dump(pw, indent, filter); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 5e802de..6f60d24 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -19,7 +19,6 @@ package com.android.server.pm; import static android.content.pm.PackageManager.INSTALL_ALL_USERS; import static android.content.pm.PackageManager.INSTALL_FROM_ADB; import static android.content.pm.PackageManager.INSTALL_REPLACE_EXISTING; -import static android.net.TrafficStats.MB_IN_BYTES; import static com.android.internal.util.XmlUtils.readBitmapAttribute; import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; @@ -48,8 +47,11 @@ import android.content.pm.IPackageInstaller; import android.content.pm.IPackageInstallerCallback; import android.content.pm.IPackageInstallerSession; import android.content.pm.PackageInstaller; +import android.content.pm.PackageParser; import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageInstaller.SessionParams; +import android.content.pm.PackageParser.PackageLite; +import android.content.pm.PackageParser.PackageParserException; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.net.Uri; @@ -208,7 +210,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { // Ignore stages claimed by active sessions for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); - unclaimed.remove(session.internalStageDir); + unclaimed.remove(session.stageDir); } // Clean up orphaned staging directories @@ -234,7 +236,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { // Ignore stages claimed by active sessions for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); - final String cid = session.externalStageCid; + final String cid = session.stageCid; if (unclaimed.remove(cid)) { // Claimed by active session, mount it @@ -304,10 +306,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub { Slog.w(TAG, "Abandoning old session first created at " + session.createdMillis); valid = false; - } else if (session.internalStageDir != null - && !session.internalStageDir.exists()) { + } else if (session.stageDir != null + && !session.stageDir.exists()) { Slog.w(TAG, "Abandoning internal session with missing stage " - + session.internalStageDir); + + session.stageDir); valid = false; } else { valid = true; @@ -401,12 +403,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub { writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME, session.installerPackageName); writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis); - if (session.internalStageDir != null) { + if (session.stageDir != null) { writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, - session.internalStageDir.getAbsolutePath()); + session.stageDir.getAbsolutePath()); } - if (session.externalStageCid != null) { - writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.externalStageCid); + if (session.stageCid != null) { + writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid); } writeBooleanAttribute(out, ATTR_SEALED, session.isSealed()); @@ -479,6 +481,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } + // TODO: treat INHERIT_EXISTING as install for user + // Figure out where we're going to be staging session data final boolean stageInternal; @@ -502,22 +506,36 @@ public class PackageInstallerService extends IPackageInstaller.Stub { Binder.restoreCallingIdentity(ident); } } else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) { - // We always stage inheriting sessions on internal storage first, - // since we don't want to grow containers until we're sure that - // everything looks legit. - stageInternal = true; - checkInternalStorage(params.sizeBytes); - - // If we have a good hunch we'll end up on external storage, verify - // free space there too. - final ApplicationInfo info = mPm.getApplicationInfo(params.appPackageName, 0, + // Inheriting existing install, so stay on the same storage medium. + final ApplicationInfo existingApp = mPm.getApplicationInfo(params.appPackageName, 0, userId); - if (info != null && (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { - checkExternalStorage(params.sizeBytes); + if (existingApp == null) { + throw new IllegalStateException( + "Missing existing app " + params.appPackageName); + } - throw new UnsupportedOperationException("TODO: finish fleshing out ASEC support"); + final long existingSize; + try { + final PackageLite existingPkg = PackageParser.parsePackageLite( + new File(existingApp.getCodePath()), 0); + existingSize = PackageHelper.calculateInstalledSize(existingPkg, false, + params.abiOverride); + } catch (PackageParserException e) { + throw new IllegalStateException( + "Failed to calculate size of " + params.appPackageName); } + if ((existingApp.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) { + // Internal we can link existing install into place, so we only + // need enough space for the new data. + checkInternalStorage(params.sizeBytes); + stageInternal = true; + } else { + // External we're going to copy existing install into our + // container, so we need footprint of both. + checkExternalStorage(params.sizeBytes + existingSize); + stageInternal = false; + } } else { throw new IllegalArgumentException("Invalid install mode: " + params.mode); } @@ -641,11 +659,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } final String cid = "smdl" + sessionId + ".tmp"; - - // Round up to nearest MB, plus another MB for filesystem overhead - final int sizeMb = (int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES) + 1; - - if (PackageHelper.createSdDir(sizeMb, cid, PackageManagerService.getEncryptKey(), + if (PackageHelper.createSdDir(sizeBytes, cid, PackageManagerService.getEncryptKey(), Process.SYSTEM_UID, true) == null) { throw new IOException("Failed to create ASEC"); } @@ -857,7 +871,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { final String existing = extras.getString( PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE); if (!TextUtils.isEmpty(existing)) { - fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, existing); + fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing); } } try { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 38a2016..5264fc4 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -19,6 +19,7 @@ package com.android.server.pm; import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED; import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS; import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR; +import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED; @@ -38,6 +39,7 @@ import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ApkLite; +import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.Signature; import android.os.Bundle; @@ -47,6 +49,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.system.ErrnoException; @@ -59,18 +62,21 @@ import android.util.MathUtils; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter; +import libcore.io.IoUtils; import libcore.io.Libcore; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class PackageInstallerSession extends IPackageInstallerSession.Stub { @@ -95,18 +101,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final SessionParams params; final long createdMillis; - /** Internal location where staged data is written. */ - final File internalStageDir; - /** External container where staged data is written. */ - final String externalStageCid; - - /** - * When a {@link SessionParams#MODE_INHERIT_EXISTING} session is installed - * into an ASEC, this is the container where the stage is combined with the - * existing install. - */ - // TODO: persist this cid once we start splicing - String combinedCid; + /** Staging location where client data is written. */ + final File stageDir; + final String stageCid; /** Note that UID is not persisted; it's always derived at runtime. */ final int installerUid; @@ -133,29 +130,34 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private String mFinalMessage; @GuardedBy("mLock") - private File mResolvedStageDir; + private ArrayList<FileBridge> mBridges = new ArrayList<>(); + + @GuardedBy("mLock") + private IPackageInstallObserver2 mRemoteObserver; + + /** Fields derived from commit parsing */ + private String mPackageName; + private int mVersionCode; + private Signature[] mSignatures; /** - * Path to the resolved base APK for this session, which may point at an APK - * inside the session (when the session defines the base), or it may point - * at the existing base APK (when adding splits to an existing app). + * Path to the validated base APK for this session, which may point at an + * APK inside the session (when the session defines the base), or it may + * point at the existing base APK (when adding splits to an existing app). * <p> * This is used when confirming permissions, since we can't fully stage the * session inside an ASEC before confirming with user. */ @GuardedBy("mLock") - private String mResolvedBaseCodePath; + private File mResolvedBaseFile; @GuardedBy("mLock") - private ArrayList<FileBridge> mBridges = new ArrayList<>(); + private File mResolvedStageDir; @GuardedBy("mLock") - private IPackageInstallObserver2 mRemoteObserver; - - /** Fields derived from commit parsing */ - private String mPackageName; - private int mVersionCode; - private Signature[] mSignatures; + private final List<File> mResolvedStagedFiles = new ArrayList<>(); + @GuardedBy("mLock") + private final List<File> mResolvedInheritedFiles = new ArrayList<>(); private final Handler.Callback mHandlerCallback = new Handler.Callback() { @Override @@ -168,9 +170,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { commitLocked(); } catch (PackageManagerException e) { - Slog.e(TAG, "Install failed: " + e); + final String completeMsg = ExceptionUtils.getCompleteMessage(e); + Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg); destroyInternal(); - dispatchSessionFinished(e.error, e.getMessage(), null); + dispatchSessionFinished(e.error, completeMsg, null); } return true; @@ -181,7 +184,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { public PackageInstallerSession(PackageInstallerService.InternalCallback callback, Context context, PackageManagerService pm, Looper looper, int sessionId, int userId, String installerPackageName, SessionParams params, long createdMillis, - File internalStageDir, String externalStageCid, boolean sealed) { + File stageDir, String stageCid, boolean sealed) { mCallback = callback; mContext = context; mPm = pm; @@ -192,12 +195,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { this.installerPackageName = installerPackageName; this.params = params; this.createdMillis = createdMillis; - this.internalStageDir = internalStageDir; - this.externalStageCid = externalStageCid; + this.stageDir = stageDir; + this.stageCid = stageCid; - if ((internalStageDir == null) == (externalStageCid == null)) { + if ((stageDir == null) == (stageCid == null)) { throw new IllegalArgumentException( - "Exactly one of internal or external stage must be set"); + "Exactly one of stageDir or stageCid stage must be set"); } mSealed = sealed; @@ -220,7 +223,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { synchronized (mLock) { info.sessionId = sessionId; info.installerPackageName = installerPackageName; - info.resolvedBaseCodePath = mResolvedBaseCodePath; + info.resolvedBaseCodePath = (mResolvedBaseFile != null) ? + mResolvedBaseFile.getAbsolutePath() : null; info.progress = mProgress; info.sealed = mSealed; info.open = mOpenCount.get() > 0; @@ -253,18 +257,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * might point at an ASEC mount point, which is why we delay path resolution * until someone actively works with the session. */ - private File getStageDir() throws IOException { + private File resolveStageDir() throws IOException { synchronized (mLock) { if (mResolvedStageDir == null) { - if (internalStageDir != null) { - mResolvedStageDir = internalStageDir; + if (stageDir != null) { + mResolvedStageDir = stageDir; } else { - final String path = PackageHelper.getSdDir(externalStageCid); + final String path = PackageHelper.getSdDir(stageCid); if (path != null) { mResolvedStageDir = new File(path); } else { - throw new IOException( - "Failed to resolve container path for " + externalStageCid); + throw new IOException("Failed to resolve path to container " + stageCid); } } } @@ -306,7 +309,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { public String[] getNames() { assertNotSealed("getNames"); try { - return getStageDir().list(); + return resolveStageDir().list(); } catch (IOException e) { throw ExceptionUtils.wrap(e); } @@ -339,8 +342,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid name: " + name); } - final File target = new File(getStageDir(), name); + final File target = new File(resolveStageDir(), name); + // TODO: this should delegate to DCS so the system process avoids + // holding open FDs into containers. final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_CREAT | O_WRONLY, 0644); Os.chmod(target.getAbsolutePath(), 0644); @@ -350,7 +355,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (lengthBytes > 0) { final StructStat stat = Libcore.os.fstat(targetFd); final long deltaBytes = lengthBytes - stat.st_size; - if (deltaBytes > 0) { + // Only need to free up space when writing to internal stage + if (stageDir != null && deltaBytes > 0) { mPm.freeStorage(deltaBytes); } Libcore.os.posix_fallocate(targetFd, 0, lengthBytes); @@ -385,7 +391,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid name: " + name); } - final File target = new File(getStageDir(), name); + final File target = new File(resolveStageDir(), name); final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_RDONLY, 0); return new ParcelFileDescriptor(targetFd); @@ -424,22 +430,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mCallback.onSessionSealed(this); } - final File stageDir; try { - stageDir = getStageDir(); + resolveStageDir(); } catch (IOException e) { throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, - "Failed to resolve stage dir", e); + "Failed to resolve stage location", e); } // Verify that stage looks sane with respect to existing application. // This currently only ensures packageName, versionCode, and certificate // consistency. - validateInstallLocked(stageDir); + validateInstallLocked(); Preconditions.checkNotNull(mPackageName); Preconditions.checkNotNull(mSignatures); - Preconditions.checkNotNull(mResolvedBaseCodePath); + Preconditions.checkNotNull(mResolvedBaseFile); if (!mPermissionsAccepted) { // User needs to accept permissions; give installer an intent they @@ -454,17 +459,41 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return; } + if (stageCid != null) { + // Figure out the final installed size and resize the container once + // and for all. Internally the parser handles straddling between two + // locations when inheriting. + final long finalSize = calculateInstalledSize(); + resizeContainer(stageCid, finalSize); + } + // Inherit any packages and native libraries from existing install that // haven't been overridden. if (params.mode == SessionParams.MODE_INHERIT_EXISTING) { - // TODO: implement splicing into existing ASEC - spliceExistingFilesIntoStage(stageDir); + try { + if (stageCid != null) { + // TODO: this should delegate to DCS so the system process + // avoids holding open FDs into containers. + copyFiles(mResolvedInheritedFiles, resolveStageDir()); + } else { + linkFiles(mResolvedInheritedFiles, resolveStageDir()); + } + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, + "Failed to inherit existing install", e); + } } // TODO: surface more granular state from dexopt mCallback.onSessionProgressChanged(this, 0.9f); - // TODO: for ASEC based applications, grow and stream in packages + // Unpack native libraries + extractNativeLibraries(mResolvedStageDir, params.abiOverride); + + // Container is ready to go, let's seal it up! + if (stageCid != null) { + finalizeAndFixContainer(stageCid); + } // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. @@ -482,7 +511,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } }; - mPm.installStage(mPackageName, this.internalStageDir, this.externalStageCid, localObserver, + mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params, installerPackageName, installerUid, new UserHandle(userId)); } @@ -490,81 +519,88 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Validate install by confirming that all application packages are have * consistent package name, version code, and signing certificates. * <p> + * Clears and populates {@link #mResolvedBaseFile}, + * {@link #mResolvedStagedFiles}, and {@link #mResolvedInheritedFiles}. + * <p> * Renames package files in stage to match split names defined inside. * <p> * Note that upgrade compatibility is still performed by * {@link PackageManagerService}. */ - private void validateInstallLocked(File stageDir) throws PackageManagerException { + private void validateInstallLocked() throws PackageManagerException { mPackageName = null; mVersionCode = -1; mSignatures = null; - mResolvedBaseCodePath = null; - final File[] files = stageDir.listFiles(); + mResolvedBaseFile = null; + mResolvedStagedFiles.clear(); + mResolvedInheritedFiles.clear(); + + final File[] files = mResolvedStageDir.listFiles(); if (ArrayUtils.isEmpty(files)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged"); } // Verify that all staged packages are internally consistent - final ArraySet<String> seenSplits = new ArraySet<>(); + final ArraySet<String> stagedSplits = new ArraySet<>(); for (File file : files) { // Installers can't stage directories, so it's fine to ignore // entries like "lost+found". if (file.isDirectory()) continue; - final ApkLite info; + final ApkLite apk; try { - info = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES); + apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Failed to parse " + file + ": " + e); } - if (!seenSplits.add(info.splitName)) { + if (!stagedSplits.add(apk.splitName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Split " + info.splitName + " was defined multiple times"); + "Split " + apk.splitName + " was defined multiple times"); } // Use first package to define unknown values if (mPackageName == null) { - mPackageName = info.packageName; - mVersionCode = info.versionCode; + mPackageName = apk.packageName; + mVersionCode = apk.versionCode; } if (mSignatures == null) { - mSignatures = info.signatures; + mSignatures = apk.signatures; } - assertPackageConsistent(String.valueOf(file), info.packageName, info.versionCode, - info.signatures); + assertApkConsistent(String.valueOf(file), apk); // Take this opportunity to enforce uniform naming final String targetName; - if (info.splitName == null) { + if (apk.splitName == null) { targetName = "base.apk"; } else { - targetName = "split_" + info.splitName + ".apk"; + targetName = "split_" + apk.splitName + ".apk"; } if (!FileUtils.isValidExtFilename(targetName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Invalid filename: " + targetName); } - final File targetFile = new File(stageDir, targetName); + final File targetFile = new File(mResolvedStageDir, targetName); if (!file.equals(targetFile)) { file.renameTo(targetFile); } // Base is coming from session - if (info.splitName == null) { - mResolvedBaseCodePath = targetFile.getAbsolutePath(); + if (apk.splitName == null) { + mResolvedBaseFile = targetFile; } + + mResolvedStagedFiles.add(targetFile); } if (params.mode == SessionParams.MODE_FULL_INSTALL) { // Full installs must include a base package - if (!seenSplits.contains(null)) { + if (!stagedSplits.contains(null)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Full install must include a base package"); } @@ -577,67 +613,204 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Missing existing base package for " + mPackageName); } - // Base might be inherited from existing install - if (mResolvedBaseCodePath == null) { - mResolvedBaseCodePath = app.getBaseCodePath(); - } - - final ApkLite info; + final PackageLite existing; + final ApkLite existingBase; try { - info = PackageParser.parseApkLite(new File(app.getBaseCodePath()), + existing = PackageParser.parsePackageLite(new File(app.getCodePath()), 0); + existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()), PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Failed to parse existing base " + app.getBaseCodePath() + ": " + e); + "Failed to parse existing package " + app.getCodePath() + ": " + e); + } + + assertApkConsistent("Existing base", existingBase); + + // Inherit base if not overridden + if (mResolvedBaseFile == null) { + mResolvedBaseFile = new File(app.getBaseCodePath()); + mResolvedInheritedFiles.add(mResolvedBaseFile); } - assertPackageConsistent("Existing base", info.packageName, info.versionCode, - info.signatures); + // Inherit splits if not overridden + if (!ArrayUtils.isEmpty(existing.splitNames)) { + for (int i = 0; i < existing.splitNames.length; i++) { + final String splitName = existing.splitNames[i]; + final File splitFile = new File(existing.splitCodePaths[i]); + + if (!stagedSplits.contains(splitName)) { + mResolvedInheritedFiles.add(splitFile); + } + } + } } } - private void assertPackageConsistent(String tag, String packageName, int versionCode, - Signature[] signatures) throws PackageManagerException { - if (!mPackageName.equals(packageName)) { + private void assertApkConsistent(String tag, ApkLite apk) throws PackageManagerException { + if (!mPackageName.equals(apk.packageName)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package " - + packageName + " inconsistent with " + mPackageName); + + apk.packageName + " inconsistent with " + mPackageName); } - if (mVersionCode != versionCode) { + if (mVersionCode != apk.versionCode) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag - + " version code " + versionCode + " inconsistent with " + + " version code " + apk.versionCode + " inconsistent with " + mVersionCode); } - if (!Signature.areExactMatch(mSignatures, signatures)) { + if (!Signature.areExactMatch(mSignatures, apk.signatures)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " signatures are inconsistent"); } } /** - * Application is already installed; splice existing files that haven't been - * overridden into our stage. + * Calculate the final install footprint size, combining both staged and + * existing APKs together and including unpacked native code from both. */ - private void spliceExistingFilesIntoStage(File stageDir) throws PackageManagerException { - final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId); + private long calculateInstalledSize() throws PackageManagerException { + Preconditions.checkNotNull(mResolvedBaseFile); - int n = 0; - final File[] oldFiles = new File(app.getCodePath()).listFiles(); - if (!ArrayUtils.isEmpty(oldFiles)) { - for (File oldFile : oldFiles) { - if (!PackageParser.isApkFile(oldFile)) continue; + final ApkLite baseApk; + try { + baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0); + } catch (PackageParserException e) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Failed to parse base package " + mResolvedBaseFile + ": " + e); + } - final File newFile = new File(stageDir, oldFile.getName()); - try { - Os.link(oldFile.getAbsolutePath(), newFile.getAbsolutePath()); - n++; - } catch (ErrnoException e) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Failed to splice into stage", e); - } + final List<String> splitPaths = new ArrayList<>(); + for (File file : mResolvedStagedFiles) { + if (mResolvedBaseFile.equals(file)) continue; + splitPaths.add(file.getAbsolutePath()); + } + for (File file : mResolvedInheritedFiles) { + if (mResolvedBaseFile.equals(file)) continue; + splitPaths.add(file.getAbsolutePath()); + } + + // This is kind of hacky; we're creating a half-parsed package that is + // straddled between the inherited and staged APKs. + final PackageLite pkg = new PackageLite(null, baseApk, null, + splitPaths.toArray(new String[splitPaths.size()])); + final boolean isForwardLocked = + (params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0; + + try { + return PackageHelper.calculateInstalledSize(pkg, isForwardLocked, params.abiOverride); + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Failed to calculate install size", e); + } + } + + private static void linkFiles(List<File> fromFiles, File toDir) throws IOException { + for (File fromFile : fromFiles) { + final File toFile = new File(toDir, fromFile.getName()); + try { + if (LOGD) Slog.d(TAG, "Linking " + fromFile + " to " + toFile); + Os.link(fromFile.getAbsolutePath(), toFile.getAbsolutePath()); + } catch (ErrnoException e) { + throw new IOException("Failed to link " + fromFile + " to " + toFile, e); + } + } + Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir); + } + + private static void copyFiles(List<File> fromFiles, File toDir) throws IOException { + // Remove any partial files from previous attempt + for (File file : toDir.listFiles()) { + if (file.getName().endsWith(".tmp")) { + file.delete(); + } + } + + for (File fromFile : fromFiles) { + final File tmpFile = File.createTempFile("inherit", ".tmp", toDir); + if (LOGD) Slog.d(TAG, "Copying " + fromFile + " to " + tmpFile); + if (!FileUtils.copyFile(fromFile, tmpFile)) { + throw new IOException("Failed to copy " + fromFile + " to " + tmpFile); + } + + final File toFile = new File(toDir, fromFile.getName()); + if (LOGD) Slog.d(TAG, "Renaming " + tmpFile + " to " + toFile); + if (!tmpFile.renameTo(toFile)) { + throw new IOException("Failed to rename " + tmpFile + " to " + toFile); + } + } + Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir); + } + + private static void extractNativeLibraries(File packageDir, String abiOverride) + throws PackageManagerException { + if (LOGD) Slog.v(TAG, "extractNativeLibraries()"); + + // Always start from a clean slate + final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME); + NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true); + + NativeLibraryHelper.Handle handle = null; + try { + handle = NativeLibraryHelper.Handle.create(packageDir); + final int res = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libDir, + abiOverride); + if (res != PackageManager.INSTALL_SUCCEEDED) { + throw new PackageManagerException(res, + "Failed to extract native libraries, res=" + res); } + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Failed to extract native libraries", e); + } finally { + IoUtils.closeQuietly(handle); + } + } + + private static void resizeContainer(String cid, long targetSize) + throws PackageManagerException { + String path = PackageHelper.getSdDir(cid); + if (path == null) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to find mounted " + cid); + } + + final long currentSize = new File(path).getTotalSpace(); + if (currentSize > targetSize) { + Slog.w(TAG, "Current size " + currentSize + " is larger than target size " + + targetSize + "; skipping resize"); + return; + } + + if (!PackageHelper.unMountSdDir(cid)) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to unmount " + cid + " before resize"); } - if (LOGD) Slog.d(TAG, "Spliced " + n + " existing APKs into stage"); + if (!PackageHelper.resizeSdDir(targetSize, cid, + PackageManagerService.getEncryptKey())) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to resize " + cid + " to " + targetSize + " bytes"); + } + + path = PackageHelper.mountSdDir(cid, PackageManagerService.getEncryptKey(), + Process.SYSTEM_UID, false); + if (path == null) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to mount " + cid + " after resize"); + } + } + + private void finalizeAndFixContainer(String cid) throws PackageManagerException { + if (!PackageHelper.finalizeSdDir(cid)) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to finalize container " + cid); + } + + final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE, + UserHandle.USER_OWNER); + final int gid = UserHandle.getSharedAppGid(uid); + if (!PackageHelper.fixSdPermissions(cid, gid, null)) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to fix permissions on container " + cid); + } } void setPermissionsResult(boolean accepted) { @@ -694,12 +867,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mSealed = true; mDestroyed = true; } - if (internalStageDir != null) { - FileUtils.deleteContents(internalStageDir); - internalStageDir.delete(); + if (stageDir != null) { + FileUtils.deleteContents(stageDir); + stageDir.delete(); } - if (externalStageCid != null) { - PackageHelper.destroySdDir(externalStageCid); + if (stageCid != null) { + PackageHelper.destroySdDir(stageCid); } } @@ -717,8 +890,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { pw.printPair("installerPackageName", installerPackageName); pw.printPair("installerUid", installerUid); pw.printPair("createdMillis", createdMillis); - pw.printPair("internalStageDir", internalStageDir); - pw.printPair("externalStageCid", externalStageCid); + pw.printPair("stageDir", stageDir); + pw.printPair("stageCid", stageCid); pw.println(); params.dump(pw); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index aa49b27..f06992a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -50,6 +50,8 @@ import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDWR; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER; +import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME; +import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.removeInt; @@ -298,9 +300,6 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; - private static final String LIB_DIR_NAME = "lib"; - private static final String LIB64_DIR_NAME = "lib64"; - private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay"; private static String sPreferredInstructionSet; @@ -1121,7 +1120,7 @@ public class PackageManagerService extends IPackageManager.Stub { if ((state != null) && !state.timeoutExtended()) { final InstallArgs args = state.getInstallArgs(); - final Uri originUri = Uri.fromFile(args.originFile); + final Uri originUri = Uri.fromFile(args.origin.resolvedFile); Slog.i(TAG, "Verification timed out for " + originUri); mPendingVerification.remove(verificationId); @@ -1168,7 +1167,7 @@ public class PackageManagerService extends IPackageManager.Stub { mPendingVerification.remove(verificationId); final InstallArgs args = state.getInstallArgs(); - final Uri originUri = Uri.fromFile(args.originFile); + final Uri originUri = Uri.fromFile(args.origin.resolvedFile); int ret; if (state.isInstallAllowed()) { @@ -4271,7 +4270,7 @@ public class PackageManagerService extends IPackageManager.Stub { InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps), ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString, - getAppDexInstructionSets(ps), isMultiArch(ps)); + getAppDexInstructionSets(ps)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } @@ -4334,7 +4333,7 @@ public class PackageManagerService extends IPackageManager.Stub { + " better than installed " + ps.versionCode); InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps), ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString, - getAppDexInstructionSets(ps), isMultiArch(ps)); + getAppDexInstructionSets(ps)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } @@ -5527,8 +5526,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (isAsec) { abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); } else { - abi32 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, - nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, useIsaSpecificSubdirs); + abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, + nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, + useIsaSpecificSubdirs); } } @@ -5539,8 +5539,9 @@ public class PackageManagerService extends IPackageManager.Stub { if (isAsec) { abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); } else { - abi64 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, - nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, useIsaSpecificSubdirs); + abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, + nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, + useIsaSpecificSubdirs); } } @@ -5578,7 +5579,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (isAsec) { copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList); } else { - copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, + copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, nativeLibraryRoot, abiList, useIsaSpecificSubdirs); } @@ -7782,7 +7783,8 @@ public class PackageManagerService extends IPackageManager.Stub { verificationParams.setInstallerUid(uid); final Message msg = mHandler.obtainMessage(INIT_COPY); - msg.obj = new InstallParams(originFile, null, false, observer, filteredFlags, + final OriginInfo origin = new OriginInfo(originFile, null, false); + msg.obj = new InstallParams(origin, observer, filteredFlags, installerPackageName, verificationParams, user, packageAbiOverride); mHandler.sendMessage(msg); } @@ -7794,7 +7796,8 @@ public class PackageManagerService extends IPackageManager.Stub { params.referrerUri, installerUid, null); final Message msg = mHandler.obtainMessage(INIT_COPY); - msg.obj = new InstallParams(stagedDir, stagedCid, true, observer, params.installFlags, + final OriginInfo origin = new OriginInfo(stagedDir, stagedCid, true); + msg.obj = new InstallParams(origin, observer, params.installFlags, installerPackageName, verifParams, user, params.abiOverride); mHandler.sendMessage(msg); } @@ -8487,22 +8490,45 @@ public class PackageManagerService extends IPackageManager.Stub { } } - class InstallParams extends HandlerParams { + static class OriginInfo { /** * Location where install is coming from, before it has been * copied/renamed into place. This could be a single monolithic APK * file, or a cluster directory. This location may be untrusted. */ - final File originFile; - final String originCid; + final File file; + final String cid; /** - * Flag indicating that {@link #originFile} or {@link #originCid} has - * already been staged, meaning downstream users don't need to - * defensively copy the contents. + * Flag indicating that {@link #file} or {@link #cid} has already been + * staged, meaning downstream users don't need to defensively copy the + * contents. */ - boolean originStaged; + final boolean staged; + + final String resolvedPath; + final File resolvedFile; + + public OriginInfo(File file, String cid, boolean staged) { + this.file = file; + this.cid = cid; + this.staged = staged; + + if (cid != null) { + resolvedPath = PackageHelper.getSdDir(cid); + resolvedFile = new File(resolvedPath); + } else if (file != null) { + resolvedPath = file.getAbsolutePath(); + resolvedFile = file; + } else { + resolvedPath = null; + resolvedFile = null; + } + } + } + class InstallParams extends HandlerParams { + final OriginInfo origin; final IPackageInstallObserver2 observer; int flags; final String installerPackageName; @@ -8510,15 +8536,12 @@ public class PackageManagerService extends IPackageManager.Stub { private InstallArgs mArgs; private int mRet; final String packageAbiOverride; - boolean multiArch; - InstallParams(File originFile, String originCid, boolean originStaged, - IPackageInstallObserver2 observer, int flags, String installerPackageName, - VerificationParams verificationParams, UserHandle user, String packageAbiOverride) { + InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int flags, + String installerPackageName, VerificationParams verificationParams, UserHandle user, + String packageAbiOverride) { super(user); - this.originFile = originFile; - this.originCid = originCid; - this.originStaged = originStaged; + this.origin = origin; this.observer = observer; this.flags = flags; this.installerPackageName = installerPackageName; @@ -8529,7 +8552,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public String toString() { return "InstallParams{" + Integer.toHexString(System.identityHashCode(this)) - + " file=" + originFile + " cid=" + originCid + "}"; + + " file=" + origin.file + " cid=" + origin.cid + "}"; } public ManifestDigest getManifestDigest() { @@ -8608,11 +8631,11 @@ public class PackageManagerService extends IPackageManager.Stub { int ret = PackageManager.INSTALL_SUCCEEDED; // If we're already staged, we've firmly committed to an install location - if (originStaged) { - if (originFile != null) { + if (origin.staged) { + if (origin.file != null) { flags |= PackageManager.INSTALL_INTERNAL; flags &= ~PackageManager.INSTALL_EXTERNAL; - } else if (originCid != null) { + } else if (origin.cid != null) { flags |= PackageManager.INSTALL_EXTERNAL; flags &= ~PackageManager.INSTALL_INTERNAL; } else { @@ -8622,6 +8645,7 @@ public class PackageManagerService extends IPackageManager.Stub { final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0; + PackageInfoLite pkgLite = null; if (onInt && onSd) { @@ -8629,21 +8653,14 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { - // Remote call to find out default install location - final String originPath = originFile.getAbsolutePath(); - pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags, + pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, flags, packageAbiOverride); - // Keep track of whether this package is a multiArch package until - // we perform a full scan of it. We need to do this because we might - // end up extracting the package shared libraries before we perform - // a full scan. - multiArch = pkgLite.multiArch; /* * If we have too little free space, try to free cache * before giving up. */ - if (!originStaged && pkgLite.recommendedInstallLocation + if (!origin.staged && pkgLite.recommendedInstallLocation == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) { // TODO: focus freeing disk space on the target device final StorageManager storage = StorageManager.from(mContext); @@ -8651,11 +8668,11 @@ public class PackageManagerService extends IPackageManager.Stub { Environment.getDataDirectory()); final long sizeBytes = mContainerService.calculateInstalledSize( - originPath, isForwardLocked(), packageAbiOverride); + origin.resolvedPath, isForwardLocked(), packageAbiOverride); if (mInstaller.freeCache(sizeBytes + lowThreshold) >= 0) { - pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags, - packageAbiOverride); + pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, + flags, packageAbiOverride); } /* @@ -8729,10 +8746,10 @@ public class PackageManagerService extends IPackageManager.Stub { final int requiredUid = mRequiredVerifierPackage == null ? -1 : getPackageUid(mRequiredVerifierPackage, userIdentifier); if (requiredUid != -1 && isVerificationEnabled(userIdentifier, flags)) { - // TODO: send verifier the install session instead of uri final Intent verification = new Intent( Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); - verification.setDataAndType(Uri.fromFile(originFile), PACKAGE_MIME_TYPE); + verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)), + PACKAGE_MIME_TYPE); verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); final List<ResolveInfo> receivers = queryIntentReceivers(verification, @@ -8890,8 +8907,7 @@ public class PackageManagerService extends IPackageManager.Stub { int mRet; MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags, - String packageName, String[] instructionSets, int uid, UserHandle user, - boolean isMultiArch) { + String packageName, String[] instructionSets, int uid, UserHandle user) { super(user); this.srcArgs = srcArgs; this.observer = observer; @@ -8901,7 +8917,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (srcArgs != null) { final String codePath = srcArgs.getCodePath(); targetArgs = createInstallArgsForMoveTarget(codePath, flags, packageName, - instructionSets, isMultiArch); + instructionSets); } else { targetArgs = null; } @@ -9002,8 +9018,6 @@ public class PackageManagerService extends IPackageManager.Stub { } private InstallArgs createInstallArgs(InstallParams params) { - // TODO: extend to support incoming zero-copy locations - if (installOnSd(params.flags) || params.isForwardLocked()) { return new AsecInstallArgs(params); } else { @@ -9016,8 +9030,7 @@ public class PackageManagerService extends IPackageManager.Stub { * when cleaning up old installs, or used as a move source. */ private InstallArgs createInstallArgsForExisting(int flags, String codePath, - String resourcePath, String nativeLibraryRoot, String[] instructionSets, - boolean isMultiArch) { + String resourcePath, String nativeLibraryRoot, String[] instructionSets) { final boolean isInAsec; if (installOnSd(flags)) { /* Apps on SD card are always in ASEC containers. */ @@ -9035,33 +9048,29 @@ public class PackageManagerService extends IPackageManager.Stub { if (isInAsec) { return new AsecInstallArgs(codePath, instructionSets, - installOnSd(flags), installForwardLocked(flags), isMultiArch); + installOnSd(flags), installForwardLocked(flags)); } else { return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot, - instructionSets, isMultiArch); + instructionSets); } } private InstallArgs createInstallArgsForMoveTarget(String codePath, int flags, String pkgName, - String[] instructionSets, boolean isMultiArch) { + String[] instructionSets) { final File codeFile = new File(codePath); if (installOnSd(flags) || installForwardLocked(flags)) { String cid = getNextCodePath(codePath, pkgName, "/" + AsecInstallArgs.RES_FILE_NAME); return new AsecInstallArgs(codeFile, cid, instructionSets, installOnSd(flags), - installForwardLocked(flags), isMultiArch); + installForwardLocked(flags)); } else { - return new FileInstallArgs(codeFile, instructionSets, isMultiArch); + return new FileInstallArgs(codeFile, instructionSets); } } static abstract class InstallArgs { - /** @see InstallParams#originFile */ - final File originFile; - /** @see InstallParams#originStaged */ - final boolean originStaged; - - // TODO: define inherit location + /** @see InstallParams#origin */ + final OriginInfo origin; final IPackageInstallObserver2 observer; // Always refers to PackageManager flags only @@ -9070,19 +9079,16 @@ public class PackageManagerService extends IPackageManager.Stub { final ManifestDigest manifestDigest; final UserHandle user; final String abiOverride; - final boolean multiArch; // The list of instruction sets supported by this app. This is currently // only used during the rmdex() phase to clean up resources. We can get rid of this // if we move dex files under the common app path. /* nullable */ String[] instructionSets; - InstallArgs(File originFile, boolean originStaged, IPackageInstallObserver2 observer, - int flags, String installerPackageName, ManifestDigest manifestDigest, - UserHandle user, String[] instructionSets, - String abiOverride, boolean multiArch) { - this.originFile = originFile; - this.originStaged = originStaged; + InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int flags, + String installerPackageName, ManifestDigest manifestDigest, UserHandle user, + String[] instructionSets, String abiOverride) { + this.origin = origin; this.flags = flags; this.observer = observer; this.installerPackageName = installerPackageName; @@ -9090,7 +9096,6 @@ public class PackageManagerService extends IPackageManager.Stub { this.user = user; this.instructionSets = instructionSets; this.abiOverride = abiOverride; - this.multiArch = multiArch; } abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException; @@ -9161,10 +9166,9 @@ public class PackageManagerService extends IPackageManager.Stub { /** New install */ FileInstallArgs(InstallParams params) { - super(params.originFile, params.originStaged, params.observer, params.flags, + super(params.origin, params.observer, params.flags, params.installerPackageName, params.getManifestDigest(), params.getUser(), - null /* instruction sets */, params.packageAbiOverride, - params.multiArch); + null /* instruction sets */, params.packageAbiOverride); if (isFwdLocked()) { throw new IllegalArgumentException("Forward locking only supported in ASEC"); } @@ -9172,8 +9176,8 @@ public class PackageManagerService extends IPackageManager.Stub { /** Existing install */ FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath, - String[] instructionSets, boolean isMultiArch) { - super(null, false, null, 0, null, null, null, instructionSets, null, isMultiArch); + String[] instructionSets) { + super(new OriginInfo(null, null, false), null, 0, null, null, null, instructionSets, null); this.codeFile = (codePath != null) ? new File(codePath) : null; this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null; this.legacyNativeLibraryPath = (legacyNativeLibraryPath != null) ? @@ -9181,13 +9185,12 @@ public class PackageManagerService extends IPackageManager.Stub { } /** New install from existing */ - FileInstallArgs(File originFile, String[] instructionSets, boolean isMultiArch) { - super(originFile, false, null, 0, null, null, null, instructionSets, null, - isMultiArch); + FileInstallArgs(File originFile, String[] instructionSets) { + super(new OriginInfo(originFile, null, false), null, 0, null, null, null, instructionSets, null); } boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException { - final long sizeBytes = imcs.calculateInstalledSize(originFile.getAbsolutePath(), + final long sizeBytes = imcs.calculateInstalledSize(origin.file.getAbsolutePath(), isFwdLocked(), abiOverride); final StorageManager storage = StorageManager.from(mContext); @@ -9195,53 +9198,53 @@ public class PackageManagerService extends IPackageManager.Stub { } int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { - int ret = PackageManager.INSTALL_SUCCEEDED; + if (origin.staged) { + Slog.d(TAG, origin.file + " already staged; skipping copy"); + codeFile = origin.file; + resourceFile = origin.file; + return PackageManager.INSTALL_SUCCEEDED; + } - if (originStaged) { - Slog.d(TAG, originFile + " already staged; skipping copy"); - codeFile = originFile; - resourceFile = originFile; - } else { - try { - final File tempDir = mInstallerService.allocateInternalStageDirLegacy(); - codeFile = tempDir; - resourceFile = tempDir; - } catch (IOException e) { - Slog.w(TAG, "Failed to create copy file: " + e); - return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; - } + try { + final File tempDir = mInstallerService.allocateInternalStageDirLegacy(); + codeFile = tempDir; + resourceFile = tempDir; + } catch (IOException e) { + Slog.w(TAG, "Failed to create copy file: " + e); + return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; + } - final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() { - @Override - public ParcelFileDescriptor open(String name, int mode) throws RemoteException { - if (!FileUtils.isValidExtFilename(name)) { - throw new IllegalArgumentException("Invalid filename: " + name); - } - try { - final File file = new File(codeFile, name); - final FileDescriptor fd = Os.open(file.getAbsolutePath(), - O_RDWR | O_CREAT, 0644); - Os.chmod(file.getAbsolutePath(), 0644); - return new ParcelFileDescriptor(fd); - } catch (ErrnoException e) { - throw new RemoteException("Failed to open: " + e.getMessage()); - } + final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() { + @Override + public ParcelFileDescriptor open(String name, int mode) throws RemoteException { + if (!FileUtils.isValidExtFilename(name)) { + throw new IllegalArgumentException("Invalid filename: " + name); + } + try { + final File file = new File(codeFile, name); + final FileDescriptor fd = Os.open(file.getAbsolutePath(), + O_RDWR | O_CREAT, 0644); + Os.chmod(file.getAbsolutePath(), 0644); + return new ParcelFileDescriptor(fd); + } catch (ErrnoException e) { + throw new RemoteException("Failed to open: " + e.getMessage()); } - }; - - ret = imcs.copyPackage(originFile.getAbsolutePath(), target); - if (ret != PackageManager.INSTALL_SUCCEEDED) { - Slog.e(TAG, "Failed to copy package"); - return ret; } + }; + + int ret = PackageManager.INSTALL_SUCCEEDED; + ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); + if (ret != PackageManager.INSTALL_SUCCEEDED) { + Slog.e(TAG, "Failed to copy package"); + return ret; } final File libraryRoot = new File(codeFile, LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(codeFile); - ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot, - abiOverride, multiArch); + ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, + abiOverride); } catch (IOException e) { Slog.e(TAG, "Copying native libraries failed", e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; @@ -9429,18 +9432,18 @@ public class PackageManagerService extends IPackageManager.Stub { /** New install */ AsecInstallArgs(InstallParams params) { - super(params.originFile, params.originStaged, params.observer, params.flags, + super(params.origin, params.observer, params.flags, params.installerPackageName, params.getManifestDigest(), params.getUser(), null /* instruction sets */, - params.packageAbiOverride, params.multiArch); + params.packageAbiOverride); } /** Existing install */ AsecInstallArgs(String fullCodePath, String[] instructionSets, - boolean isExternal, boolean isForwardLocked, boolean isMultiArch) { - super(null, false, null, (isExternal ? INSTALL_EXTERNAL : 0) + boolean isExternal, boolean isForwardLocked) { + super(new OriginInfo(null, null, false), null, (isExternal ? INSTALL_EXTERNAL : 0) | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, - instructionSets, null, isMultiArch); + instructionSets, null); // Hackily pretend we're still looking at a full code path if (!fullCodePath.endsWith(RES_FILE_NAME)) { fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath(); @@ -9454,21 +9457,20 @@ public class PackageManagerService extends IPackageManager.Stub { setMountPath(subStr1); } - AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked, - boolean isMultiArch) { - super(null, false, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0) + AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) { + super(new OriginInfo(null, null, false), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0) | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, - instructionSets, null, isMultiArch); + instructionSets, null); this.cid = cid; setMountPath(PackageHelper.getSdDir(cid)); } /** New install from existing */ AsecInstallArgs(File originPackageFile, String cid, String[] instructionSets, - boolean isExternal, boolean isForwardLocked, boolean isMultiArch) { - super(originPackageFile, false, null, (isExternal ? INSTALL_EXTERNAL : 0) + boolean isExternal, boolean isForwardLocked) { + super(new OriginInfo(originPackageFile, null, false), null, (isExternal ? INSTALL_EXTERNAL : 0) | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, - instructionSets, null, isMultiArch); + instructionSets, null); this.cid = cid; } @@ -9496,7 +9498,13 @@ public class PackageManagerService extends IPackageManager.Stub { } int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { - // TODO: if already staged, we only need to extract native code + if (origin.staged) { + Slog.d(TAG, origin.cid + " already staged; skipping copy"); + cid = origin.cid; + setMountPath(PackageHelper.getSdDir(cid)); + return PackageManager.INSTALL_SUCCEEDED; + } + if (temp) { createCopyFile(); } else { @@ -9508,7 +9516,7 @@ public class PackageManagerService extends IPackageManager.Stub { } final String newMountPath = imcs.copyPackageToContainer( - originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(), + origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternal(), isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */)); if (newMountPath != null) { @@ -10133,8 +10141,7 @@ public class PackageManagerService extends IPackageManager.Stub { deletedPackage.applicationInfo.getCodePath(), deletedPackage.applicationInfo.getResourcePath(), deletedPackage.applicationInfo.nativeLibraryRootDir, - getAppDexInstructionSets(deletedPackage.applicationInfo), - isMultiArch(deletedPackage.applicationInfo)); + getAppDexInstructionSets(deletedPackage.applicationInfo)); } else { res.removedInfo.args = null; } @@ -10920,7 +10927,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (deleteCodeAndResources && (outInfo != null)) { outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps), ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString, - getAppDexInstructionSets(ps), isMultiArch(ps)); + getAppDexInstructionSets(ps)); if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args); } return true; @@ -12725,7 +12732,7 @@ public class PackageManagerService extends IPackageManager.Stub { } final AsecInstallArgs args = new AsecInstallArgs(cid, - getAppDexInstructionSets(ps), isForwardLocked(ps), isMultiArch(ps)); + getAppDexInstructionSets(ps), isForwardLocked(ps)); // The package status is changed only if the code path // matches between settings and the container id. if (ps.codePathString != null @@ -13019,7 +13026,7 @@ public class PackageManagerService extends IPackageManager.Stub { * anyway. */ if (returnCode != PackageManager.MOVE_SUCCEEDED) { - processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user, false), + processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user), returnCode); } else { Message msg = mHandler.obtainMessage(INIT_COPY); @@ -13027,9 +13034,9 @@ public class PackageManagerService extends IPackageManager.Stub { final boolean multiArch = isMultiArch(pkg.applicationInfo); InstallArgs srcArgs = createInstallArgsForExisting(currFlags, pkg.applicationInfo.getCodePath(), pkg.applicationInfo.getResourcePath(), - pkg.applicationInfo.nativeLibraryRootDir, instructionSets, multiArch); + pkg.applicationInfo.nativeLibraryRootDir, instructionSets); MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, - instructionSets, pkg.applicationInfo.uid, user, multiArch); + instructionSets, pkg.applicationInfo.uid, user); msg.obj = mp; mHandler.sendMessage(msg); } @@ -13107,8 +13114,8 @@ public class PackageManagerService extends IPackageManager.Stub { final int abi = NativeLibraryHelper.findSupportedAbi( handle, Build.SUPPORTED_ABIS); if (abi >= 0) { - NativeLibraryHelper.copyNativeBinariesIfNeededLI( - handle, newNativeDir, Build.SUPPORTED_ABIS[abi]); + NativeLibraryHelper.copyNativeBinaries(handle, + newNativeDir, Build.SUPPORTED_ABIS[abi]); } } catch (IOException ioe) { Slog.w(TAG, "Unable to extract native libs for package :" diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 9734bd4..f47a07c 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -160,9 +160,9 @@ public final class PowerManagerService extends com.android.server.SystemService // Poll interval in milliseconds for watching boot animation finished. private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; - // Used to send the hint to the PowerHAL indicating transitions - // from and to the low power mode. - private static final int POWER_HINT_LOW_POWER_MODE = 5; + // Power hints defined in hardware/libhardware/include/hardware/power.h. + private static final int POWER_HINT_INTERACTION = 2; + private static final int POWER_HINT_LOW_POWER = 5; private final Context mContext; private final ServiceThread mHandlerThread; @@ -223,6 +223,9 @@ public final class PowerManagerService extends com.android.server.SystemService private long mLastUserActivityTime; private long mLastUserActivityTimeNoChangeLights; + // Timestamp of last interactive power hint. + private long mLastInteractivePowerHintTime; + // A bitfield that summarizes the effect of the user activity timer. // A zero value indicates that the user activity timer has expired. private int mUserActivitySummary; @@ -707,7 +710,7 @@ public final class PowerManagerService extends com.android.server.SystemService final boolean lowPowerModeEnabled = mLowPowerModeSetting; if (mLowPowerModeEnabled != lowPowerModeEnabled) { mLowPowerModeEnabled = lowPowerModeEnabled; - powerHintInternal(POWER_HINT_LOW_POWER_MODE, lowPowerModeEnabled ? 1 : 0); + powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0); mLowPowerModeEnabled = lowPowerModeEnabled; BackgroundThread.getHandler().post(new Runnable() { @Override @@ -969,15 +972,25 @@ public final class PowerManagerService extends com.android.server.SystemService } if (eventTime < mLastSleepTime || eventTime < mLastWakeTime - || mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING || !mBootCompleted || !mSystemReady) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity"); try { + if (eventTime > mLastInteractivePowerHintTime) { + powerHintInternal(POWER_HINT_INTERACTION, 0); + mLastInteractivePowerHintTime = eventTime; + } + mNotifier.onUserActivity(event, uid); + if (mWakefulness == WAKEFULNESS_ASLEEP + || mWakefulness == WAKEFULNESS_DOZING + || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) { + return false; + } + if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) { if (eventTime > mLastUserActivityTimeNoChangeLights && eventTime > mLastUserActivityTime) { @@ -2319,6 +2332,8 @@ public final class PowerManagerService extends com.android.server.SystemService pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime)); pw.println(" mLastUserActivityTimeNoChangeLights=" + TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights)); + pw.println(" mLastInteractivePowerHintTime=" + + TimeUtils.formatUptime(mLastInteractivePowerHintTime)); pw.println(" mDisplayReady=" + mDisplayReady); pw.println(" mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker); pw.println(" mHoldingDisplaySuspendBlocker=" + mHoldingDisplaySuspendBlocker); @@ -2774,6 +2789,10 @@ public final class PowerManagerService extends com.android.server.SystemService PowerManager.validateWakeLockParameters(flags, tag); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); + if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + } if (ws != null && ws.size() != 0) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.UPDATE_DEVICE_STATS, null); @@ -2859,7 +2878,10 @@ public final class PowerManagerService extends com.android.server.SystemService public void userActivity(long eventTime, int event, int flags) { final long now = SystemClock.uptimeMillis(); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) - != PackageManager.PERMISSION_GRANTED) { + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingOrSelfPermission( + android.Manifest.permission.USER_ACTIVITY) + != PackageManager.PERMISSION_GRANTED) { // Once upon a time applications could call userActivity(). // Now we require the DEVICE_POWER permission. Log a warning and ignore the // request instead of throwing a SecurityException so we don't break old apps. @@ -2867,8 +2889,8 @@ public final class PowerManagerService extends com.android.server.SystemService if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) { mLastWarningAboutUserActivityPermission = now; Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the " - + "caller does not have DEVICE_POWER permission. " - + "Please fix your app! " + + "caller does not have DEVICE_POWER or USER_ACTIVITY " + + "permission. Please fix your app! " + " pid=" + Binder.getCallingPid() + " uid=" + Binder.getCallingUid()); } diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java index 0523af7..4c080cb 100644 --- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java +++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java @@ -16,16 +16,22 @@ package com.android.server.trust; +import android.app.AlarmManager; +import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.PatternMatcher; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -43,6 +49,9 @@ import java.util.List; * TrustManager and the actual TrustAgent. */ public class TrustAgentWrapper { + private static final String EXTRA_COMPONENT_NAME = "componentName"; + private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION"; + private static final String PERMISSION = "android.permission.PROVIDE_TRUST_AGENT"; private static final boolean DEBUG = false; private static final String TAG = "TrustAgentWrapper"; @@ -79,6 +88,20 @@ public class TrustAgentWrapper { private boolean mTrustDisabledByDpm; private boolean mManagingTrust; private IBinder mSetTrustAgentFeaturesToken; + private AlarmManager mAlarmManager; + private final Intent mAlarmIntent; + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT_NAME); + if (TRUST_EXPIRED_ACTION.equals(intent.getAction()) + && mName.equals(component)) { + mHandler.removeMessages(MSG_TRUST_TIMEOUT); + mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); + } + } + }; private final Handler mHandler = new Handler() { @Override @@ -95,8 +118,10 @@ public class TrustAgentWrapper { boolean initiatedByUser = msg.arg1 != 0; long durationMs = msg.getData().getLong(DATA_DURATION); if (durationMs > 0) { - mHandler.removeMessages(MSG_TRUST_TIMEOUT); - mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs); + long expiration = SystemClock.elapsedRealtime() + durationMs; + PendingIntent op = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, + PendingIntent.FLAG_CANCEL_CURRENT); + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration, op); } mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, (mMessage != null ? mMessage.toString() : null), @@ -106,6 +131,7 @@ public class TrustAgentWrapper { case MSG_TRUST_TIMEOUT: if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString()); mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); + onTrustTimeout(); // Fall through. case MSG_REVOKE_TRUST: mTrusted = false; @@ -212,8 +238,19 @@ public class TrustAgentWrapper { Intent intent, UserHandle user) { mContext = context; mTrustManagerService = trustManagerService; + mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mUserId = user.getIdentifier(); mName = intent.getComponent(); + + mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName); + mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME))); + + final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION); + alarmFilter.addDataScheme(mAlarmIntent.getScheme()); + final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME); + alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL); + mContext.registerReceiver(mBroadcastReceiver, alarmFilter); + // Schedules a restart for when connecting times out. If the connection succeeds, // the restart is canceled in mCallback's onConnected. scheduleRestart(); @@ -227,6 +264,13 @@ public class TrustAgentWrapper { Slog.w(TAG , "Remote Exception", e); } + private void onTrustTimeout() { + try { + if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout(); + } catch (RemoteException e) { + onError(e); + } + } /** * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) */ diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 490536e..98c3381 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -168,6 +168,8 @@ public class TrustManagerService extends SystemService { obsoleteAgents.addAll(mActiveAgents); for (UserInfo userInfo : userInfos) { + if (lockPatternUtils.getKeyguardStoredPasswordQuality() + == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue; DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager(); int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id); final boolean disableTrustAgents = diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index d05d0c7..61ad7aa 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -412,8 +412,9 @@ final class AccessibilityController { private final WindowManager mWindowManager; - private final int mBorderWidth; + private final float mBorderWidth; private final int mHalfBorderWidth; + private final int mDrawBorderInset; private final ViewportWindow mWindow; @@ -421,10 +422,11 @@ final class AccessibilityController { public MagnifiedViewport() { mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE); - mBorderWidth = (int) TypedValue.applyDimension( + mBorderWidth = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, DEFAUTLT_BORDER_WIDTH_DIP, mContext.getResources().getDisplayMetrics()); - mHalfBorderWidth = (int) (mBorderWidth + 0.5) / 2; + mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2); + mDrawBorderInset = (int) mBorderWidth / 2; mWindow = new ViewportWindow(mContext); recomputeBoundsLocked(); } @@ -437,7 +439,8 @@ final class AccessibilityController { } // If this message is pending we are in a rotation animation and do not want // to show the border. We will do so when the pending message is handled. - if (!mHandler.hasMessages(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) { + if (!mHandler.hasMessages( + MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) { setMagnifiedRegionBorderShownLocked(isMagnifyingLocked(), true); } } @@ -513,8 +516,8 @@ final class AccessibilityController { visibleWindows.clear(); - magnifiedBounds.op(mHalfBorderWidth, mHalfBorderWidth, - screenWidth - mHalfBorderWidth, screenHeight - mHalfBorderWidth, + magnifiedBounds.op(mDrawBorderInset, mDrawBorderInset, + screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset, Region.Op.INTERSECT); if (!mOldMagnifiedBounds.equals(magnifiedBounds)) { @@ -527,8 +530,8 @@ final class AccessibilityController { Rect dirtyRect = mTempRect1; if (mFullRedrawNeeded) { mFullRedrawNeeded = false; - dirtyRect.set(mHalfBorderWidth, mHalfBorderWidth, - screenWidth - mHalfBorderWidth, screenHeight - mHalfBorderWidth); + dirtyRect.set(mDrawBorderInset, mDrawBorderInset, + screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset); mWindow.invalidate(dirtyRect); } else { Region dirtyRegion = mTempRegion3; diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index 4ff3899..f25fc62 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -8,11 +8,13 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := \ + services.core \ + services.devicepolicy \ easymocklib \ guava \ mockito-target -LOCAL_JAVA_LIBRARIES := android.test.runner services +LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_PACKAGE_NAME := FrameworksServicesTests diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java index 2b693a3..402f0dd 100644 --- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java @@ -51,11 +51,11 @@ public class JobStoreTest extends AndroidTestCase { final JobInfo task = new Builder(taskId, mComponent) .setRequiresCharging(true) - .setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY) - .setBackoffCriteria(initialBackoff, JobInfo.BackoffPolicy.EXPONENTIAL) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) + .setBackoffCriteria(initialBackoff, JobInfo.BACKOFF_POLICY_EXPONENTIAL) .setOverrideDeadline(runByMillis) .setMinimumLatency(runFromMillis) - .setIsPersisted(true) + .setPersisted(true) .build(); final JobStatus ts = new JobStatus(task, SOME_UID); mTaskStoreUnderTest.add(ts); @@ -80,14 +80,14 @@ public class JobStoreTest extends AndroidTestCase { .setRequiresDeviceIdle(true) .setPeriodic(10000L) .setRequiresCharging(true) - .setIsPersisted(true) + .setPersisted(true) .build(); final JobInfo task2 = new Builder(12, mComponent) .setMinimumLatency(5000L) - .setBackoffCriteria(15000L, JobInfo.BackoffPolicy.LINEAR) + .setBackoffCriteria(15000L, JobInfo.BACKOFF_POLICY_LINEAR) .setOverrideDeadline(30000L) - .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) - .setIsPersisted(true) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) + .setPersisted(true) .build(); final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID); final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID); @@ -121,7 +121,7 @@ public class JobStoreTest extends AndroidTestCase { .setRequiresDeviceIdle(true) .setPeriodic(10000L) .setRequiresCharging(true) - .setIsPersisted(true); + .setPersisted(true); PersistableBundle extras = new PersistableBundle(); extras.putDouble("hello", 3.2); @@ -159,11 +159,11 @@ public class JobStoreTest extends AndroidTestCase { assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(), second.isRequireDeviceIdle()); assertEquals("Invalid unmetered constraint.", - first.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED, - second.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED); + first.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED, + second.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED); assertEquals("Invalid connectivity constraint.", - first.getNetworkCapabilities() == JobInfo.NetworkType.ANY, - second.getNetworkCapabilities() == JobInfo.NetworkType.ANY); + first.getNetworkType() == JobInfo.NETWORK_TYPE_ANY, + second.getNetworkType() == JobInfo.NETWORK_TYPE_ANY); assertEquals("Invalid deadline constraint.", first.hasLateConstraint(), second.hasLateConstraint()); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java index 3a64984..376230b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java @@ -16,6 +16,10 @@ package com.android.server.voiceinteraction; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.hardware.soundtrigger.IRecognitionStatusCallback; import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.Keyphrase; @@ -27,6 +31,7 @@ import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent; import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent; import android.hardware.soundtrigger.SoundTriggerModule; +import android.os.PowerManager; import android.os.RemoteException; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; @@ -64,8 +69,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { /** The properties for the DSP module */ private final SoundTriggerModule mModule; private final Object mLock = new Object(); + private final Context mContext; private final TelephonyManager mTelephonyManager; private final PhoneStateListener mPhoneStateListener; + private final PowerManager mPowerManager; // TODO: Since many layers currently only deal with one recognition // we simplify things by assuming one listener here too. @@ -77,15 +84,19 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private RecognitionConfig mRecognitionConfig = null; private boolean mRequested = false; private boolean mCallActive = false; + private boolean mIsPowerSaveMode = false; // Indicates if the native sound trigger service is disabled or not. // This is an indirect indication of the microphone being open in some other application. private boolean mServiceDisabled = false; private boolean mStarted = false; + private PowerSaveModeListener mPowerSaveModeListener; - SoundTriggerHelper(TelephonyManager telephonyManager) { + SoundTriggerHelper(Context context) { ArrayList <ModuleProperties> modules = new ArrayList<>(); int status = SoundTrigger.listModules(modules); - mTelephonyManager = telephonyManager; + mContext = context; + mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mPhoneStateListener = new MyCallStateListener(); if (status != SoundTrigger.STATUS_OK || modules.size() == 0) { Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size()); @@ -133,6 +144,15 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mCallActive = mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE; // Register for call state changes when the first call to start recognition occurs. mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + + // Register for power saver mode changes when the first call to start recognition + // occurs. + if (mPowerSaveModeListener == null) { + mPowerSaveModeListener = new PowerSaveModeListener(); + mContext.registerReceiver(mPowerSaveModeListener, + new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); + } + mIsPowerSaveMode = mPowerManager.isPowerSaveMode(); } if (moduleProperties == null || mModule == null) { @@ -338,16 +358,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } } - class MyCallStateListener extends PhoneStateListener { - @Override - public void onCallStateChanged(int state, String arg1) { - if (DBG) Slog.d(TAG, "onCallStateChanged: " + state); - synchronized (mLock) { - onCallStateChangedLocked(TelephonyManager.CALL_STATE_IDLE != state); - } - } - } - private void onCallStateChangedLocked(boolean callActive) { if (mCallActive == callActive) { // We consider multiple call states as being active @@ -358,6 +368,14 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { updateRecognitionLocked(true /* notify */); } + private void onPowerSaveModeChangedLocked(boolean isPowerSaveMode) { + if (mIsPowerSaveMode == isPowerSaveMode) { + return; + } + mIsPowerSaveMode = isPowerSaveMode; + updateRecognitionLocked(true /* notify */); + } + private void onSoundModelUpdatedLocked(SoundModelEvent event) { // TODO: Handle sound model update here. } @@ -438,7 +456,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return STATUS_OK; } - boolean start = mRequested && !mCallActive && !mServiceDisabled; + boolean start = mRequested && !mCallActive && !mServiceDisabled && !mIsPowerSaveMode; if (start == mStarted) { // No-op. return STATUS_OK; @@ -509,6 +527,36 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // Unregister from call state changes. mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); + + // Unregister from power save mode changes. + if (mPowerSaveModeListener != null) { + mContext.unregisterReceiver(mPowerSaveModeListener); + mPowerSaveModeListener = null; + } + } + + class MyCallStateListener extends PhoneStateListener { + @Override + public void onCallStateChanged(int state, String arg1) { + if (DBG) Slog.d(TAG, "onCallStateChanged: " + state); + synchronized (mLock) { + onCallStateChangedLocked(TelephonyManager.CALL_STATE_IDLE != state); + } + } + } + + class PowerSaveModeListener extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) { + return; + } + boolean active = mPowerManager.isPowerSaveMode(); + if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active); + synchronized (mLock) { + onPowerSaveModeChangedLocked(active); + } + } } void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -525,6 +573,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { pw.print(" requested="); pw.println(mRequested); pw.print(" started="); pw.println(mStarted); pw.print(" call active="); pw.println(mCallActive); + pw.print(" power save mode active="); pw.println(mIsPowerSaveMode); pw.print(" service disabled="); pw.println(mServiceDisabled); } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index a173a5c..45fa923 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -46,7 +46,6 @@ import android.service.voice.IVoiceInteractionSession; import android.service.voice.VoiceInteractionService; import android.service.voice.VoiceInteractionServiceInfo; import android.speech.RecognitionService; -import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Slog; @@ -78,8 +77,7 @@ public class VoiceInteractionManagerService extends SystemService { mContext = context; mResolver = context.getContentResolver(); mDbHelper = new DatabaseHelper(context); - mSoundTriggerHelper = new SoundTriggerHelper( - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)); + mSoundTriggerHelper = new SoundTriggerHelper(context); } @Override diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java index 63f85e9..a71f739 100644 --- a/telecomm/java/android/telecomm/Call.java +++ b/telecomm/java/android/telecomm/Call.java @@ -329,6 +329,7 @@ public final class Call { * * @param call The {@code Call} invoking this method. * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}. + * @hide */ public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {} @@ -582,6 +583,7 @@ public final class Call { * Obtains an object that can be used to display video from this {@code Call}. * * @return An {@code Call.VideoCall}. + * @hide */ public InCallService.VideoCall getVideoCall() { return mVideoCall; diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java index 3aa4baf..d8f487f 100644 --- a/telecomm/java/android/telecomm/Connection.java +++ b/telecomm/java/android/telecomm/Connection.java @@ -87,6 +87,7 @@ public abstract class Connection { public void onConferenceChanged(Connection c, Conference conference) {} } + /** @hide */ public static abstract class VideoProvider { /** @@ -528,6 +529,7 @@ public abstract class Connection { * {@link VideoProfile.VideoState#RX_ENABLED}. * * @return The video state of the call. + * @hide */ public final int getVideoState() { return mVideoState; @@ -699,6 +701,7 @@ public abstract class Connection { * {@link VideoProfile.VideoState#RX_ENABLED}. * * @param videoState The new video state. + * @hide */ public final void setVideoState(int videoState) { Log.d(this, "setVideoState %d", videoState); @@ -755,6 +758,7 @@ public abstract class Connection { /** * Sets the video call provider. * @param videoProvider The video provider. + * @hide */ public final void setVideoProvider(VideoProvider videoProvider) { mVideoProvider = videoProvider; @@ -763,6 +767,7 @@ public abstract class Connection { } } + /** @hide */ public final VideoProvider getVideoProvider() { return mVideoProvider; } diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java index 5ea1d1a..b991af1 100644 --- a/telecomm/java/android/telecomm/ConnectionRequest.java +++ b/telecomm/java/android/telecomm/ConnectionRequest.java @@ -93,6 +93,7 @@ public final class ConnectionRequest implements Parcelable { * {@link VideoProfile.VideoState#RX_ENABLED}. * * @return The video state for the connection. + * @hide */ public int getVideoState() { return mVideoState; diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java index 794ec41..a062632 100644 --- a/telecomm/java/android/telecomm/InCallService.java +++ b/telecomm/java/android/telecomm/InCallService.java @@ -198,6 +198,7 @@ public abstract class InCallService extends Service { /** * Class to invoke functionality related to video calls. + * @hide */ public static abstract class VideoCall { @@ -294,6 +295,7 @@ public abstract class InCallService extends Service { /** * Listener class which invokes callbacks after video call actions occur. + * @hide */ public static abstract class Listener { /** diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java index 30cfdde..70db6f5 100644 --- a/telecomm/java/android/telecomm/RemoteConnection.java +++ b/telecomm/java/android/telecomm/RemoteConnection.java @@ -158,6 +158,7 @@ public final class RemoteConnection { * * @param connection The {@code RemoteConnection} invoking this method. * @param videoState The new video state of the {@code RemoteConnection}. + * @hide */ public void onVideoStateChanged(RemoteConnection connection, int videoState) {} @@ -357,6 +358,7 @@ public final class RemoteConnection { /** * @return The video state of the {@code RemoteConnection}. See * {@link VideoProfile.VideoState}. + * @hide */ public int getVideoState() { return mVideoState; diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java index 5192b0f..e59fea1 100644 --- a/telecomm/java/android/telecomm/TelecommManager.java +++ b/telecomm/java/android/telecomm/TelecommManager.java @@ -76,6 +76,7 @@ public class TelecommManager { * {@link VideoProfile.VideoState#BIDIRECTIONAL}, * {@link VideoProfile.VideoState#RX_ENABLED}, * {@link VideoProfile.VideoState#TX_ENABLED}. + * @hide */ public static final String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.intent.extra.START_CALL_WITH_VIDEO_STATE"; diff --git a/telecomm/java/android/telecomm/VideoProfile.java b/telecomm/java/android/telecomm/VideoProfile.java index b147978..028d24e 100644 --- a/telecomm/java/android/telecomm/VideoProfile.java +++ b/telecomm/java/android/telecomm/VideoProfile.java @@ -21,6 +21,8 @@ import android.os.Parcelable; /** * Represents attributes of video calls. + * + * {@hide} */ public class VideoProfile implements Parcelable { /** diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index b935d2a..acb97a0 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1825,7 +1825,7 @@ public class PhoneNumberUtils int slotId = SubscriptionManager.getSlotId(subId); // retrieve the list of emergency numbers // check read-write ecclist property first - String ecclist = (slotId == 0) ? "ril.ecclist" : ("ril.ecclist" + slotId); + String ecclist = (slotId <= 0) ? "ril.ecclist" : ("ril.ecclist" + slotId); numbers = SystemProperties.get(ecclist); diff --git a/tests/JobSchedulerTestApp/res/layout/activity_main.xml b/tests/JobSchedulerTestApp/res/layout/activity_main.xml index d3429ff..96e1641 100644 --- a/tests/JobSchedulerTestApp/res/layout/activity_main.xml +++ b/tests/JobSchedulerTestApp/res/layout/activity_main.xml @@ -141,6 +141,20 @@ android:id="@+id/checkbox_idle" android:text="@string/idle_mode_text"/> </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/persisted_caption" + android:layout_marginRight="15dp"/> + <CheckBox + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/checkbox_persisted" + android:text="@string/persisted_mode_text"/> + </LinearLayout> </LinearLayout> <Button diff --git a/tests/JobSchedulerTestApp/res/values/strings.xml b/tests/JobSchedulerTestApp/res/values/strings.xml index eebfb19..90dd2b6 100644 --- a/tests/JobSchedulerTestApp/res/values/strings.xml +++ b/tests/JobSchedulerTestApp/res/values/strings.xml @@ -27,6 +27,7 @@ limitations under the License. <string name="charging_caption">Charging:</string> <string name="charging_text">Requires device plugged in.</string> <string name="idle_caption">Idle:</string> + <string name="persisted_caption">Persisted:</string> <string name="constraints">Constraints</string> <string name="connectivity">Connectivity:</string> <string name="any">Any</string> @@ -34,4 +35,5 @@ limitations under the License. <string name="timing">Timing:</string> <string name="delay">Delay:</string> <string name="deadline">Deadline:</string> + <string name="persisted_mode_text">Persisted:</string> </resources> diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java index e15929d..b9a2a7e 100644 --- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java +++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java @@ -65,6 +65,8 @@ public class MainActivity extends Activity { mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any); mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging); mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle); + mIsPersistedCheckbox = (CheckBox) findViewById(R.id.checkbox_persisted); + mServiceComponent = new ComponentName(this, TestJobService.class); // Start service and provide it a way to communicate with us. Intent startServiceIntent = new Intent(this, TestJobService.class); @@ -85,6 +87,7 @@ public class MainActivity extends Activity { RadioButton mAnyConnectivityRadioButton; CheckBox mRequiresChargingCheckBox; CheckBox mRequiresIdleCheckbox; + CheckBox mIsPersistedCheckbox; ComponentName mServiceComponent; /** Service object to interact scheduled jobs. */ @@ -140,13 +143,13 @@ public class MainActivity extends Activity { boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked(); boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked(); if (requiresUnmetered) { - builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED); + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } else if (requiresAnyConnectivity) { - builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY); + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked()); - + builder.setPersisted(mIsPersistedCheckbox.isChecked()); mTestService.scheduleJob(builder.build()); } diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java index e2c3be0..a68e04e 100644 --- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java +++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java @@ -90,31 +90,6 @@ public class TestJobService extends JobService { mActivity.onReceivedStartJob(params); } - // Spin off a new task on a separate thread for a couple seconds. - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... voids) { - try { - Log.d(TAG, "Sleeping for 3 seconds."); - Thread.sleep(3000L); - } catch (InterruptedException e) {} - final JobParameters params = jobParamsMap.get(currId); - Log.d(TAG, "Pulled :" + currId + " " + params); - jobFinished(params, false); - - Log.d(TAG, "Rescheduling new job: " + params.getJobId()); - scheduleJob( - new JobInfo.Builder(params.getJobId(), - new ComponentName(getBaseContext(), TestJobService.class)) - .setMinimumLatency(2000L) - .setOverrideDeadline(3000L) - .setRequiresCharging(true) - .build() - ); - - return null; - } - }.execute(); return true; } diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java index 77c0c32..1233c0c 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java @@ -25,6 +25,7 @@ import android.service.voice.VoiceInteractionService; import android.util.Log; import java.util.Arrays; +import java.util.Locale; public class MainInteractionService extends VoiceInteractionService { static final String TAG = "MainInteractionService"; @@ -67,7 +68,8 @@ public class MainInteractionService extends VoiceInteractionService { Log.i(TAG, "Keyphrase enrollment meta-data: " + Arrays.toString(getKeyphraseEnrollmentInfo().listKeyphraseMetadata())); - mHotwordDetector = createAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback); + mHotwordDetector = createAlwaysOnHotwordDetector( + "Hello There", new Locale("en-US"), mHotwordCallback); } @Override diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index bdbf47b..b394671 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -438,6 +438,7 @@ enum { LARGE_SCREEN_ATTR = 0x01010286, XLARGE_SCREEN_ATTR = 0x010102bf, REQUIRED_ATTR = 0x0101028e, + INSTALL_LOCATION_ATTR = 0x010102b7, SCREEN_SIZE_ATTR = 0x010102ca, SCREEN_DENSITY_ATTR = 0x010102cb, REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, @@ -1177,6 +1178,33 @@ int doDump(Bundle* bundle) splitName.string()).string()); } printf("\n"); + + int32_t installLocation = getResolvedIntegerAttribute(&res, tree, + INSTALL_LOCATION_ATTR, &error, -1); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n", + error.string()); + goto bail; + } + + if (installLocation >= 0) { + printf("install-location:'"); + switch (installLocation) { + case 0: + printf("auto"); + break; + case 1: + printf("internalOnly"); + break; + case 2: + printf("preferExternal"); + break; + default: + fprintf(stderr, "Invalid installLocation %d\n", installLocation); + goto bail; + } + printf("'\n"); + } } else if (depth == 2) { withinApplication = false; if (tag == "application") { diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp index de8b4fc..fc95e14 100644 --- a/tools/aapt/ResourceFilter.cpp +++ b/tools/aapt/ResourceFilter.cpp @@ -56,24 +56,34 @@ WeakResourceFilter::match(const ResTable_config& config) const return true; } + uint32_t matchedAxis = 0x0; const size_t N = mConfigs.size(); for (size_t i = 0; i < N; i++) { const std::pair<ConfigDescription, uint32_t>& entry = mConfigs[i]; uint32_t diff = entry.first.diff(config); if ((diff & entry.second) == 0) { - return true; + // Mark the axis that was matched. + matchedAxis |= entry.second; } else if ((diff & entry.second) == ResTable_config::CONFIG_LOCALE) { // If the locales differ, but the languages are the same and // the locale we are matching only has a language specified, // we match. - if (config.language[0] && memcmp(config.language, entry.first.language, sizeof(config.language)) == 0) { + if (config.language[0] && + memcmp(config.language, entry.first.language, sizeof(config.language)) == 0) { if (config.country[0] == 0) { - return true; + matchedAxis |= ResTable_config::CONFIG_LOCALE; } } + } else if ((diff & entry.second) == ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) { + // Special case if the smallest screen width doesn't match. We check that the + // config being matched has a smaller screen width than the filter specified. + if (config.smallestScreenWidthDp != 0 && + config.smallestScreenWidthDp < entry.first.smallestScreenWidthDp) { + matchedAxis |= ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE; + } } } - return false; + return matchedAxis == (mConfigMask & mask); } status_t diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h index f459584..d6430c0 100644 --- a/tools/aapt/ResourceFilter.h +++ b/tools/aapt/ResourceFilter.h @@ -24,8 +24,7 @@ public: }; /** - * Implements logic for parsing and handling "-c" and "--preferred-configurations" - * options. + * Implements logic for parsing and handling "-c" options. */ class WeakResourceFilter : public ResourceFilter { public: diff --git a/tools/aapt/tests/ResourceFilter_test.cpp b/tools/aapt/tests/ResourceFilter_test.cpp index b55379e..bbc2e02 100644 --- a/tools/aapt/tests/ResourceFilter_test.cpp +++ b/tools/aapt/tests/ResourceFilter_test.cpp @@ -75,6 +75,17 @@ TEST(WeakResourceFilterTest, MatchesConfigWithSameValueAxisAndOtherUnrelatedAxis EXPECT_TRUE(filter.match(config)); } +TEST(WeakResourceFilterTest, MatchesConfigWithOneMatchingAxis) { + WeakResourceFilter filter; + ASSERT_EQ(NO_ERROR, filter.parse(String8("fr_FR,sw360dp,normal,en_US"))); + + ConfigDescription config; + config.language[0] = 'e'; + config.language[1] = 'n'; + + EXPECT_TRUE(filter.match(config)); +} + TEST(WeakResourceFilterTest, DoesNotMatchConfigWithDifferentValueAxis) { WeakResourceFilter filter; ASSERT_EQ(NO_ERROR, filter.parse(String8("fr"))); @@ -86,6 +97,32 @@ TEST(WeakResourceFilterTest, DoesNotMatchConfigWithDifferentValueAxis) { EXPECT_FALSE(filter.match(config)); } +TEST(WeakResourceFilterTest, DoesNotMatchWhenOneQualifierIsExplicitlyNotMatched) { + WeakResourceFilter filter; + ASSERT_EQ(NO_ERROR, filter.parse(String8("fr_FR,en_US,normal,large,xxhdpi,sw320dp"))); + + ConfigDescription config; + config.language[0] = 'f'; + config.language[1] = 'r'; + config.smallestScreenWidthDp = 600; + config.version = 13; + + EXPECT_FALSE(filter.match(config)); +} + +TEST(WeakResourceFilterTest, MatchesSmallestWidthWhenSmaller) { + WeakResourceFilter filter; + ASSERT_EQ(NO_ERROR, filter.parse(String8("sw600dp"))); + + ConfigDescription config; + config.language[0] = 'f'; + config.language[1] = 'r'; + config.smallestScreenWidthDp = 320; + config.version = 13; + + EXPECT_TRUE(filter.match(config)); +} + TEST(WeakResourceFilterTest, MatchesConfigWithSameLanguageButNoRegionSpecified) { WeakResourceFilter filter; ASSERT_EQ(NO_ERROR, filter.parse(String8("de-rDE"))); |