Merge "Remove dock divider surface when it's not visible."
diff --git a/api/current.txt b/api/current.txt
index aea7f67..73962f8f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13880,7 +13880,7 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
- field public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.BlackLevelPattern> SENSOR_DYNAMIC_BLACK_LEVEL;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> SENSOR_DYNAMIC_BLACK_LEVEL;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> SENSOR_DYNAMIC_WHITE_LEVEL;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -31403,7 +31403,10 @@
public static final class Telephony.Sms.Intents {
method public static android.telephony.SmsMessage[] getMessagesFromIntent(android.content.Intent);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.provider.Telephony.ACTION_CHANGE_DEFAULT";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_PACKAGE_CHANGED = "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED";
+ field public static final java.lang.String ACTION_EXTERNAL_PROVIDER_CHANGE = "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
field public static final java.lang.String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
+ field public static final java.lang.String EXTRA_IS_DEFAULT_SMS_APP = "android.provider.extra.IS_DEFAULT_SMS_APP";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "package";
field public static final int RESULT_SMS_DUPLICATED = 5; // 0x5
field public static final int RESULT_SMS_GENERIC_ERROR = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index a8b054a..c4d99b8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -14228,7 +14228,7 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
- field public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.BlackLevelPattern> SENSOR_DYNAMIC_BLACK_LEVEL;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> SENSOR_DYNAMIC_BLACK_LEVEL;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> SENSOR_DYNAMIC_WHITE_LEVEL;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -33519,7 +33519,10 @@
public static final class Telephony.Sms.Intents {
method public static android.telephony.SmsMessage[] getMessagesFromIntent(android.content.Intent);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.provider.Telephony.ACTION_CHANGE_DEFAULT";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_PACKAGE_CHANGED = "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED";
+ field public static final java.lang.String ACTION_EXTERNAL_PROVIDER_CHANGE = "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
field public static final java.lang.String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
+ field public static final java.lang.String EXTRA_IS_DEFAULT_SMS_APP = "android.provider.extra.IS_DEFAULT_SMS_APP";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "package";
field public static final int RESULT_SMS_DUPLICATED = 5; // 0x5
field public static final int RESULT_SMS_GENERIC_ERROR = 2; // 0x2
diff --git a/api/test-current.txt b/api/test-current.txt
index aea7f67..73962f8f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -13880,7 +13880,7 @@
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
- field public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.BlackLevelPattern> SENSOR_DYNAMIC_BLACK_LEVEL;
+ field public static final android.hardware.camera2.CaptureResult.Key<float[]> SENSOR_DYNAMIC_BLACK_LEVEL;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> SENSOR_DYNAMIC_WHITE_LEVEL;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -31403,7 +31403,10 @@
public static final class Telephony.Sms.Intents {
method public static android.telephony.SmsMessage[] getMessagesFromIntent(android.content.Intent);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.provider.Telephony.ACTION_CHANGE_DEFAULT";
+ field public static final java.lang.String ACTION_DEFAULT_SMS_PACKAGE_CHANGED = "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED";
+ field public static final java.lang.String ACTION_EXTERNAL_PROVIDER_CHANGE = "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
field public static final java.lang.String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
+ field public static final java.lang.String EXTRA_IS_DEFAULT_SMS_APP = "android.provider.extra.IS_DEFAULT_SMS_APP";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "package";
field public static final int RESULT_SMS_DUPLICATED = 5; // 0x5
field public static final int RESULT_SMS_GENERIC_ERROR = 2; // 0x2
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 273483a..468c145 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -178,15 +178,8 @@
* </p>
* <h3>Notification strategy</h3>
* <p>
- * For each feedback type only one accessibility service is notified. Services are notified
- * in the order of registration. Hence, if two services are registered for the same
- * feedback type in the same package the first one wins. It is possible however, to
- * register a service as the default one for a given feedback type. In such a case this
- * service is invoked if no other service was interested in the event. In other words, default
- * services do not compete with other services and are notified last regardless of the
- * registration order. This enables "generic" accessibility services that work reasonably
- * well with most applications to coexist with "polished" ones that are targeted for
- * specific applications.
+ * All accessibility services are notified of all events they have requested, regardless of their
+ * feedback type.
* </p>
* <p class="note">
* <strong>Note:</strong> The event notification timeout is useful to avoid propagating
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 2e05edb..1370000 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -129,8 +129,8 @@
String libname = "main";
String funcname = "ANativeActivity_onCreate";
ActivityInfo ai;
-
- mIMM = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ mIMM = getSystemService(InputMethodManager.class);
getWindow().takeSurface(this);
getWindow().takeInputQueue(this);
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index fa11221..9c18df8 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -505,8 +505,7 @@
// We made sure the IME was displayed, so also make sure it is closed
// when we go away.
- InputMethodManager imm = (InputMethodManager)getContext()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
if (imm != null) {
imm.hideSoftInputFromWindow(
getWindow().getDecorView().getWindowToken(), 0);
@@ -643,8 +642,7 @@
public void onBackPressed() {
// If the input method is covering the search dialog completely,
// e.g. in landscape mode with no hard keyboard, dismiss just the input method
- InputMethodManager imm = (InputMethodManager)getContext()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
if (imm != null && imm.isFullscreenMode() &&
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0)) {
return;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 5f27bca..3c2d503 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3329,8 +3329,8 @@
* @see CaptureRequest#SENSOR_SENSITIVITY
*/
@PublicKey
- public static final Key<android.hardware.camera2.params.BlackLevelPattern> SENSOR_DYNAMIC_BLACK_LEVEL =
- new Key<android.hardware.camera2.params.BlackLevelPattern>("android.sensor.dynamicBlackLevel", android.hardware.camera2.params.BlackLevelPattern.class);
+ public static final Key<float[]> SENSOR_DYNAMIC_BLACK_LEVEL =
+ new Key<float[]>("android.sensor.dynamicBlackLevel", float[].class);
/**
* <p>Maximum raw value output by sensor for this frame.</p>
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 10307e4..515e9a2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1028,13 +1028,25 @@
* Guess what the network request was trying to say so that the resulting
* network is accessible via the legacy (deprecated) API such as
* requestRouteToHost.
- * This means we should try to be fairly preceise about transport and
+ *
+ * This means we should try to be fairly precise about transport and
* capability but ignore things such as networkSpecifier.
* If the request has more than one transport or capability it doesn't
* match the old legacy requests (they selected only single transport/capability)
* so this function cannot map the request to a single legacy type and
* the resulting network will not be available to the legacy APIs.
*
+ * This code is only called from the requestNetwork API (L and above).
+ *
+ * Setting a legacy type causes CONNECTIVITY_ACTION broadcasts, which are expensive
+ * because they wake up lots of apps - see http://b/23350688 . So we currently only
+ * do this for SUPL requests, which are the only ones that we know need it. If
+ * omitting these broadcasts causes unacceptable app breakage, then for backwards
+ * compatibility we can send them:
+ *
+ * if (targetSdkVersion < Build.VERSION_CODES.M) && // legacy API unsupported >= M
+ * targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP)) // requestNetwork not present < L
+ *
* TODO - This should be removed when the legacy APIs are removed.
*/
private int inferLegacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
@@ -1046,6 +1058,14 @@
return TYPE_NONE;
}
+ // Do this only for SUPL, until GpsLocationProvider is fixed. http://b/25876485 .
+ if (!netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+ // NOTE: if this causes app breakage, we should not just comment out this early return;
+ // instead, we should make this early return conditional on the requesting app's target
+ // SDK version, as described in the comment above.
+ return TYPE_NONE;
+ }
+
String type = null;
int result = TYPE_NONE;
@@ -1062,7 +1082,7 @@
type = "enableDUN";
result = TYPE_MOBILE_DUN;
} else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
- type = "enableSUPL";
+ type = "enableSUPL";
result = TYPE_MOBILE_SUPL;
// back out this hack for mms as they no longer need this and it's causing
// device slowdowns - b/23350688 (note, supl still needs this)
@@ -2541,7 +2561,7 @@
* This function behaves identically to the non-timedout version, but if a suitable
* network is not found within the given time (in milliseconds) the
* {@link NetworkCallback#unavailable} callback is called. The request must
- * still be released normally by calling {@link releaseNetworkRequest}.
+ * still be released normally by calling {@link unregisterNetworkCallback}.
*
* <p>This method requires the caller to hold either the
* {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f560f8a..c92382a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4420,8 +4420,19 @@
* to receive changes in this value.
*/
public static final String LOCATION_MODE = "location_mode";
+ /**
+ * Stores the previous location mode when {@link #LOCATION_MODE} is set to
+ * {@link #LOCATION_MODE_OFF}
+ * @hide
+ */
+ public static final String LOCATION_PREVIOUS_MODE = "location_previous_mode";
/**
+ * Sets all location providers to the previous states before location was turned off.
+ * @hide
+ */
+ public static final int LOCATION_MODE_PREVIOUS = -1;
+ /**
* Location access disabled.
*/
public static final int LOCATION_MODE_OFF = 0;
@@ -5795,6 +5806,7 @@
CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
+ CLONE_TO_MANAGED_PROFILE.add(LOCATION_PREVIOUS_MODE);
CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
CLONE_TO_MANAGED_PROFILE.add(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
@@ -5882,6 +5894,28 @@
}
/**
+ * Saves the current location mode into {@link #LOCATION_PREVIOUS_MODE}.
+ */
+ private static final boolean saveLocationModeForUser(ContentResolver cr, int userId) {
+ final int mode = getLocationModeForUser(cr, userId);
+ return putIntForUser(cr, Settings.Secure.LOCATION_PREVIOUS_MODE, mode, userId);
+ }
+
+ /**
+ * Restores the current location mode from {@link #LOCATION_PREVIOUS_MODE}.
+ */
+ private static final boolean restoreLocationModeForUser(ContentResolver cr, int userId) {
+ int mode = getIntForUser(cr, Settings.Secure.LOCATION_PREVIOUS_MODE,
+ LOCATION_MODE_HIGH_ACCURACY, userId);
+ // Make sure that the previous mode is never "off". Otherwise the user won't be able to
+ // turn on location any longer.
+ if (mode == LOCATION_MODE_OFF) {
+ mode = LOCATION_MODE_HIGH_ACCURACY;
+ }
+ return setLocationModeForUser(cr, mode, userId);
+ }
+
+ /**
* Thread-safe method for setting the location mode to one of
* {@link #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY},
* {@link #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}.
@@ -5899,7 +5933,11 @@
boolean gps = false;
boolean network = false;
switch (mode) {
+ case LOCATION_MODE_PREVIOUS:
+ // Retrieve the actual mode and set to that mode.
+ return restoreLocationModeForUser(cr, userId);
case LOCATION_MODE_OFF:
+ saveLocationModeForUser(cr, userId);
break;
case LOCATION_MODE_SENSORS_ONLY:
gps = true;
diff --git a/core/java/android/security/net/config/KeyStoreCertificateSource.java b/core/java/android/security/net/config/KeyStoreCertificateSource.java
index 1973ef1..9167a90 100644
--- a/core/java/android/security/net/config/KeyStoreCertificateSource.java
+++ b/core/java/android/security/net/config/KeyStoreCertificateSource.java
@@ -47,9 +47,6 @@
Set<X509Certificate> certificates = new ArraySet<>(mKeyStore.size());
for (Enumeration<String> en = mKeyStore.aliases(); en.hasMoreElements();) {
String alias = en.nextElement();
- if (!mKeyStore.isCertificateEntry(alias)) {
- continue;
- }
X509Certificate cert = (X509Certificate) mKeyStore.getCertificate(alias);
if (cert != null) {
certificates.add(cert);
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 2b882d3..c7a4ccc 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -15,6 +15,7 @@
*/
package android.speech.tts;
+import android.annotation.NonNull;
import android.media.AudioFormat;
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
import android.util.Log;
@@ -46,7 +47,6 @@
private FileChannel mFileChannel;
private final UtteranceProgressDispatcher mDispatcher;
- private final Object mCallerIdentity;
private boolean mStarted = false;
private boolean mDone = false;
@@ -54,12 +54,11 @@
/** Status code of synthesis */
protected int mStatusCode;
- FileSynthesisCallback(FileChannel fileChannel, UtteranceProgressDispatcher dispatcher,
- Object callerIdentity, boolean clientIsUsingV2) {
+ FileSynthesisCallback(@NonNull FileChannel fileChannel,
+ @NonNull UtteranceProgressDispatcher dispatcher, boolean clientIsUsingV2) {
super(clientIsUsingV2);
mFileChannel = fileChannel;
mDispatcher = dispatcher;
- mCallerIdentity = callerIdentity;
mStatusCode = TextToSpeech.SUCCESS;
}
@@ -75,9 +74,7 @@
mStatusCode = TextToSpeech.STOPPED;
cleanUp();
- if (mDispatcher != null) {
- mDispatcher.dispatchOnStop();
- }
+ mDispatcher.dispatchOnStop();
}
}
@@ -134,9 +131,7 @@
mAudioFormat = audioFormat;
mChannelCount = channelCount;
- if (mDispatcher != null) {
- mDispatcher.dispatchOnStart();
- }
+ mDispatcher.dispatchOnStart();
fileChannel = mFileChannel;
}
@@ -214,8 +209,7 @@
if (DBG) Log.d(TAG, "Request has been aborted.");
return errorCodeOnStop();
}
- if (mDispatcher != null && mStatusCode != TextToSpeech.SUCCESS &&
- mStatusCode != TextToSpeech.STOPPED) {
+ if (mStatusCode != TextToSpeech.SUCCESS && mStatusCode != TextToSpeech.STOPPED) {
mDispatcher.dispatchOnError(mStatusCode);
return TextToSpeech.ERROR;
}
@@ -239,9 +233,7 @@
synchronized (mStateLock) {
closeFile();
- if (mDispatcher != null) {
- mDispatcher.dispatchOnSuccess();
- }
+ mDispatcher.dispatchOnSuccess();
return TextToSpeech.SUCCESS;
}
} catch (IOException ex) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index c3aed75..8c355d8 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -1032,8 +1032,7 @@
@Override
protected AbstractSynthesisCallback createSynthesisCallback() {
- return new FileSynthesisCallback(mFileOutputStream.getChannel(),
- this, getCallerIdentity(), false);
+ return new FileSynthesisCallback(mFileOutputStream.getChannel(), this, false);
}
@Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ab1943c..692fa66 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -22369,7 +22369,13 @@
* Used to track views that need (at least) a partial relayout at their current size
* during the next traversal.
*/
- final List<View> mPartialLayoutViews = new ArrayList<View>();
+ List<View> mPartialLayoutViews = new ArrayList<>();
+
+ /**
+ * Swapped with mPartialLayoutViews during layout to avoid concurrent
+ * modification. Lazily assigned during ViewRootImpl layout.
+ */
+ List<View> mEmptyPartialLayoutViews;
/**
* Used to track the identity of the current drag operation.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b503e12..3c9310d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1974,6 +1974,15 @@
final List<View> partialLayoutViews = mAttachInfo.mPartialLayoutViews;
final boolean didPartialLayout;
if (!partialLayoutViews.isEmpty()) {
+ // Measurement or layout of views may result in changes to the list
+ // of partial-layout views. Swap in an "empty" list to prevent
+ // concurrent modification of the list being traversed.
+ if (mAttachInfo.mEmptyPartialLayoutViews == null) {
+ mAttachInfo.mPartialLayoutViews = new ArrayList<>();
+ } else {
+ mAttachInfo.mPartialLayoutViews = mAttachInfo.mEmptyPartialLayoutViews;
+ }
+
final int count = partialLayoutViews.size();
mInLayout = true;
for (int i = 0; i < count; i++) {
@@ -1992,9 +2001,12 @@
}
}
mInLayout = false;
- partialLayoutViews.clear();
didPartialLayout = true;
triggerGlobalLayoutListener = true;
+
+ // The traversal list becomes the new empty list.
+ partialLayoutViews.clear();
+ mAttachInfo.mEmptyPartialLayoutViews = partialLayoutViews;
} else {
didPartialLayout = false;
}
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index b3b95f8..f313893 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -61,8 +61,7 @@
setText("");
mMatches = (TextView) mCustomView.findViewById(
com.android.internal.R.id.matches);
- mInput = (InputMethodManager)
- context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mInput = context.getSystemService(InputMethodManager.class);
mResources = context.getResources();
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 90de053..f050e49 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -5755,8 +5755,8 @@
// The editor is off in its own window; we need to be
// the one that does this.
if (editorAction == EditorInfo.IME_ACTION_DONE) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager imm =
+ getContext().getSystemService(InputMethodManager.class);
if (imm != null) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index ad2b4a7..88f02d1 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -152,8 +152,7 @@
*/
private Runnable mShowImeRunnable = new Runnable() {
public void run() {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
if (imm != null) {
imm.showSoftInputUnchecked(0, null);
@@ -912,8 +911,7 @@
post(mShowImeRunnable);
} else {
removeCallbacks(mShowImeRunnable);
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
if (imm != null) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
@@ -1768,8 +1766,8 @@
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus && mSearchView.hasFocus() && getVisibility() == VISIBLE) {
- InputMethodManager inputManager = (InputMethodManager) getContext()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager inputManager =
+ getContext().getSystemService(InputMethodManager.class);
inputManager.showSoftInput(this, 0);
// If in landscape mode, then make sure that
// the ime is in front of the dropdown.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 476c6a2..2f385c1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7225,6 +7225,7 @@
// of the intended optimizations as part of requestLayoutForChild.
nullLayouts();
requestLayout();
+ invalidate();
}
@Override
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index e339c44..592576b 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -137,7 +137,7 @@
super(c);
setFocusableInTouchMode(true);
- mIm = (InputManager)c.getSystemService(Context.INPUT_SERVICE);
+ mIm = c.getSystemService(InputManager.class);
mVC = ViewConfiguration.get(c);
mTextPaint = new Paint();
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 4a9b163..9be3bfb 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1470,8 +1470,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"المطالبة برقم التعريف الشخصي قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"المطالبة بنقش إلغاء القفل قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"المطالبة بكلمة المرور قبل إزالة التثبيت"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"التطبيق غير قابل لتغيير الحجم، يمكنك تمريره بإصبعين."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"تم تثبيت الحزمة عن طريق المشرف"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"تم التحديث بواسطة المشرف"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"تم حذف الحزمة عن طريق المشرف"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 233d709..2617bdb 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Запитване за ПИН код преди освобождаване"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитване за фигура за отключване преди освобождаване"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитване за парола преди освобождаване"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Приложението не може да се преоразмерява. Превъртете го с два пръста."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано от администратора ви"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Актуализирано от администратора ви"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Изтрито от администратора ви"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 646f734..dbf85e3 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Bed om pinkode inden frigørelse"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bed om oplåsningsmønster ved deaktivering"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Appens størrelse kan ikke ændres. Gennemgå den ved at rulle med to fingre."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installeret af din administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Opdateret af administrator"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet af din administrator"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7a7cce1..e00fbec 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Το μέγεθος της εφαρμογής δεν είναι προσαρμόσιμο. Σύρετε προς τα κάτω με δύο δάχτυλα."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Εγκαταστάθηκε από το διαχειριστή σας"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ενημερώθηκε από το διαχειριστή σας"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Διαγράφηκε από το διαχειριστή σας"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 0168d4f..19f1bd9 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para quitar fijación"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para quitar fijación"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para quitar fijación"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"No se puede modificar el tamaño de la app, desplázala con dos dedos."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Lo instaló el administrador."</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por el administrador"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Lo eliminó el administrador."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 04cdfe0..f290c04 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para desactivar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para desactivar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para desactivar"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"No se puede cambiar el tamaño de la aplicación: desplázala con dos dedos."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado por tu administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por tu administrador"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado por tu administrador"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 5898ca0..ca6ad3c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Enne vabastamist küsi PIN-koodi"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Enne vabastamist küsi avamismustrit"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Enne vabastamist küsi parooli"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Rakenduse suurust ei saa muuta. Kerige kahe sõrmega."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installis teie administraator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Värskendas administraator"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Kustutas teie administraator"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 689e9e0..bc5caa2 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -191,7 +191,7 @@
<string name="reboot_to_update_prepare" msgid="6305853831955310890">"آمادهسازی برای بهروزرسانی…"</string>
<string name="reboot_to_update_package" msgid="3871302324500927291">"در حال پردازش بستهبندی بهروز…"</string>
<string name="reboot_to_update_reboot" msgid="6428441000951565185">"در حال راهاندازی مجدد…"</string>
- <string name="reboot_to_reset_title" msgid="4142355915340627490">"بازنشانی به دادههای کارخانه"</string>
+ <string name="reboot_to_reset_title" msgid="4142355915340627490">"بازنشانی دادههای کارخانه"</string>
<string name="reboot_to_reset_message" msgid="2432077491101416345">"در حال راهاندازی مجدد…"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"در حال خاموش شدن…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش میشود."</string>
@@ -511,9 +511,9 @@
<string name="policylab_forceLock" msgid="2274085384704248431">"قفل کردن صفحه"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"نحوه و زمان قفل شدن صفحه را کنترل میکند."</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"پاک کردن تمام دادهها"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به دادههای کارخانه، دادههای رایانهٔ لوحی بدون هشدار پاک میشود."</string>
- <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"دادههای تلویزیون را بدون هشدار با انجام بازنشانی به داده کارخانه پاک کنید."</string>
- <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"با انجام بازنشانی به دادههای کارخانه، دادههای تلفن بدون هشدار پاک میشود."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی دادههای کارخانه، دادههای رایانهٔ لوحی بدون هشدار پاک میشود."</string>
+ <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"دادههای تلویزیون را بدون هشدار با انجام بازنشانی دادههای کارخانه پاک کنید."</string>
+ <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"با انجام بازنشانی دادههای کارخانه، دادههای تلفن بدون هشدار پاک میشود."</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"پاک کردن دادههای کاربر"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"دادههای این کاربر را در این رایانه لوحی بدون هشدار پاک میکند."</string>
<string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"دادههای این کاربر را در این تلویزیون بدون هشدار پاک میکند."</string>
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"درخواست کد پین قبل از برداشتن پین"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"درخواست الگوی باز کردن قفل قبل از برداشتن پین"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"درخواست گذرواژه قبل از برداشتن پین"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"اندازه برنامه قابل تغییر نیست، با دو انگشت آن را پیمایش کنید."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"توسط سرپرستتان نصب شد"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"توسط سرپرست شما بهروزرسانی شد"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"توسط سرپرستتان حذف شد"</string>
@@ -1484,7 +1483,7 @@
<string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"آخر هفته"</string>
<string name="zen_mode_default_events_name" msgid="8158334939013085363">"رویداد"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> آن را بیصدا کرد"</string>
- <string name="system_error_wipe_data" msgid="6608165524785354962">"دستگاهتان یک مشکل داخلی دارد، و ممکن است تا زمانی که بازنشانی به داده کارخانه انجام نگیرد، بیثبات بماند."</string>
+ <string name="system_error_wipe_data" msgid="6608165524785354962">"دستگاهتان یک مشکل داخلی دارد، و ممکن است تا زمانی که بازنشانی دادههای کارخانه انجام نگیرد، بیثبات بماند."</string>
<string name="system_error_manufacturer" msgid="8086872414744210668">"دستگاهتان یک مشکل داخلی دارد. برای جزئیات آن با سازندهتان تماس بگیرید."</string>
<string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"درخواست USSD به درخواست DIAL اصلاح میشود."</string>
<string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"درخواست USSD به درخواست SS اصلاح میشود."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 8af6e56..3494d53 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pyydä PIN ennen irrotusta"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pyydä salasana ennen irrotusta"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Sovelluksen koko ei muutu. Vieritä näkymää kahdella sormella."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Järjestelmänvalvoja on asentanut paketin."</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Järjestelmänvalvojasi on päivittänyt paketin."</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Järjestelmänvalvoja on poistanut paketin."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index e2daae6..94f59fa 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le NIP avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5de0971..965b229 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le code PIN avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Il est impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index ba25f89..a5c42e3 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar un PIN antes de soltar a pantalla"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar un padrón de desbloqueo antes de soltar a pantalla"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Non se pode cambiar o tamaño da aplicación. Desprázate por ela con dous dedos."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado polo administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado polo administrador"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado polo administrador"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index ce05ef5..6dabd69 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"અનપિન કરતાં પહેલાં PIN માટે પૂછો"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"અનપિન કરતા પહેલાં અનલૉક પેટર્ન માટે પૂછો"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ઍપ્લિકેશનનું કદ બદલવા યોગ્ય નથી, બે આંગળીઓ વડે તેને સ્ક્રોલ કરો."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"તમારા વ્યવસ્થાપક દ્વારા ઇન્સ્ટોલ કરેલ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ થયેલ"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખેલ"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 9bc0267..2596f1c0 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1443,8 +1443,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN radi otkvačivanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži uzorak za otključavanje radi otkvačivanja"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži zaporku radi otkvačivanja"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Veličina aplikacije ne može se mijenjati, pomičite je s dva prsta."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurira vaš administrator"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao administrator"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 02c6bed..29474f0 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ապաամրացնելուց առաջ հարցնել PIN-կոդը"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ապաամրացնելուց առաջ հարցնել ապակողպող նախշը"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Հավելվածի չափը հնարավոր չէ փոխել, ոլորեք այն երկու մատի օգնությամբ:"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Ադմինիստրատորը տեղադրել է այն"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ադմինիստրատորը թարմացրել է այն"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Ադմինիստրատորը ջնջել է այն"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7346d31..9a3ae05 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Meminta PIN sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Meminta sandi sebelum melepas sematan"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Aplikasi tidak dapat diubah ukurannya, gulir dengan dua jari."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Diperbarui oleh administrator"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Dihapus oleh administrator"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index c6ec5b1..23db2d2 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Biðja um PIN-númer til að losa"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Biðja um opnunarmynstur til að losa"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Biðja um aðgangsorð til að losa"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Ekki er hægt að breyta stærð forritsins, flettu upp og niður með tveimur fingrum."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Uppsett af kerfisstjóra"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Uppfært af kerfisstjóranum"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eytt af kerfisstjóra"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index c4ecbad..ff005ee 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Richiedi il PIN per lo sblocco"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Richiedi sequenza di sblocco prima di sbloccare"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Richiedi password prima di sbloccare"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Non è posssibile ridimensionare l\'app: scorri con due dita."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installato dall\'amministratore"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Aggiornato dall\'amministratore"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminato dall\'amministratore"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 55fa332..06cf587 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1452,8 +1452,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"בקש PIN לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"בקש קו ביטול נעילה לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"בקש סיסמה לפני ביטול הצמדה"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"אין אפשרות לשנות את גודל האפליקציה, גלול אותה בשתי אצבעות."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"הותקנה על ידי מנהל המערכת שלך"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"עודכן על ידי מנהל המערכת שלך"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"נמחקה על ידי מנהל המערכת שלך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a74d5b7..807dbd3 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"オフライン再生を解除する前にPINの入力を求める"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"アプリのサイズは変更できません。2 本の指でスクロールしてください。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"管理者によってインストールされました"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"管理者によって更新されています"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"管理者によって削除されました"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index d37f6099..9ce703f 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"აპის ზომა ვერ შეიცვლება. გადაადგილდით მასში ორი თითის მეშვეობით."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"თქვენი ადმინისტრატორის მიერ დაყენებული"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"თქვენი ადმინისტრატორის მიერ წაშლილი"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 0a79c3b..7b3c756 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1305,7 +1305,7 @@
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"Қол жетімділік өшірілді."</string>
<string name="user_switched" msgid="3768006783166984410">"Ағымдағы пайдаланушы <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> ауысу орындалуда…"</string>
- <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> ішінен шығу орындалуда…"</string>
+ <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> ішінен шығу…"</string>
<string name="owner_name" msgid="2716755460376028154">"Пайдаланушы"</string>
<string name="error_message_title" msgid="4510373083082500195">"Қателік"</string>
<string name="error_message_change_not_allowed" msgid="1347282344200417578">"Бұл өзгертуге әкімші рұқсат етпеген"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 21b1dc6..ad3b9bd 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1436,8 +1436,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"សួររកកូដ PIN មុនពេលផ្ដាច់"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"សួររកលំនាំដោះសោមុនពេលផ្ដាច់"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"សួររកពាក្យសម្ងាត់មុនពេលផ្ដាច់"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"កម្មវិធីមិនអាចផ្លាស់ប្តូរទំហំបានទេ សូមរមូរវាដោយប្រើម្រាមដៃពីរ។"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"បានដំឡើងដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"បានធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"បានលុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8ed4a6f..8e546ba 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"고정 해제 이전에 PIN 요청"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"고정 해제 이전에 잠금해제 패턴 요청"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"고정 해제 이전에 비밀번호 요청"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"앱에서 크기 조절이 불가능합니다. 두 손가락을 사용해 스크롤하세요."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"관리자가 설치함"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"관리자에 의해 업데이트됨"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"관리자가 삭제함"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 8381c32..55dd4ec 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1435,8 +1435,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Бошотуудан мурун PIN суралсын"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Бошотуудан мурун кулпуну ачкан үлгү суралсын"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Колдонмонун көлөмүн өзгөртүүгө болбойт, андыктан эки манжаңыз менен сыдырып караңыз."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Администраторуңуз тарабынан орнотулган"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Администраторуңуз жаңырткан"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Администраторуңуз тарабынан жок кылынган"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 9884bf1..fa3be85 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1305,7 +1305,7 @@
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"ຍົກເລີກໂຕຊ່ວຍການເຂົ້າເຖິງແລ້ວ."</string>
<string name="user_switched" msgid="3768006783166984410">"ຜູ່ໃຊ້ປັດຈຸບັນ <xliff:g id="NAME">%1$s</xliff:g> ."</string>
<string name="user_switching_message" msgid="2871009331809089783">"ກຳລັງສະລັບໄປຫາ <xliff:g id="NAME">%1$s</xliff:g>…"</string>
- <string name="user_logging_out_message" msgid="8939524935808875155">"ກຳລັງອອກຈາກລະບົບ <xliff:g id="NAME">%1$s</xliff:g>…"</string>
+ <string name="user_logging_out_message" msgid="8939524935808875155">"ກຳລັງອອກຈາກລະບົບ <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="owner_name" msgid="2716755460376028154">"ເຈົ້າຂອງ"</string>
<string name="error_message_title" msgid="4510373083082500195">"ຜິດພາດ"</string>
<string name="error_message_change_not_allowed" msgid="1347282344200417578">"ຜູ່ເບິ່ງແຍງລະບົບຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ປ່ຽນແປງສິ່ງນີ້"</string>
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ຖາມຫາ PIN ກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ຖາມຫາຮູບແບບປົດລັອກກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ຖາມຫາລະຫັດຜ່ານກ່ອນຍົກເລີກການປັກໝຸດ"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ບໍ່ສາມາດປັບຂະໜາດແອັບຯໄດ້, ກະລຸນາເລື່ອນມັນໂດຍໃຊ້ນິ້ວສອງນິ້ວແທນ."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ຜູ້ຄວບຄຸມຂອງທ່ານຕິດຕັ້ງໃສ່ແລ້ວ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"ອັບເດດໂດຍຜູ້ຄວບຄຸມຂອງທ່ານແລ້ວ"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ຖືກຜູ້ຄວບຄຸມຂອງທ່ານລຶບໄປແລ້ວ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 1c326fe..cfcb639 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1452,8 +1452,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prašyti PIN kodo prieš atsegant"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Prašyti atrakinimo piešinio prieš atsegant"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Prašyti slaptažodžio prieš atsegant"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Programos dydis nekeičiamas, slinkite dviem pirštais."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Įdiegė administratorius"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atnaujino administratorius"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Ištrynė administratorius"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index cd2efc4a..99d5d46 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1436,8 +1436,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Прашај за ПИН пред откачување"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Прашај за шема за отклучување пред откачување"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Прашај за лозинка пред откачување"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Не може да се промени големината на апликацијата. Движете ја со два прста."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано од администраторот"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирано од администраторот"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Избришано од администраторот"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index c8eae7e..f114cb9 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടുക"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് പാസ്വേഡ് ആവശ്യപ്പെടുക"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ആപ്പിന്റെ വലുപ്പം ക്രമീകരിക്കാൻ കഴിയില്ല, രണ്ട് വിരലുകൾ ഉപയോഗിച്ച് അത് സ്ക്രോൾ ചെയ്യുക."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർ ഇൻസ്റ്റാളുചെയ്തു"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർ അപ്ഡേറ്റുചെയ്തു"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർ ഇല്ലാതാക്കി"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 7b7d4b1..ac226a4 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тогтоосныг суллахаас өмнө PIN асуух"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тогтоосныг суллахаас өмнө түгжээ тайлах хээ асуух"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Апп-н хэмжээ нь өөрчлөгддөггүй. Үүнийг 2 хуруугаараа гүйлгэнэ үү."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Таны админ суулгасан байна"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Танай админ шинэчилсэн"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Таны админ устгасан байна"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index f354ea0..d9175c2 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Minta PIN sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Minta corak buka kunci sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Apl tidak boleh tukar saiznya, tatal apl itu menggunakan dua jari."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh pentadbir anda"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Dikemas kini oleh pentadbir anda"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Dipadamkan oleh pentadbir anda"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4fc7078..f504175 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kode for å løsne apper"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Krev bruk av opplåsningsmønster for å løsne apper"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Krev passord for å løsne apper"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Du kan ikke endre størrselse på appen – rull med to fingre."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installert av administratoren"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Oppdatert av administratoren"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet av administratoren"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 17e67f8..7867c59 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1440,12 +1440,11 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"पिन निकाल्नुअघि PIN सोध्नुहोस्"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"पिन निकाल्नुअघि खोल्ने रूपरेखा सोध्नुहोस्"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"अनुप्रयोगको आकार सानो-ठुलो बनाउन मिल्दैन, दुई औँलाले यसलाई स्क्रोल गर्नुहोस्।"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"तपाईँको प्रशासकद्वारा स्थापना गरिएको"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"तपाईँको प्रशासकद्वारा अद्यावधिक गरिएको"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"तपाईँको प्रशासकद्वारा हटाइएको"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"ब्याट्रीको आयु सुधार्न, ब्याट्री रक्षकले तपाईँको यन्त्रको कार्यसम्पादन घटाउँछ र भाइब्रेसन, स्थान सेवा र बहुसंख्यक पृष्ठभूमि डेटा सीमित गर्दछ। इमेल, सन्देश, र अन्य अनुप्रयोगहरू जुन सिङ्कमा भर पर्छन् अद्यावधिक नहुन सक्छन् जबसम्म तपाईँ तिनीहरूलाई खोल्नुहुन्न\n\n ब्याट्री रक्षक स्वत: निस्कृय हुन्छ जब तपाईँको यन्त्र चार्ज हुँदै हुन्छ।"</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"ब्याट्रीको आयु सुधार्न, ब्याट्री संरक्षकले तपाईँको यन्त्रको कार्यसम्पादन घटाउँछ र भाइब्रेसन, स्थान सेवा र बहुसंख्यक पृष्ठभूमि डेटा सीमित गर्दछ। इमेल, सन्देश, र अन्य अनुप्रयोगहरू जुन सिङ्कमा भर पर्छन् अद्यावधिक नहुन सक्छन् जबसम्म तपाईँ तिनीहरूलाई खोल्नुहुन्न\n\n ब्याट्री संरक्षक स्वत: निस्कृय हुन्छ जब तपाईँको यन्त्र चार्ज हुँदै हुन्छ।"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
<item quantity="other"> %1$d मिनेटको लागि (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> सम्म)</item>
<item quantity="one">एक मिनेटको लागि (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> सम्म)</item>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 14e56cb..ad826262 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1452,8 +1452,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Podaj PIN, aby odpiąć"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Aby odpiąć, poproś o wzór odblokowania"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Aby odpiąć, poproś o hasło"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Rozmiaru tej aplikacji nie można zmienić. Przewiń ją dwoma palcami."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Zainstalowany przez administratora"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Zaktualizowane przez administratora"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Usunięty przez administratora"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 8212d13..c338b3b 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"O app não é redimensionável. Desloque-o com dois dedos."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 90091d8..6b0581f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de soltar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir sequência de desbloqueio antes de soltar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir palavra-passe antes de soltar"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"A aplicação não é redimensionável. Desloque-a com dois dedos."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado pelo administrador"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 8212d13..c338b3b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"O app não é redimensionável. Desloque-o com dois dedos."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 9536c70..9e676fd 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1443,8 +1443,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicită codul PIN înainte de a anula fixarea"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicită modelul pentru deblocare înainte de a anula fixarea"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicită parola înainte de a anula fixarea"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Aplicația nu poate fi redimensionată. Derulați în ea cu două degete."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalat de administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizat de un administrator"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Șters de administrator"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 613c738..ca1a986 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1452,8 +1452,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для отключения"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запрашивать графический ключ для отключения блокировки"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Размер окна нельзя изменить. Прокрутите страницу двумя пальцами."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Установлено администратором"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Обновлено администратором"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Удалено администратором"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index b9ae0e9..66061d1 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1436,8 +1436,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ගැලවීමට පෙර PIN විමසන්න"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"යෙදුම ප්රතිප්රමාණ කළ හැකි නොවේ, එය ඇඟිලි දෙකකින් අනුචලනය කරන්න."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ඔබගේ පරිපාලක විසින් ස්ථාපනය කරන ලද"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"ඔබගේ පරිපාලක විසින් යාවත්කාලීන කරන ලදී"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ඔබගේ පරිපාලක විසින් මකන ලද"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 856f8f7..72e8db2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1452,8 +1452,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pred uvoľnením požiadať o číslo PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred uvoľnením požiadať o heslo"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Veľkosť aplikácie nie je možné zmeniť. Zobrazenie môžete posúvať dvoma prstami."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Inštalovaný správcom"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizované správcom"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Odstránený správcom"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index eff1574..9f1c669 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1452,8 +1452,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zahtevaj PIN pred odpenjanjem"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred odpenjanjem vprašaj za geslo"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Velikosti aplikacije ni mogoče spremeniti. Po njej se pomikajte z dvema prstoma."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Namestil skrbnik"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Posodobil skrbnik"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisal skrbnik"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index a29a960..d67a5fe 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zhgozhdimi kërkon PIN-in"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Kërko model shkyçjeje para heqjes së gozhdimit"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Përmasa e apl. nuk mund të ndryshohet, lëvize atë me të dy gishtat."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"U instalua nga administratori yt"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Përditësuar nga administratori"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"U fshi nga administratori yt"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 9d12292..ddb9ba7 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1443,8 +1443,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тражи PIN пре откачињања"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тражи шаблон за откључавање пре откачињања"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тражи лозинку пре откачињања"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Величина апликације не може да се мења, померајте је помоћу два прста."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирао је ваш администратор"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирао је администратор"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Избрисао је ваш адмиистратор"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 57edbcb..f5172fe 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Be om pinkod innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Be om lösenord innan skärmen slutar fästas"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Det går inte att ändra appens storlek. Rulla med två fingrar."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Paketet har installerats av administratören"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Uppdaterat av administratören"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Paketet har raderats av administratören"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f168d6c..81bc75f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ขอ PIN ก่อนเลิกตรึง"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ขอรูปแบบการปลดล็อกก่อนเลิกตรึง"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ขอรหัสผ่านก่อนเลิกตรึง"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"แอปไม่สามารถปรับขนาดได้ เลื่อนแอปด้วยนิ้ว 2 นิ้ว"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ติดตั้งโดยผู้ดูแลระบบของคุณ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"อัปเดตโดยผู้ดูแลระบบ"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ลบโดยผู้ดูแลระบบของคุณ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ab30e30..29efae69 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Humingi ng PIN bago mag-unpin"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Humingi ng password bago mag-unpin"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Hindi nare-resize ang app, mag-scroll dito gamit ang dalawang daliri."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Na-install ng iyong administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Na-update ng iyong administrator"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Na-delete ng iyong administrator"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8cf8935..dac5259 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Uygulama yeniden boyutlandırılamaz. İki parmağınızla kaydırın."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Yöneticiniz tarafından yüklendi"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Yöneticiniz tarafından güncellendi"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Yöneticiniz tarafından silindi"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index c4d2466..388b790 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"پن ہٹانے سے پہلے PIN طلب کریں"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ایپ ری سائز ایبل نہیں ہے، اسے دو انگلیوں کے ساتھ سکرول کریں۔"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"آپ کے منتظم کی جانب سے انسٹال کر دیا گیا"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"آپ کے منتظم نے اپ ڈيٹ کر دیا"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"آپ کے منتظم کی جانب سے حذف کر دیا گیا"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 596bbed..bafedfc 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Yechishda PIN-kod so‘ralsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bo‘shatishdan oldin chizmali parol so‘ralsin"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Oyna o‘lchamini o‘zgartirib bo‘lmaydi. Sahifani ikkita barmoq bilan aylantiring."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Administratoringiz tomonidan o‘rnatilgan"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratoringiz tomonidan o‘chirilgan"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c5aa37e..9165f4d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Hỏi mã PIN trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Hỏi mật khẩu trước khi bỏ ghim"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Ứng dụng không đổi kích thước được, hãy cuộn ứng dụng bằng hai ngón tay."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Được cài đặt bởi quản trị viên của bạn"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Được cập nhật bởi quản trị viên của bạn"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Đã bị xóa bởi quản trị viên của bạn"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 311fe55..36a1a7f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1305,8 +1305,7 @@
<string name="enable_accessibility_canceled" msgid="3833923257966635673">"已取消无障碍功能。"</string>
<string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
<string name="user_switching_message" msgid="2871009331809089783">"正在切换为<xliff:g id="NAME">%1$s</xliff:g>…"</string>
- <!-- no translation found for user_logging_out_message (8939524935808875155) -->
- <skip />
+ <string name="user_logging_out_message" msgid="8939524935808875155">"正在将<xliff:g id="NAME">%1$s</xliff:g>退出帐号…"</string>
<string name="owner_name" msgid="2716755460376028154">"机主"</string>
<string name="error_message_title" msgid="4510373083082500195">"错误"</string>
<string name="error_message_change_not_allowed" msgid="1347282344200417578">"您的管理员不允许进行此更改"</string>
@@ -1435,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消时要求输入PIN码"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消时要求绘制解锁图案"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"无法调整这个应用的大小,请用双指滚动应用。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 4d23d76..e938fb8 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1434,8 +1434,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖形"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
- <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
- <skip />
+ <string name="dock_non_resizeble_text" msgid="9156251681042762723">"無法調整這個應用程式的大小,請用雙指捲動該應用程式。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"由您的管理員更新"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"已遭管理員刪除"</string>
diff --git a/data/sounds/AllAudio.mk b/data/sounds/AllAudio.mk
index f6d8ee9..edfd380 100644
--- a/data/sounds/AllAudio.mk
+++ b/data/sounds/AllAudio.mk
@@ -228,6 +228,7 @@
$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
$(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/ogg/VideoStop_48k.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index 5a5eea6..c5222af 100644
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
@@ -1,9 +1,9 @@
#
# Audio Package 10 - Mako
-#
+#
# Include this file in a product makefile to include these audio files
#
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -23,6 +23,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/material/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoStop_48k.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/material/ogg/LowBattery_48k.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk
index 0f85b33..43c83b9 100644
--- a/data/sounds/AudioPackage11.mk
+++ b/data/sounds/AudioPackage11.mk
@@ -1,9 +1,9 @@
#
# Audio Package 11 - Razor
-#
+#
# Include this file in a product makefile to include these audio files
#
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -23,6 +23,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/material/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoStop_48k.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/material/ogg/LowBattery_48k.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/AudioPackage12.mk b/data/sounds/AudioPackage12.mk
index 4251332..cd4d35b 100644
--- a/data/sounds/AudioPackage12.mk
+++ b/data/sounds/AudioPackage12.mk
@@ -13,7 +13,7 @@
RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel
EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
camera_focus Dock Undock Lock Unlock Trusted
-MATERIAL_EFFECT_FILES := camera_click VideoRecord LowBattery WirelessChargingStarted
+MATERIAL_EFFECT_FILES := camera_click VideoRecord LowBattery WirelessChargingStarted VideoStop
PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
$(LOCAL_PATH)/alarms/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
diff --git a/data/sounds/AudioPackage12_48.mk b/data/sounds/AudioPackage12_48.mk
index 70e68d3..80758f4 100644
--- a/data/sounds/AudioPackage12_48.mk
+++ b/data/sounds/AudioPackage12_48.mk
@@ -13,7 +13,7 @@
RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel
EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
Lock Unlock Trusted
-MATERIAL_EFFECT_FILES := camera_click VideoRecord LowBattery WirelessChargingStarted
+MATERIAL_EFFECT_FILES := camera_click VideoRecord LowBattery WirelessChargingStarted VideoStop
# Alarms not yet available in 48 kHz
PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
diff --git a/data/sounds/AudioPackage13.mk b/data/sounds/AudioPackage13.mk
index cec7280..d33a4af 100644
--- a/data/sounds/AudioPackage13.mk
+++ b/data/sounds/AudioPackage13.mk
@@ -14,7 +14,7 @@
Umbriel
EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
camera_focus Dock Undock Lock Unlock Trusted
-MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery
+MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery VideoStop
PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
$(LOCAL_PATH)/alarms/material/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
diff --git a/data/sounds/AudioPackage13_48.mk b/data/sounds/AudioPackage13_48.mk
index d1b17c8..9c320ae 100644
--- a/data/sounds/AudioPackage13_48.mk
+++ b/data/sounds/AudioPackage13_48.mk
@@ -14,7 +14,7 @@
Umbriel
EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
Lock Unlock Trusted
-MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery
+MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery VideoStop
PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
$(LOCAL_PATH)/alarms/material/ogg/$(fn)_48k.ogg:system/media/audio/alarms/$(fn).ogg)
diff --git a/data/sounds/AudioPackage2.mk b/data/sounds/AudioPackage2.mk
index ba9d7e2..40319c4 100644
--- a/data/sounds/AudioPackage2.mk
+++ b/data/sounds/AudioPackage2.mk
@@ -1,11 +1,11 @@
#
# Audio Package 2
-#
+#
# Include this file in a product makefile to include these audio files
#
# This is a larger package of sounds than the 1.0 release for devices
# that have larger internal flash.
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -34,6 +34,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
diff --git a/data/sounds/AudioPackage3.mk b/data/sounds/AudioPackage3.mk
index 5bfeb42..a05de72 100644
--- a/data/sounds/AudioPackage3.mk
+++ b/data/sounds/AudioPackage3.mk
@@ -1,11 +1,11 @@
#
# Audio Package 3
-#
+#
# Include this file in a product makefile to include these audio files
#
# This is a larger package of sounds than the 1.0 release for devices
# that have larger internal flash.
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -34,6 +34,7 @@
$(LOCAL_PATH)/effects/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
diff --git a/data/sounds/AudioPackage4.mk b/data/sounds/AudioPackage4.mk
index 43dbe20..d376a2d 100644
--- a/data/sounds/AudioPackage4.mk
+++ b/data/sounds/AudioPackage4.mk
@@ -1,11 +1,11 @@
#
# Audio Package 4
-#
+#
# Include this file in a product makefile to include these audio files
#
# This is a larger package of sounds than the 1.0 release for devices
# that have larger internal flash.
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -39,6 +39,7 @@
$(LOCAL_PATH)/effects/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
diff --git a/data/sounds/AudioPackage5.mk b/data/sounds/AudioPackage5.mk
index fbbb16a..72384c8 100644
--- a/data/sounds/AudioPackage5.mk
+++ b/data/sounds/AudioPackage5.mk
@@ -1,9 +1,9 @@
#
# Audio Package 5 - Crespo/Soju
-#
+#
# Include this file in a product makefile to include these audio files
#
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -20,6 +20,7 @@
$(LOCAL_PATH)/effects/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/AudioPackage6.mk b/data/sounds/AudioPackage6.mk
index c843fdc..5413704 100644
--- a/data/sounds/AudioPackage6.mk
+++ b/data/sounds/AudioPackage6.mk
@@ -1,9 +1,9 @@
#
# Audio Package 6 - Trygon/Stingray
-#
+#
# Include this file in a product makefile to include these audio files
#
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -19,6 +19,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index ce82651..e4763be 100644
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -1,9 +1,9 @@
#
# Audio Package 7 - Tuna
-#
+#
# Include this file in a product makefile to include these audio files
#
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -21,6 +21,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_120.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/AudioPackage7alt.mk b/data/sounds/AudioPackage7alt.mk
index db468f3..30e6173 100644
--- a/data/sounds/AudioPackage7alt.mk
+++ b/data/sounds/AudioPackage7alt.mk
@@ -21,6 +21,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_120.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/ogg/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
index 4112c18..b38e62d 100644
--- a/data/sounds/AudioPackage8.mk
+++ b/data/sounds/AudioPackage8.mk
@@ -1,9 +1,9 @@
#
# Audio Package 7 - Tuna
-#
+#
# Include this file in a product makefile to include these audio files
#
-#
+#
LOCAL_PATH:= frameworks/base/data/sounds
@@ -23,6 +23,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk
index 1b430c0..dbe1350 100644
--- a/data/sounds/AudioPackage9.mk
+++ b/data/sounds/AudioPackage9.mk
@@ -23,6 +23,7 @@
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/material/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
diff --git a/data/sounds/OriginalAudio.mk b/data/sounds/OriginalAudio.mk
index e1ca24b..f683752 100644
--- a/data/sounds/OriginalAudio.mk
+++ b/data/sounds/OriginalAudio.mk
@@ -1,8 +1,8 @@
#
# Original audio package that shipped on G1
-#
+#
# This file is included from core.mk so that all devices will have these sounds
-#
+#
# TODO: Clean up for future releases
#
@@ -32,6 +32,7 @@
$(LOCAL_PATH)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
$(LOCAL_PATH)/newwavelabs/CaffeineSnake.ogg:system/media/audio/notifications/CaffeineSnake.ogg
diff --git a/data/sounds/effects/VideoStop.ogg b/data/sounds/effects/VideoStop.ogg
new file mode 100644
index 0000000..1450522
--- /dev/null
+++ b/data/sounds/effects/VideoStop.ogg
Binary files differ
diff --git a/data/sounds/effects/VideoStop.wav b/data/sounds/effects/VideoStop.wav
new file mode 100644
index 0000000..5809d93
--- /dev/null
+++ b/data/sounds/effects/VideoStop.wav
Binary files differ
diff --git a/data/sounds/effects/material/ogg/VideoStop.ogg b/data/sounds/effects/material/ogg/VideoStop.ogg
new file mode 100644
index 0000000..e98fabc0
--- /dev/null
+++ b/data/sounds/effects/material/ogg/VideoStop.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/VideoStop_48k.ogg b/data/sounds/effects/material/ogg/VideoStop_48k.ogg
new file mode 100644
index 0000000..b1eb780
--- /dev/null
+++ b/data/sounds/effects/material/ogg/VideoStop_48k.ogg
Binary files differ
diff --git a/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml b/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml
index d1a956bf..069e137 100644
--- a/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Tashqi xotira"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Ichki xotira"</string>
- <string name="root_home" msgid="7931555396767513359">"Shaxsiy"</string>
+ <string name="root_home" msgid="7931555396767513359">"Mening fayllarim"</string>
</resources>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
deleted file mode 100644
index 844b216..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mtp;
-
-import android.content.res.Resources;
-import android.database.MatrixCursor;
-import android.media.MediaFile;
-import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo;
-import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Document;
-
-/**
- * TODO Remove this class after we switch to use MtpDatabase.
- */
-final class CursorHelper {
- static final int DUMMY_HANDLE_FOR_ROOT = 0;
-
- private CursorHelper() {
- }
-
- static void addToCursor(Resources resources, MtpRoot root, MatrixCursor.RowBuilder builder) {
- final Identifier identifier = new Identifier(
- root.mDeviceId, root.mStorageId, DUMMY_HANDLE_FOR_ROOT);
- builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
- builder.add(Document.COLUMN_DISPLAY_NAME, root.getRootName(resources));
- builder.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
- builder.add(Document.COLUMN_LAST_MODIFIED, null);
- builder.add(Document.COLUMN_FLAGS, 0);
- builder.add(Document.COLUMN_SIZE,
- (int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE));
- }
-
- static void addToCursor(MtpObjectInfo objectInfo, Identifier rootIdentifier,
- MatrixCursor.RowBuilder builder) {
- final Identifier identifier = new Identifier(
- rootIdentifier.mDeviceId, rootIdentifier.mStorageId, objectInfo.getObjectHandle());
- final String mimeType = formatTypeToMimeType(objectInfo.getFormat());
-
- int flag = 0;
- if (objectInfo.getProtectionStatus() == 0) {
- flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
- if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR) {
- flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
- }
- }
- if (objectInfo.getThumbCompressedSize() > 0) {
- flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
- }
-
- builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
- builder.add(Document.COLUMN_DISPLAY_NAME, objectInfo.getName());
- builder.add(Document.COLUMN_MIME_TYPE, mimeType);
- builder.add(
- Document.COLUMN_LAST_MODIFIED,
- objectInfo.getDateModified() != 0 ? objectInfo.getDateModified() : null);
- builder.add(Document.COLUMN_FLAGS, flag);
- builder.add(Document.COLUMN_SIZE, objectInfo.getCompressedSize());
- }
-
- static String formatTypeToMimeType(int format) {
- if (format == MtpConstants.FORMAT_ASSOCIATION) {
- return DocumentsContract.Document.MIME_TYPE_DIR;
- } else {
- return MediaFile.getMimeTypeForFormatCode(format);
- }
- }
-
- static int mimeTypeToFormatType(String fileName, String mimeType) {
- if (Document.MIME_TYPE_DIR.equals(mimeType)) {
- return MtpConstants.FORMAT_ASSOCIATION;
- } else {
- return MediaFile.getFormatCode(fileName, mimeType);
- }
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 1c96906..6fa0df2 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -24,7 +24,6 @@
import android.os.Bundle;
import android.os.Process;
import android.provider.DocumentsContract;
-import android.util.Log;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -75,9 +74,15 @@
int parentHandle = parent.mObjectHandle;
// Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
// getObjectHandles if we would like to obtain children under the root.
- if (parentHandle == CursorHelper.DUMMY_HANDLE_FOR_ROOT) {
+ if (parentHandle == Identifier.DUMMY_HANDLE_FOR_ROOT) {
parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
}
+ // TODO: Handle nit race around here.
+ // 1. getObjectHandles.
+ // 2. putNewDocument.
+ // 3. startAddingChildDocuemnts.
+ // 4. stopAddingChildDocuments - It removes the new document added at the step 2,
+ // because it is not updated between start/stopAddingChildDocuments.
task = new LoaderTask(mDatabase, parent, mMtpManager.getObjectHandles(
parent.mDeviceId, parent.mStorageId, parentHandle));
task.fillDocuments(loadDocuments(
@@ -215,8 +220,8 @@
throw new IOException(mError);
}
- final Cursor cursor = mDatabase.queryChildDocuments(
- columnNames, mIdentifier.mDocumentId, /* use old ID format */ true);
+ final Cursor cursor =
+ mDatabase.queryChildDocuments(columnNames, mIdentifier.mDocumentId);
cursor.setNotificationUri(resolver, createUri());
cursor.respond(extras);
@@ -250,10 +255,10 @@
return;
}
if (mNumLoaded == 0) {
- mDatabase.startAddingChildDocuments(mIdentifier.mDocumentId);
+ mDatabase.getMapper().startAddingChildDocuments(mIdentifier.mDocumentId);
}
try {
- mDatabase.putChildDocuments(
+ mDatabase.getMapper().putChildDocuments(
mIdentifier.mDeviceId, mIdentifier.mDocumentId, objectInfoList);
mNumLoaded += objectInfoList.length;
} catch (SQLiteException exp) {
@@ -261,7 +266,7 @@
mNumLoaded = 0;
}
if (getState() != STATE_LOADING) {
- mDatabase.stopAddingChildDocuments(mIdentifier.mDocumentId);
+ mDatabase.getMapper().stopAddingChildDocuments(mIdentifier.mDocumentId);
}
}
@@ -270,13 +275,13 @@
mError = message;
mNumLoaded = 0;
if (lastState == STATE_LOADING) {
- mDatabase.stopAddingChildDocuments(mIdentifier.mDocumentId);
+ mDatabase.getMapper().stopAddingChildDocuments(mIdentifier.mDocumentId);
}
}
private Uri createUri() {
return DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, mIdentifier.toDocumentId());
+ MtpDocumentsProvider.AUTHORITY, mIdentifier.mDocumentId);
}
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
index 4238721e..20b3bf5 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
@@ -16,39 +16,19 @@
package com.android.mtp;
+import java.util.Objects;
+
/**
* Static utilities for ID.
*/
class Identifier {
+ final static int DUMMY_HANDLE_FOR_ROOT = 0;
+
final int mDeviceId;
final int mStorageId;
final int mObjectHandle;
final String mDocumentId;
- static Identifier createFromRootId(String rootId) {
- final String[] components = rootId.split("_");
- return new Identifier(
- Integer.parseInt(components[0]),
- Integer.parseInt(components[1]));
- }
-
- static Identifier createFromDocumentId(String documentId) {
- final String[] components = documentId.split("_");
- return new Identifier(
- Integer.parseInt(components[0]),
- Integer.parseInt(components[1]),
- Integer.parseInt(components[2]));
- }
-
-
- Identifier(int deviceId, int storageId) {
- this(deviceId, storageId, CursorHelper.DUMMY_HANDLE_FOR_ROOT);
- }
-
- Identifier(int deviceId, int storageId, int objectHandle) {
- this(deviceId, storageId, objectHandle, null);
- }
-
Identifier(int deviceId, int storageId, int objectHandle, String documentId) {
mDeviceId = deviceId;
mStorageId = storageId;
@@ -56,16 +36,6 @@
mDocumentId = documentId;
}
- // TODO: Make the ID persistent.
- String toRootId() {
- return String.format("%d_%d", mDeviceId, mStorageId);
- }
-
- // TODO: Make the ID persistent.
- String toDocumentId() {
- return String.format("%d_%d_%d", mDeviceId, mStorageId, mObjectHandle);
- }
-
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Identifier))
@@ -77,6 +47,6 @@
@Override
public int hashCode() {
- return (mDeviceId << 16) ^ (mStorageId << 8) ^ mObjectHandle;
+ return Objects.hash(mDeviceId, mStorageId, mObjectHandle, mDocumentId);
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
new file mode 100644
index 0000000..0d9d60c
--- /dev/null
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mtp;
+
+import static com.android.mtp.MtpDatabaseConstants.*;
+
+import android.content.ContentValues;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.mtp.MtpObjectInfo;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.android.mtp.MtpDatabase.strings;
+
+
+/**
+ * Mapping operations for MtpDatabase.
+ * Also see the comments of {@link MtpDatabase}.
+ */
+class Mapper {
+ private final MtpDatabase mDatabase;
+
+ /**
+ * Mapping mode for roots/documents where we start adding child documents.
+ * Methods operate the state needs to be synchronized.
+ */
+ private final Map<String, Integer> mMappingMode = new HashMap<>();
+
+ Mapper(MtpDatabase database) {
+ mDatabase = database;
+ }
+
+ /**
+ * Invokes {@link #startAddingDocuments} for root documents.
+ * @param deviceId Device ID.
+ */
+ synchronized void startAddingRootDocuments(int deviceId) {
+ final String mappingStateKey = getRootDocumentsMappingStateKey(deviceId);
+ Preconditions.checkState(!mMappingMode.containsKey(mappingStateKey));
+ mMappingMode.put(
+ mappingStateKey,
+ startAddingDocuments(
+ SELECTION_ROOT_DOCUMENTS, Integer.toString(deviceId)));
+ }
+
+ /**
+ * Invokes {@link #startAddingDocuments} for child of specific documents.
+ * @param parentDocumentId Document ID for parent document.
+ */
+ @VisibleForTesting
+ synchronized void startAddingChildDocuments(String parentDocumentId) {
+ final String mappingStateKey = getChildDocumentsMappingStateKey(parentDocumentId);
+ Preconditions.checkState(!mMappingMode.containsKey(mappingStateKey));
+ mMappingMode.put(
+ mappingStateKey,
+ startAddingDocuments(SELECTION_CHILD_DOCUMENTS, parentDocumentId));
+ }
+
+ /**
+ * Puts root information to database.
+ * @param deviceId Device ID
+ * @param resources Resources required to localize root name.
+ * @param roots List of root information.
+ * @return If roots are added or removed from the database.
+ */
+ synchronized boolean putRootDocuments(int deviceId, Resources resources, MtpRoot[] roots) {
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ database.beginTransaction();
+ try {
+ final boolean heuristic;
+ final String mapColumn;
+ final String key = getRootDocumentsMappingStateKey(deviceId);
+ Preconditions.checkState(mMappingMode.containsKey(key));
+ switch (mMappingMode.get(key)) {
+ case MAP_BY_MTP_IDENTIFIER:
+ heuristic = false;
+ mapColumn = COLUMN_STORAGE_ID;
+ break;
+ case MAP_BY_NAME:
+ heuristic = true;
+ mapColumn = Document.COLUMN_DISPLAY_NAME;
+ break;
+ default:
+ throw new Error("Unexpected map mode.");
+ }
+ final ContentValues[] valuesList = new ContentValues[roots.length];
+ for (int i = 0; i < roots.length; i++) {
+ if (roots[i].mDeviceId != deviceId) {
+ throw new IllegalArgumentException();
+ }
+ valuesList[i] = new ContentValues();
+ MtpDatabase.getRootDocumentValues(valuesList[i], resources, roots[i]);
+ }
+ final boolean changed = putDocuments(
+ valuesList,
+ SELECTION_ROOT_DOCUMENTS,
+ Integer.toString(deviceId),
+ heuristic,
+ mapColumn);
+ final ContentValues values = new ContentValues();
+ int i = 0;
+ for (final MtpRoot root : roots) {
+ // Use the same value for the root ID and the corresponding document ID.
+ final String documentId = valuesList[i++].getAsString(Document.COLUMN_DOCUMENT_ID);
+ // If it fails to insert/update documents, the document ID will be set with -1.
+ // In this case we don't insert/update root extra information neither.
+ if (documentId == null) {
+ continue;
+ }
+ values.put(Root.COLUMN_ROOT_ID, documentId);
+ values.put(
+ Root.COLUMN_FLAGS,
+ Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
+ values.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
+ values.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
+ values.put(Root.COLUMN_MIME_TYPES, "");
+ database.replace(TABLE_ROOT_EXTRA, null, values);
+ }
+ database.setTransactionSuccessful();
+ return changed;
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ /**
+ * Puts document information to database.
+ * @param deviceId Device ID
+ * @param parentId Parent document ID.
+ * @param documents List of document information.
+ */
+ synchronized void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents) {
+ final boolean heuristic;
+ final String mapColumn;
+ final String key = getChildDocumentsMappingStateKey(parentId);
+ Preconditions.checkState(mMappingMode.containsKey(key));
+ switch (mMappingMode.get(key)) {
+ case MAP_BY_MTP_IDENTIFIER:
+ heuristic = false;
+ mapColumn = COLUMN_OBJECT_HANDLE;
+ break;
+ case MAP_BY_NAME:
+ heuristic = true;
+ mapColumn = Document.COLUMN_DISPLAY_NAME;
+ break;
+ default:
+ throw new Error("Unexpected map mode.");
+ }
+ final ContentValues[] valuesList = new ContentValues[documents.length];
+ for (int i = 0; i < documents.length; i++) {
+ valuesList[i] = new ContentValues();
+ MtpDatabase.getChildDocumentValues(
+ valuesList[i], deviceId, parentId, documents[i]);
+ }
+ putDocuments(
+ valuesList, SELECTION_CHILD_DOCUMENTS, parentId, heuristic, mapColumn);
+ }
+
+ /**
+ * Stops adding root documents.
+ * @param deviceId Device ID.
+ * @return True if new rows are added/removed.
+ */
+ synchronized boolean stopAddingRootDocuments(int deviceId) {
+ final String key = getRootDocumentsMappingStateKey(deviceId);
+ Preconditions.checkState(mMappingMode.containsKey(key));
+ switch (mMappingMode.get(key)) {
+ case MAP_BY_MTP_IDENTIFIER:
+ mMappingMode.remove(key);
+ return stopAddingDocuments(
+ SELECTION_ROOT_DOCUMENTS,
+ Integer.toString(deviceId),
+ COLUMN_STORAGE_ID);
+ case MAP_BY_NAME:
+ mMappingMode.remove(key);
+ return stopAddingDocuments(
+ SELECTION_ROOT_DOCUMENTS,
+ Integer.toString(deviceId),
+ Document.COLUMN_DISPLAY_NAME);
+ default:
+ throw new Error("Unexpected mapping state.");
+ }
+ }
+
+ /**
+ * Stops adding documents under the parent.
+ * @param parentId Document ID of the parent.
+ */
+ synchronized void stopAddingChildDocuments(String parentId) {
+ final String key = getChildDocumentsMappingStateKey(parentId);
+ Preconditions.checkState(mMappingMode.containsKey(key));
+ switch (mMappingMode.get(key)) {
+ case MAP_BY_MTP_IDENTIFIER:
+ stopAddingDocuments(
+ SELECTION_CHILD_DOCUMENTS,
+ parentId,
+ COLUMN_OBJECT_HANDLE);
+ break;
+ case MAP_BY_NAME:
+ stopAddingDocuments(
+ SELECTION_CHILD_DOCUMENTS,
+ parentId,
+ Document.COLUMN_DISPLAY_NAME);
+ break;
+ default:
+ throw new Error("Unexpected mapping state.");
+ }
+ mMappingMode.remove(key);
+ }
+
+ @VisibleForTesting
+ void clearMapping() {
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ database.beginTransaction();
+ try {
+ mDatabase.deleteDocumentsAndRootsRecursively(
+ COLUMN_ROW_STATE + " = ?", strings(ROW_STATE_PENDING));
+ final ContentValues values = new ContentValues();
+ values.putNull(COLUMN_OBJECT_HANDLE);
+ values.putNull(COLUMN_STORAGE_ID);
+ values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
+ database.update(TABLE_DOCUMENTS, values, null, null);
+ database.setTransactionSuccessful();
+ mMappingMode.clear();
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ /**
+ * Starts adding new documents.
+ * The methods decides mapping mode depends on if all documents under the given parent have MTP
+ * identifier or not. If all the documents have MTP identifier, it uses the identifier to find
+ * a corresponding existing row. Otherwise it does heuristic.
+ *
+ * @param selection Query matches valid documents.
+ * @param arg Argument for selection.
+ * @return Mapping mode.
+ */
+ private int startAddingDocuments(String selection, String arg) {
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ database.beginTransaction();
+ try {
+ // Delete all pending rows.
+ mDatabase.deleteDocumentsAndRootsRecursively(
+ selection + " AND " + COLUMN_ROW_STATE + "=?", strings(arg, ROW_STATE_PENDING));
+
+ // Set all documents as invalidated.
+ final ContentValues values = new ContentValues();
+ values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
+ database.update(TABLE_DOCUMENTS, values, selection, new String[] { arg });
+
+ // If we have rows that does not have MTP identifier, do heuristic mapping by name.
+ final boolean useNameForResolving = DatabaseUtils.queryNumEntries(
+ database,
+ TABLE_DOCUMENTS,
+ selection + " AND " + COLUMN_STORAGE_ID + " IS NULL",
+ new String[] { arg }) > 0;
+ database.setTransactionSuccessful();
+ return useNameForResolving ? MAP_BY_NAME : MAP_BY_MTP_IDENTIFIER;
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ /**
+ * Puts the documents into the database.
+ * If the mapping mode is not heuristic, it just adds the rows to the database or updates the
+ * existing rows with the new values. If the mapping mode is heuristic, it adds some new rows as
+ * 'pending' state when that rows may be corresponding to existing 'invalidated' rows. Then
+ * {@link #stopAddingDocuments(String, String, String)} turns the pending rows into 'valid'
+ * rows. If the methods adds rows to database, it updates valueList with correct document ID.
+ *
+ * @param valuesList Values for documents to be stored in the database.
+ * @param selection SQL where closure to select rows that shares the same parent.
+ * @param arg Argument for selection SQL.
+ * @param heuristic Whether the mapping mode is heuristic.
+ * @return Whether the method adds new rows.
+ */
+ private boolean putDocuments(
+ ContentValues[] valuesList,
+ String selection,
+ String arg,
+ boolean heuristic,
+ String mappingKey) {
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ boolean added = false;
+ database.beginTransaction();
+ try {
+ for (final ContentValues values : valuesList) {
+ final Cursor candidateCursor = database.query(
+ TABLE_DOCUMENTS,
+ strings(Document.COLUMN_DOCUMENT_ID),
+ selection + " AND " +
+ COLUMN_ROW_STATE + "=? AND " +
+ mappingKey + "=?",
+ strings(arg, ROW_STATE_INVALIDATED, values.getAsString(mappingKey)),
+ null,
+ null,
+ null,
+ "1");
+ try {
+ final long rowId;
+ if (candidateCursor.getCount() == 0) {
+ rowId = database.insert(TABLE_DOCUMENTS, null, values);
+ if (rowId == -1) {
+ throw new SQLiteException("Failed to put a document into database.");
+ }
+ added = true;
+ } else if (!heuristic) {
+ candidateCursor.moveToNext();
+ final String documentId = candidateCursor.getString(0);
+ rowId = database.update(
+ TABLE_DOCUMENTS,
+ values,
+ SELECTION_DOCUMENT_ID,
+ strings(documentId));
+ } else {
+ values.put(COLUMN_ROW_STATE, ROW_STATE_PENDING);
+ rowId = database.insert(TABLE_DOCUMENTS, null, values);
+ }
+ // Document ID is a primary integer key of the table. So the returned row
+ // IDs should be same with the document ID.
+ values.put(Document.COLUMN_DOCUMENT_ID, rowId);
+ } finally {
+ candidateCursor.close();
+ }
+ }
+
+ database.setTransactionSuccessful();
+ return added;
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ /**
+ * Maps 'pending' document and 'invalidated' document that shares the same column of groupKey.
+ * If the database does not find corresponding 'invalidated' document, it just removes
+ * 'invalidated' document from the database.
+ * @param selection Query to select rows for resolving.
+ * @param arg Argument for selection SQL.
+ * @param groupKey Column name used to find corresponding rows.
+ * @return Whether the methods adds or removed visible rows.
+ */
+ private boolean stopAddingDocuments(String selection, String arg, String groupKey) {
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ database.beginTransaction();
+ try {
+ // Get 1-to-1 mapping of invalidated document and pending document.
+ final String invalidatedIdQuery = createStateFilter(
+ ROW_STATE_INVALIDATED, Document.COLUMN_DOCUMENT_ID);
+ final String pendingIdQuery = createStateFilter(
+ ROW_STATE_PENDING, Document.COLUMN_DOCUMENT_ID);
+ // SQL should be like:
+ // SELECT group_concat(CASE WHEN raw_state = 1 THEN document_id ELSE NULL END),
+ // group_concat(CASE WHEN raw_state = 2 THEN document_id ELSE NULL END)
+ // WHERE device_id = ? AND parent_document_id IS NULL
+ // GROUP BY display_name
+ // HAVING count(CASE WHEN raw_state = 1 THEN document_id ELSE NULL END) = 1 AND
+ // count(CASE WHEN raw_state = 2 THEN document_id ELSE NULL END) = 1
+ final Cursor mergingCursor = database.query(
+ TABLE_DOCUMENTS,
+ new String[] {
+ "group_concat(" + invalidatedIdQuery + ")",
+ "group_concat(" + pendingIdQuery + ")"
+ },
+ selection,
+ strings(arg),
+ groupKey,
+ "count(" + invalidatedIdQuery + ") = 1 AND count(" + pendingIdQuery + ") = 1",
+ null);
+
+ final ContentValues values = new ContentValues();
+ while (mergingCursor.moveToNext()) {
+ final String invalidatedId = mergingCursor.getString(0);
+ final String pendingId = mergingCursor.getString(1);
+
+ // Obtain the new values including the latest object handle from mapping row.
+ getFirstRow(
+ TABLE_DOCUMENTS,
+ SELECTION_DOCUMENT_ID,
+ new String[] { pendingId },
+ values);
+ values.remove(Document.COLUMN_DOCUMENT_ID);
+ values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
+ database.update(
+ TABLE_DOCUMENTS,
+ values,
+ SELECTION_DOCUMENT_ID,
+ new String[] { invalidatedId });
+
+ getFirstRow(
+ TABLE_ROOT_EXTRA,
+ SELECTION_ROOT_ID,
+ new String[] { pendingId },
+ values);
+ if (values.size() > 0) {
+ values.remove(Root.COLUMN_ROOT_ID);
+ database.update(
+ TABLE_ROOT_EXTRA,
+ values,
+ SELECTION_ROOT_ID,
+ new String[] { invalidatedId });
+ }
+
+ // Delete 'pending' row.
+ mDatabase.deleteDocumentsAndRootsRecursively(
+ SELECTION_DOCUMENT_ID, new String[] { pendingId });
+ }
+ mergingCursor.close();
+
+ boolean changed = false;
+
+ // Delete all invalidated rows that cannot be mapped.
+ if (mDatabase.deleteDocumentsAndRootsRecursively(
+ COLUMN_ROW_STATE + " = ? AND " + selection,
+ strings(ROW_STATE_INVALIDATED, arg))) {
+ changed = true;
+ }
+
+ // The database cannot find old document ID for the pending rows.
+ // Turn the all pending rows into valid state, which means the rows become to be
+ // valid with new document ID.
+ values.clear();
+ values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
+ if (database.update(
+ TABLE_DOCUMENTS,
+ values,
+ COLUMN_ROW_STATE + " = ? AND " + selection,
+ strings(ROW_STATE_PENDING, arg)) != 0) {
+ changed = true;
+ }
+ database.setTransactionSuccessful();
+ return changed;
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ /**
+ * Obtains values of the first row for the query.
+ * @param values ContentValues that the values are stored to.
+ * @param table Target table.
+ * @param selection Query to select rows.
+ * @param args Argument for query.
+ */
+ private void getFirstRow(String table, String selection, String[] args, ContentValues values) {
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ values.clear();
+ final Cursor cursor = database.query(table, null, selection, args, null, null, null, "1");
+ if (cursor.getCount() == 0) {
+ return;
+ }
+ cursor.moveToNext();
+ DatabaseUtils.cursorRowToContentValues(cursor, values);
+ cursor.close();
+ }
+
+ /**
+ * Gets SQL expression that represents the given value or NULL depends on the row state.
+ * You must pass static constants to this methods otherwise you may be suffered from SQL
+ * injections.
+ * @param state Expected row state.
+ * @param a SQL value.
+ * @return Expression that represents a if the row state is expected one, and represents NULL
+ * otherwise.
+ */
+ private static String createStateFilter(int state, String a) {
+ return "CASE WHEN " + COLUMN_ROW_STATE + " = " + Integer.toString(state) +
+ " THEN " + a + " ELSE NULL END";
+ }
+
+ /**
+ * @param deviceId Device ID.
+ * @return Key for {@link #mMappingMode}.
+ */
+ private static String getRootDocumentsMappingStateKey(int deviceId) {
+ return "RootDocuments/" + deviceId;
+ }
+
+ /**
+ * @param parentDocumentId Document ID for the parent document.
+ * @return Key for {@link #mMappingMode}.
+ */
+ private static String getChildDocumentsMappingStateKey(String parentDocumentId) {
+ return "ChildDocuments/" + parentDocumentId;
+ }
+}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 3dc69cc..00fe7a7 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -22,6 +22,12 @@
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.media.MediaFile;
+import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
@@ -29,8 +35,9 @@
import com.android.internal.annotations.VisibleForTesting;
-import java.util.HashMap;
-import java.util.Map;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Objects;
/**
* Database for MTP objects.
@@ -46,13 +53,13 @@
* by comparing the directory structure and object name.
*
* To start putting documents into the database, the client needs to call
- * {@link #startAddingChildDocuments(String)} with the parent document ID. Also it needs to call
- * {@link #stopAddingChildDocuments(String)} after putting all child documents to the database.
- * (All explanations are same for root documents)
+ * {@link Mapper#startAddingChildDocuments(String)} with the parent document ID. Also it
+ * needs to call {@link Mapper#stopAddingChildDocuments(String)} after putting all child
+ * documents to the database. (All explanations are same for root documents)
*
- * database.startAddingChildDocuments();
- * database.putChildDocuments();
- * database.stopAddingChildDocuments();
+ * database.getMapper().startAddingChildDocuments();
+ * database.getMapper().putChildDocuments();
+ * database.getMapper().stopAddingChildDocuments();
*
* To update the existing documents, the client code can repeat to call the three methods again.
* The newly added rows update corresponding existing rows that have same MTP identifier like
@@ -66,170 +73,232 @@
* the database tries to find corresponding rows by using document's name instead of MTP identifier
* at the next update cycle.
*
- * TODO: Remove @VisibleForTesting annotation when we start to use this class.
* TODO: Improve performance by SQL optimization.
*/
-@VisibleForTesting
class MtpDatabase {
- private final MtpDatabaseInternal mDatabase;
+ private final SQLiteDatabase mDatabase;
+ private final Mapper mMapper;
- /**
- * Mapping mode for roots/documents where we start adding child documents.
- * Methods operate the state needs to be synchronized.
- */
- private final Map<String, Integer> mMappingMode = new HashMap<>();
-
- @VisibleForTesting
- MtpDatabase(Context context, int flags) {
- mDatabase = new MtpDatabaseInternal(context, flags);
+ SQLiteDatabase getSQLiteDatabase() {
+ return mDatabase;
}
- /**
- * Closes the database.
- */
- @VisibleForTesting
+ MtpDatabase(Context context, int flags) {
+ final OpenHelper helper = new OpenHelper(context, flags);
+ mDatabase = helper.getWritableDatabase();
+ mMapper = new Mapper(this);
+ }
+
void close() {
mDatabase.close();
}
/**
- * {@link MtpDatabaseInternal#queryRoots}
+ * Returns operations for mapping.
+ * @return Mapping operations.
*/
- Cursor queryRoots(String[] columnNames) {
- return mDatabase.queryRoots(columnNames);
+ Mapper getMapper() {
+ return mMapper;
}
/**
- * {@link MtpDatabaseInternal#queryRootDocuments}
+ * Queries roots information.
+ * @param columnNames Column names defined in {@link android.provider.DocumentsContract.Root}.
+ * @return Database cursor.
+ */
+ Cursor queryRoots(String[] columnNames) {
+ return mDatabase.query(
+ VIEW_ROOTS,
+ columnNames,
+ COLUMN_ROW_STATE + " IN (?, ?)",
+ strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
+ null,
+ null,
+ null);
+ }
+
+ /**
+ * Queries root documents information.
+ * @param columnNames Column names defined in
+ * {@link android.provider.DocumentsContract.Document}.
+ * @return Database cursor.
*/
@VisibleForTesting
Cursor queryRootDocuments(String[] columnNames) {
- return mDatabase.queryRootDocuments(columnNames);
+ return mDatabase.query(
+ TABLE_DOCUMENTS,
+ columnNames,
+ COLUMN_ROW_STATE + " IN (?, ?)",
+ strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
+ null,
+ null,
+ null);
}
/**
- * {@link MtpDatabaseInternal#queryChildDocuments}
+ * Queries documents information.
+ * @param columnNames Column names defined in
+ * {@link android.provider.DocumentsContract.Document}.
+ * @return Database cursor.
*/
- @VisibleForTesting
Cursor queryChildDocuments(String[] columnNames, String parentDocumentId) {
- return queryChildDocuments(columnNames, parentDocumentId, false);
- }
-
- @VisibleForTesting
- Cursor queryChildDocuments(String[] columnNames, String parentDocumentId, boolean useOldId) {
- final String[] newColumnNames = new String[columnNames.length];
-
- // TODO: Temporary replace document ID with old format.
- for (int i = 0; i < columnNames.length; i++) {
- if (useOldId && DocumentsContract.Document.COLUMN_DOCUMENT_ID.equals(columnNames[i])) {
- newColumnNames[i] = COLUMN_DEVICE_ID + " || '_' || " + COLUMN_STORAGE_ID +
- " || '_' || IFNULL(" + COLUMN_OBJECT_HANDLE + ",0) AS " +
- DocumentsContract.Document.COLUMN_DOCUMENT_ID;
- } else {
- newColumnNames[i] = columnNames[i];
- }
- }
-
- return mDatabase.queryChildDocuments(newColumnNames, parentDocumentId);
- }
-
- Identifier createIdentifier(String parentDocumentId) {
- return mDatabase.createIdentifier(parentDocumentId);
+ return mDatabase.query(
+ TABLE_DOCUMENTS,
+ columnNames,
+ COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_PARENT_DOCUMENT_ID + " = ?",
+ strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, parentDocumentId),
+ null,
+ null,
+ null);
}
/**
- * {@link MtpDatabaseInternal#removeDeviceRows}
+ * Queries a single document.
+ * @param documentId
+ * @param projection
+ * @return Database cursor.
*/
- void removeDeviceRows(int deviceId) {
- mDatabase.removeDeviceRows(deviceId);
+ public Cursor queryDocument(String documentId, String[] projection) {
+ return mDatabase.query(
+ TABLE_DOCUMENTS,
+ projection,
+ SELECTION_DOCUMENT_ID,
+ strings(documentId),
+ null,
+ null,
+ null,
+ "1");
}
/**
- * Invokes {@link MtpDatabaseInternal#startAddingDocuments} for root documents.
+ * Remove all rows belong to a device.
* @param deviceId Device ID.
*/
- synchronized void startAddingRootDocuments(int deviceId) {
- final String mappingStateKey = getRootDocumentsMappingStateKey(deviceId);
- if (mMappingMode.containsKey(mappingStateKey)) {
- throw new Error("Mapping for the root has already started.");
- }
- mMappingMode.put(
- mappingStateKey,
- mDatabase.startAddingDocuments(
- SELECTION_ROOT_DOCUMENTS, Integer.toString(deviceId)));
+ void removeDeviceRows(int deviceId) {
+ // Call non-recursive version because it anyway deletes all rows in the devices.
+ deleteDocumentsAndRoots(COLUMN_DEVICE_ID + "=?", strings(deviceId));
}
/**
- * Invokes {@link MtpDatabaseInternal#startAddingDocuments} for child of specific documents.
- * @param parentDocumentId Document ID for parent document.
+ * Obtains parent document ID.
+ * @param documentId
+ * @return parent document ID.
+ * @throws FileNotFoundException
*/
- @VisibleForTesting
- synchronized void startAddingChildDocuments(String parentDocumentId) {
- final String mappingStateKey = getChildDocumentsMappingStateKey(parentDocumentId);
- if (mMappingMode.containsKey(mappingStateKey)) {
- throw new Error("Mapping for the root has already started.");
+ String getParentId(String documentId) throws FileNotFoundException {
+ final Cursor cursor = mDatabase.query(
+ TABLE_DOCUMENTS,
+ strings(COLUMN_PARENT_DOCUMENT_ID),
+ SELECTION_DOCUMENT_ID,
+ strings(documentId),
+ null,
+ null,
+ null,
+ "1");
+ try {
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
+ } else {
+ throw new FileNotFoundException("Cannot find a row having ID=" + documentId);
+ }
+ } finally {
+ cursor.close();
}
- mMappingMode.put(
- mappingStateKey,
- mDatabase.startAddingDocuments(SELECTION_CHILD_DOCUMENTS, parentDocumentId));
}
/**
- * Puts root information to database.
- * @param deviceId Device ID
- * @param resources Resources required to localize root name.
- * @param roots List of root information.
- * @return If roots are added or removed from the database.
+ * Adds new document under the parent.
+ * The method does not affect invalidated and pending documents because we know the document is
+ * newly added and never mapped with existing ones.
+ * @param parentDocumentId
+ * @param info
+ * @return Document ID of added document.
*/
- synchronized boolean putRootDocuments(int deviceId, Resources resources, MtpRoot[] roots) {
+ String putNewDocument(int deviceId, String parentDocumentId, MtpObjectInfo info) {
+ final ContentValues values = new ContentValues();
+ getChildDocumentValues(values, deviceId, parentDocumentId, info);
mDatabase.beginTransaction();
try {
- final boolean heuristic;
- final String mapColumn;
- switch (mMappingMode.get(getRootDocumentsMappingStateKey(deviceId))) {
- case MAP_BY_MTP_IDENTIFIER:
- heuristic = false;
- mapColumn = COLUMN_STORAGE_ID;
- break;
- case MAP_BY_NAME:
- heuristic = true;
- mapColumn = Document.COLUMN_DISPLAY_NAME;
- break;
- default:
- throw new Error("Unexpected map mode.");
+ final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
+ mDatabase.setTransactionSuccessful();
+ return Long.toString(id);
+ } finally {
+ mDatabase.endTransaction();
+ }
+ }
+
+ /**
+ * Deletes document and its children.
+ * @param documentId
+ */
+ void deleteDocument(String documentId) {
+ deleteDocumentsAndRootsRecursively(SELECTION_DOCUMENT_ID, strings(documentId));
+ }
+
+ /**
+ * Gets identifier from document ID.
+ * @param documentId Document ID.
+ * @return Identifier.
+ * @throws FileNotFoundException
+ */
+ Identifier createIdentifier(String documentId) throws FileNotFoundException {
+ // Currently documentId is old format.
+ final Cursor cursor = mDatabase.query(
+ TABLE_DOCUMENTS,
+ strings(COLUMN_DEVICE_ID, COLUMN_STORAGE_ID, COLUMN_OBJECT_HANDLE),
+ SELECTION_DOCUMENT_ID,
+ strings(documentId),
+ null,
+ null,
+ null,
+ "1");
+ try {
+ if (cursor.getCount() == 0) {
+ throw new FileNotFoundException("ID is not found.");
+ } else {
+ cursor.moveToNext();
+ return new Identifier(
+ cursor.getInt(0),
+ cursor.getInt(1),
+ cursor.isNull(2) ? Identifier.DUMMY_HANDLE_FOR_ROOT : cursor.getInt(2),
+ documentId);
}
- final ContentValues[] valuesList = new ContentValues[roots.length];
- for (int i = 0; i < roots.length; i++) {
- if (roots[i].mDeviceId != deviceId) {
- throw new IllegalArgumentException();
+ } finally {
+ cursor.close();
+ }
+ }
+
+ /**
+ * Deletes a document, and its root information if the document is a root document.
+ * @param selection Query to select documents.
+ * @param args Arguments for selection.
+ * @return Whether the method deletes rows.
+ */
+ boolean deleteDocumentsAndRootsRecursively(String selection, String[] args) {
+ mDatabase.beginTransaction();
+ try {
+ boolean changed = false;
+ final Cursor cursor = mDatabase.query(
+ TABLE_DOCUMENTS,
+ strings(Document.COLUMN_DOCUMENT_ID),
+ selection,
+ args,
+ null,
+ null,
+ null);
+ try {
+ while (cursor.moveToNext()) {
+ if (deleteDocumentsAndRootsRecursively(
+ COLUMN_PARENT_DOCUMENT_ID + "=?",
+ strings(cursor.getString(0)))) {
+ changed = true;
+ }
}
- valuesList[i] = new ContentValues();
- getRootDocumentValues(valuesList[i], resources, roots[i]);
+ } finally {
+ cursor.close();
}
- final boolean changed = mDatabase.putDocuments(
- valuesList,
- SELECTION_ROOT_DOCUMENTS,
- Integer.toString(deviceId),
- heuristic,
- mapColumn);
- final ContentValues values = new ContentValues();
- int i = 0;
- for (final MtpRoot root : roots) {
- // Use the same value for the root ID and the corresponding document ID.
- final String documentId = valuesList[i++].getAsString(Document.COLUMN_DOCUMENT_ID);
- // If it fails to insert/update documents, the document ID will be set with -1.
- // In this case we don't insert/update root extra information neither.
- if (documentId == null) {
- continue;
- }
- values.put(Root.COLUMN_ROOT_ID, documentId);
- values.put(
- Root.COLUMN_FLAGS,
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
- values.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
- values.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
- values.put(Root.COLUMN_MIME_TYPES, "");
- mDatabase.putRootExtra(values);
+ if (deleteDocumentsAndRoots(selection, args)) {
+ changed = true;
}
mDatabase.setTransactionSuccessful();
return changed;
@@ -239,94 +308,80 @@
}
/**
- * Puts document information to database.
- * @param deviceId Device ID
- * @param parentId Parent document ID.
- * @param documents List of document information.
+ * Returns the set of device ID stored in the database.
*/
- @VisibleForTesting
- synchronized void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents) {
- final boolean heuristic;
- final String mapColumn;
- switch (mMappingMode.get(getChildDocumentsMappingStateKey(parentId))) {
- case MAP_BY_MTP_IDENTIFIER:
- heuristic = false;
- mapColumn = COLUMN_OBJECT_HANDLE;
- break;
- case MAP_BY_NAME:
- heuristic = true;
- mapColumn = Document.COLUMN_DISPLAY_NAME;
- break;
- default:
- throw new Error("Unexpected map mode.");
- }
- final ContentValues[] valuesList = new ContentValues[documents.length];
- for (int i = 0; i < documents.length; i++) {
- valuesList[i] = new ContentValues();
- getChildDocumentValues(valuesList[i], deviceId, parentId, documents[i]);
- }
- mDatabase.putDocuments(
- valuesList, SELECTION_CHILD_DOCUMENTS, parentId, heuristic, mapColumn);
- }
-
- /**
- * Clears mapping between MTP identifier and document/root ID.
- */
- @VisibleForTesting
- synchronized void clearMapping() {
- mDatabase.clearMapping();
- mMappingMode.clear();
- }
-
- /**
- * Stops adding root documents.
- * @param deviceId Device ID.
- * @return True if new rows are added/removed.
- */
- synchronized boolean stopAddingRootDocuments(int deviceId) {
- final String mappingModeKey = getRootDocumentsMappingStateKey(deviceId);
- switch (mMappingMode.get(mappingModeKey)) {
- case MAP_BY_MTP_IDENTIFIER:
- mMappingMode.remove(mappingModeKey);
- return mDatabase.stopAddingDocuments(
- SELECTION_ROOT_DOCUMENTS,
- Integer.toString(deviceId),
- COLUMN_STORAGE_ID);
- case MAP_BY_NAME:
- mMappingMode.remove(mappingModeKey);
- return mDatabase.stopAddingDocuments(
- SELECTION_ROOT_DOCUMENTS,
- Integer.toString(deviceId),
- Document.COLUMN_DISPLAY_NAME);
- default:
- throw new Error("Unexpected mapping state.");
+ int[] getDeviceIds() {
+ final Cursor cursor = mDatabase.query(
+ true,
+ TABLE_DOCUMENTS,
+ strings(COLUMN_DEVICE_ID),
+ null,
+ null,
+ null,
+ null,
+ null,
+ null);
+ try {
+ final int[] ids = new int[cursor.getCount()];
+ for (int i = 0; i < ids.length; i++) {
+ cursor.moveToNext();
+ ids[i] = cursor.getInt(0);
+ }
+ return ids;
+ } finally {
+ cursor.close();
}
}
- /**
- * Stops adding documents under the parent.
- * @param parentId Document ID of the parent.
- */
- @VisibleForTesting
- synchronized void stopAddingChildDocuments(String parentId) {
- final String mappingModeKey = getChildDocumentsMappingStateKey(parentId);
- switch (mMappingMode.get(mappingModeKey)) {
- case MAP_BY_MTP_IDENTIFIER:
- mDatabase.stopAddingDocuments(
- SELECTION_CHILD_DOCUMENTS,
- parentId,
- COLUMN_OBJECT_HANDLE);
- break;
- case MAP_BY_NAME:
- mDatabase.stopAddingDocuments(
- SELECTION_CHILD_DOCUMENTS,
- parentId,
- Document.COLUMN_DISPLAY_NAME);
- break;
- default:
- throw new Error("Unexpected mapping state.");
+ private boolean deleteDocumentsAndRoots(String selection, String[] args) {
+ mDatabase.beginTransaction();
+ try {
+ int deleted = 0;
+ deleted += mDatabase.delete(
+ TABLE_ROOT_EXTRA,
+ Root.COLUMN_ROOT_ID + " IN (" + SQLiteQueryBuilder.buildQueryString(
+ false,
+ TABLE_DOCUMENTS,
+ new String[] { Document.COLUMN_DOCUMENT_ID },
+ selection,
+ null,
+ null,
+ null,
+ null) + ")",
+ args);
+ deleted += mDatabase.delete(TABLE_DOCUMENTS, selection, args);
+ mDatabase.setTransactionSuccessful();
+ // TODO Remove mappingState.
+ return deleted != 0;
+ } finally {
+ mDatabase.endTransaction();
}
- mMappingMode.remove(mappingModeKey);
+ }
+
+ private static class OpenHelper extends SQLiteOpenHelper {
+ public OpenHelper(Context context, int flags) {
+ super(context,
+ flags == FLAG_DATABASE_IN_MEMORY ? null : DATABASE_NAME,
+ null,
+ DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(QUERY_CREATE_DOCUMENTS);
+ db.execSQL(QUERY_CREATE_ROOT_EXTRA);
+ db.execSQL(QUERY_CREATE_VIEW_ROOTS);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @VisibleForTesting
+ static void deleteDatabase(Context context) {
+ context.deleteDatabase(DATABASE_NAME);
}
/**
@@ -335,8 +390,7 @@
* @param resources Resources used to get localized root name.
* @param root Root to be converted {@link ContentValues}.
*/
- private static void getRootDocumentValues(
- ContentValues values, Resources resources, MtpRoot root) {
+ static void getRootDocumentValues(ContentValues values, Resources resources, MtpRoot root) {
values.clear();
values.put(COLUMN_DEVICE_ID, root.mDeviceId);
values.put(COLUMN_STORAGE_ID, root.mStorageId);
@@ -360,10 +414,12 @@
* @param parentId Parent document ID of the object.
* @param info MTP object info.
*/
- private void getChildDocumentValues(
+ static void getChildDocumentValues(
ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
values.clear();
- final String mimeType = CursorHelper.formatTypeToMimeType(info.getFormat());
+ final String mimeType = info.getFormat() == MtpConstants.FORMAT_ASSOCIATION ?
+ DocumentsContract.Document.MIME_TYPE_DIR :
+ MediaFile.getMimeTypeForFormatCode(info.getFormat());
int flag = 0;
if (info.getProtectionStatus() == 0) {
flag |= Document.FLAG_SUPPORTS_DELETE |
@@ -391,19 +447,11 @@
values.put(Document.COLUMN_SIZE, info.getCompressedSize());
}
- /**
- * @param deviceId Device ID.
- * @return Key for {@link #mMappingMode}.
- */
- private static String getRootDocumentsMappingStateKey(int deviceId) {
- return "RootDocuments/" + deviceId;
- }
-
- /**
- * @param parentDocumentId Document ID for the parent document.
- * @return Key for {@link #mMappingMode}.
- */
- private static String getChildDocumentsMappingStateKey(String parentDocumentId) {
- return "ChildDocuments/" + parentDocumentId;
+ static String[] strings(Object... args) {
+ final String[] results = new String[args.length];
+ for (int i = 0; i < args.length; i++) {
+ results[i] = Objects.toString(args[i]);
+ }
+ return results;
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
index 97c1d29..0ead2d5 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
@@ -24,7 +24,7 @@
*/
class MtpDatabaseConstants {
static final int DATABASE_VERSION = 1;
- static final String DATABASE_NAME = null;
+ static final String DATABASE_NAME = "database";
static final int FLAG_DATABASE_IN_MEMORY = 1;
static final int FLAG_DATABASE_IN_FILE = 0;
@@ -129,11 +129,7 @@
Root.COLUMN_TITLE + "," +
TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " +
Root.COLUMN_SUMMARY + "," +
- // Temporary replace COLUMN_DOCUMENT_ID with old format.
TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID + " AS " +
- Root.COLUMN_DOCUMENT_ID + "_," +
- TABLE_DOCUMENTS + "." + COLUMN_DEVICE_ID + "|| '_' ||" +
- TABLE_DOCUMENTS + "." + COLUMN_STORAGE_ID + "||'_0' AS " +
Root.COLUMN_DOCUMENT_ID + "," +
TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES + "," +
TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES + "," +
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java
deleted file mode 100644
index 9c5d6b6..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mtp;
-
-import static com.android.mtp.MtpDatabaseConstants.*;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-
-import java.util.Objects;
-
-/**
- * Class that provides operations processing SQLite database directly.
- */
-class MtpDatabaseInternal {
- private static class OpenHelper extends SQLiteOpenHelper {
- public OpenHelper(Context context, int flags) {
- super(context,
- flags == FLAG_DATABASE_IN_MEMORY ? null : DATABASE_NAME,
- null,
- DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(QUERY_CREATE_DOCUMENTS);
- db.execSQL(QUERY_CREATE_ROOT_EXTRA);
- db.execSQL(QUERY_CREATE_VIEW_ROOTS);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- throw new UnsupportedOperationException();
- }
- }
-
- private final SQLiteDatabase mDatabase;
-
- MtpDatabaseInternal(Context context, int flags) {
- final OpenHelper helper = new OpenHelper(context, flags);
- mDatabase = helper.getWritableDatabase();
- }
-
- void close() {
- mDatabase.close();
- }
-
- /**
- * Queries roots information.
- * @param columnNames Column names defined in {@link android.provider.DocumentsContract.Root}.
- * @return Database cursor.
- */
- Cursor queryRoots(String[] columnNames) {
- return mDatabase.query(
- VIEW_ROOTS,
- columnNames,
- COLUMN_ROW_STATE + " IN (?, ?)",
- strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
- null,
- null,
- null);
- }
-
- /**
- * Queries root documents information.
- * @param columnNames Column names defined in
- * {@link android.provider.DocumentsContract.Document}.
- * @return Database cursor.
- */
- Cursor queryRootDocuments(String[] columnNames) {
- return mDatabase.query(
- TABLE_DOCUMENTS,
- columnNames,
- COLUMN_ROW_STATE + " IN (?, ?)",
- strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
- null,
- null,
- null);
- }
-
- /**
- * Queries documents information.
- * @param columnNames Column names defined in
- * {@link android.provider.DocumentsContract.Document}.
- * @return Database cursor.
- */
- Cursor queryChildDocuments(String[] columnNames, String parentDocumentId) {
- return mDatabase.query(
- TABLE_DOCUMENTS,
- columnNames,
- COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_PARENT_DOCUMENT_ID + " = ?",
- strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, parentDocumentId),
- null,
- null,
- null);
- }
-
- /**
- * Remove all rows belong to a device.
- * @param deviceId Device ID.
- */
- void removeDeviceRows(int deviceId) {
- deleteDocumentsAndRoots(COLUMN_DEVICE_ID + "=?", strings(deviceId));
- }
-
- /**
- * Gets identifier from document ID.
- * @param documentId Document ID.
- * @return Identifier.
- */
- Identifier createIdentifier(String documentId) {
- // Currently documentId is old format.
- final Identifier oldIdentifier = Identifier.createFromDocumentId(documentId);
- final String selection;
- final String[] args;
- if (oldIdentifier.mObjectHandle == CursorHelper.DUMMY_HANDLE_FOR_ROOT) {
- selection = COLUMN_DEVICE_ID + "= ? AND " +
- COLUMN_ROW_STATE + " IN (?, ?) AND " +
- COLUMN_STORAGE_ID + "= ? AND " +
- COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
- args = strings(
- oldIdentifier.mDeviceId,
- ROW_STATE_VALID,
- ROW_STATE_INVALIDATED,
- oldIdentifier.mStorageId);
- } else {
- selection = COLUMN_DEVICE_ID + "= ? AND " +
- COLUMN_ROW_STATE + " IN (?, ?) AND " +
- COLUMN_STORAGE_ID + "= ? AND " +
- COLUMN_OBJECT_HANDLE + " = ?";
- args = strings(
- oldIdentifier.mDeviceId,
- ROW_STATE_VALID,
- ROW_STATE_INVALIDATED,
- oldIdentifier.mStorageId,
- oldIdentifier.mObjectHandle);
- }
-
- final Cursor cursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- selection,
- args,
- null,
- null,
- null,
- "1");
- try {
- if (cursor.getCount() == 0) {
- return oldIdentifier;
- } else {
- cursor.moveToNext();
- return new Identifier(
- oldIdentifier.mDeviceId,
- oldIdentifier.mStorageId,
- oldIdentifier.mObjectHandle,
- cursor.getString(0));
- }
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Starts adding new documents.
- * The methods decides mapping mode depends on if all documents under the given parent have MTP
- * identifier or not. If all the documents have MTP identifier, it uses the identifier to find
- * a corresponding existing row. Otherwise it does heuristic.
- *
- * @param selection Query matches valid documents.
- * @param arg Argument for selection.
- * @return Mapping mode.
- */
- int startAddingDocuments(String selection, String arg) {
- mDatabase.beginTransaction();
- try {
- // Delete all pending rows.
- deleteDocumentsAndRoots(
- selection + " AND " + COLUMN_ROW_STATE + "=?", strings(arg, ROW_STATE_PENDING));
-
- // Set all documents as invalidated.
- final ContentValues values = new ContentValues();
- values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
- mDatabase.update(TABLE_DOCUMENTS, values, selection, new String[] { arg });
-
- // If we have rows that does not have MTP identifier, do heuristic mapping by name.
- final boolean useNameForResolving = DatabaseUtils.queryNumEntries(
- mDatabase,
- TABLE_DOCUMENTS,
- selection + " AND " + COLUMN_STORAGE_ID + " IS NULL",
- new String[] { arg }) > 0;
- mDatabase.setTransactionSuccessful();
- return useNameForResolving ? MAP_BY_NAME : MAP_BY_MTP_IDENTIFIER;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Puts the documents into the database.
- * If the mapping mode is not heuristic, it just adds the rows to the database or updates the
- * existing rows with the new values. If the mapping mode is heuristic, it adds some new rows as
- * 'pending' state when that rows may be corresponding to existing 'invalidated' rows. Then
- * {@link #stopAddingDocuments(String, String, String)} turns the pending rows into 'valid'
- * rows. If the methods adds rows to database, it updates valueList with correct document ID.
- *
- * @param valuesList Values for documents to be stored in the database.
- * @param selection SQL where closure to select rows that shares the same parent.
- * @param arg Argument for selection SQL.
- * @param heuristic Whether the mapping mode is heuristic.
- * @return Whether the method adds new rows.
- */
- boolean putDocuments(
- ContentValues[] valuesList,
- String selection,
- String arg,
- boolean heuristic,
- String mappingKey) {
- boolean added = false;
- mDatabase.beginTransaction();
- try {
- for (final ContentValues values : valuesList) {
- final Cursor candidateCursor = mDatabase.query(
- TABLE_DOCUMENTS,
- strings(Document.COLUMN_DOCUMENT_ID),
- selection + " AND " +
- COLUMN_ROW_STATE + "=? AND " +
- mappingKey + "=?",
- strings(arg, ROW_STATE_INVALIDATED, values.getAsString(mappingKey)),
- null,
- null,
- null,
- "1");
- try {
- final long rowId;
- if (candidateCursor.getCount() == 0) {
- rowId = mDatabase.insert(TABLE_DOCUMENTS, null, values);
- if (rowId == -1) {
- throw new SQLiteException("Failed to put a document into database.");
- }
- added = true;
- } else if (!heuristic) {
- candidateCursor.moveToNext();
- final String documentId = candidateCursor.getString(0);
- rowId = mDatabase.update(
- TABLE_DOCUMENTS,
- values,
- SELECTION_DOCUMENT_ID,
- strings(documentId));
- } else {
- values.put(COLUMN_ROW_STATE, ROW_STATE_PENDING);
- rowId = mDatabase.insert(TABLE_DOCUMENTS, null, values);
- }
- // Document ID is a primary integer key of the table. So the returned row
- // IDs should be same with the document ID.
- values.put(Document.COLUMN_DOCUMENT_ID, rowId);
- } finally {
- candidateCursor.close();
- }
- }
-
- mDatabase.setTransactionSuccessful();
- return added;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Puts extra information for root documents.
- * @param values Values containing extra information.
- */
- void putRootExtra(ContentValues values) {
- mDatabase.replace(TABLE_ROOT_EXTRA, null, values);
- }
-
- /**
- * Maps 'pending' document and 'invalidated' document that shares the same column of groupKey.
- * If the database does not find corresponding 'invalidated' document, it just removes
- * 'invalidated' document from the database.
- * @param selection Query to select rows for resolving.
- * @param arg Argument for selection SQL.
- * @param groupKey Column name used to find corresponding rows.
- * @return Whether the methods adds or removed visible rows.
- */
- boolean stopAddingDocuments(String selection, String arg, String groupKey) {
- mDatabase.beginTransaction();
- try {
- // Get 1-to-1 mapping of invalidated document and pending document.
- final String invalidatedIdQuery = createStateFilter(
- ROW_STATE_INVALIDATED, Document.COLUMN_DOCUMENT_ID);
- final String pendingIdQuery = createStateFilter(
- ROW_STATE_PENDING, Document.COLUMN_DOCUMENT_ID);
- // SQL should be like:
- // SELECT group_concat(CASE WHEN raw_state = 1 THEN document_id ELSE NULL END),
- // group_concat(CASE WHEN raw_state = 2 THEN document_id ELSE NULL END)
- // WHERE device_id = ? AND parent_document_id IS NULL
- // GROUP BY display_name
- // HAVING count(CASE WHEN raw_state = 1 THEN document_id ELSE NULL END) = 1 AND
- // count(CASE WHEN raw_state = 2 THEN document_id ELSE NULL END) = 1
- final Cursor mergingCursor = mDatabase.query(
- TABLE_DOCUMENTS,
- new String[] {
- "group_concat(" + invalidatedIdQuery + ")",
- "group_concat(" + pendingIdQuery + ")"
- },
- selection,
- strings(arg),
- groupKey,
- "count(" + invalidatedIdQuery + ") = 1 AND count(" + pendingIdQuery + ") = 1",
- null);
-
- final ContentValues values = new ContentValues();
- while (mergingCursor.moveToNext()) {
- final String invalidatedId = mergingCursor.getString(0);
- final String pendingId = mergingCursor.getString(1);
-
- // Obtain the new values including the latest object handle from mapping row.
- getFirstRow(
- TABLE_DOCUMENTS,
- SELECTION_DOCUMENT_ID,
- new String[] { pendingId },
- values);
- values.remove(Document.COLUMN_DOCUMENT_ID);
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- mDatabase.update(
- TABLE_DOCUMENTS,
- values,
- SELECTION_DOCUMENT_ID,
- new String[] { invalidatedId });
-
- getFirstRow(
- TABLE_ROOT_EXTRA,
- SELECTION_ROOT_ID,
- new String[] { pendingId },
- values);
- if (values.size() > 0) {
- values.remove(Root.COLUMN_ROOT_ID);
- mDatabase.update(
- TABLE_ROOT_EXTRA,
- values,
- SELECTION_ROOT_ID,
- new String[] { invalidatedId });
- }
-
- // Delete 'pending' row.
- deleteDocumentsAndRoots(SELECTION_DOCUMENT_ID, new String[] { pendingId });
- }
- mergingCursor.close();
-
- boolean changed = false;
-
- // Delete all invalidated rows that cannot be mapped.
- if (deleteDocumentsAndRoots(
- COLUMN_ROW_STATE + " = ? AND " + selection,
- strings(ROW_STATE_INVALIDATED, arg))) {
- changed = true;
- }
-
- // The database cannot find old document ID for the pending rows.
- // Turn the all pending rows into valid state, which means the rows become to be
- // valid with new document ID.
- values.clear();
- values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
- if (mDatabase.update(
- TABLE_DOCUMENTS,
- values,
- COLUMN_ROW_STATE + " = ? AND " + selection,
- strings(ROW_STATE_PENDING, arg)) != 0) {
- changed = true;
- }
- mDatabase.setTransactionSuccessful();
- return changed;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Clears MTP related identifier.
- * It clears MTP's object handle and storage ID that are not stable over MTP sessions and mark
- * the all documents as 'invalidated'. It also remove 'pending' rows as adding is cancelled
- * now.
- */
- void clearMapping() {
- mDatabase.beginTransaction();
- try {
- deleteDocumentsAndRoots(COLUMN_ROW_STATE + " = ?", strings(ROW_STATE_PENDING));
- final ContentValues values = new ContentValues();
- values.putNull(COLUMN_OBJECT_HANDLE);
- values.putNull(COLUMN_STORAGE_ID);
- values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
- mDatabase.update(TABLE_DOCUMENTS, values, null, null);
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * {@link android.database.sqlite.SQLiteDatabase#beginTransaction()}
- */
- void beginTransaction() {
- mDatabase.beginTransaction();
- }
-
- /**
- * {@link android.database.sqlite.SQLiteDatabase#setTransactionSuccessful()}
- */
- void setTransactionSuccessful() {
- mDatabase.setTransactionSuccessful();
- }
-
- /**
- * {@link android.database.sqlite.SQLiteDatabase#endTransaction()}
- */
- void endTransaction() {
- mDatabase.endTransaction();
- }
-
- /**
- * Deletes a document, and its root information if the document is a root document.
- * @param selection Query to select documents.
- * @param args Arguments for selection.
- * @return Whether the method deletes rows.
- */
- private boolean deleteDocumentsAndRoots(String selection, String[] args) {
- mDatabase.beginTransaction();
- try {
- int deleted = 0;
- deleted += mDatabase.delete(
- TABLE_ROOT_EXTRA,
- Root.COLUMN_ROOT_ID + " IN (" + SQLiteQueryBuilder.buildQueryString(
- false,
- TABLE_DOCUMENTS,
- new String[] { Document.COLUMN_DOCUMENT_ID },
- selection,
- null,
- null,
- null,
- null) + ")",
- args);
- deleted += mDatabase.delete(TABLE_DOCUMENTS, selection, args);
- mDatabase.setTransactionSuccessful();
- return deleted != 0;
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- /**
- * Obtains values of the first row for the query.
- * @param values ContentValues that the values are stored to.
- * @param table Target table.
- * @param selection Query to select rows.
- * @param args Argument for query.
- */
- private void getFirstRow(String table, String selection, String[] args, ContentValues values) {
- values.clear();
- final Cursor cursor = mDatabase.query(table, null, selection, args, null, null, null, "1");
- if (cursor.getCount() == 0) {
- return;
- }
- cursor.moveToNext();
- DatabaseUtils.cursorRowToContentValues(cursor, values);
- cursor.close();
- }
-
- /**
- * Gets SQL expression that represents the given value or NULL depends on the row state.
- * @param state Expected row state.
- * @param a SQL value.
- * @return Expression that represents a if the row state is expected one, and represents NULL
- * otherwise.
- */
- private static String createStateFilter(int state, String a) {
- return "CASE WHEN " + COLUMN_ROW_STATE + " = " + Integer.toString(state) +
- " THEN " + a + " ELSE NULL END";
- }
-
- /**
- * Converts values into string array.
- * @param args Values converted into string array.
- * @return String array.
- */
- private static String[] strings(Object... args) {
- final String[] results = new String[args.length];
- for (int i = 0; i < args.length; i++) {
- results[i] = Objects.toString(args[i]);
- }
- return results;
- }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 7c0676f..9511e15 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -20,8 +20,9 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.Cursor;
-import android.database.MatrixCursor;
import android.graphics.Point;
+import android.media.MediaFile;
+import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
@@ -56,11 +57,13 @@
Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
};
+ private final Object mDeviceListLock = new Object();
+
private static MtpDocumentsProvider sSingleton;
private MtpManager mMtpManager;
private ContentResolver mResolver;
- @GuardedBy("mDeviceToolkits")
+ @GuardedBy("mDeviceListLock")
private Map<Integer, DeviceToolkit> mDeviceToolkits;
private RootScanner mRootScanner;
private Resources mResources;
@@ -82,6 +85,7 @@
mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
mRootScanner = new RootScanner(mResolver, mResources, mMtpManager, mDatabase);
+ resume();
return true;
}
@@ -97,6 +101,7 @@
mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
mDatabase = database;
mRootScanner = new RootScanner(mResolver, mResources, mMtpManager, mDatabase);
+ resume();
}
@Override
@@ -116,39 +121,7 @@
if (projection == null) {
projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
}
- final Identifier identifier = Identifier.createFromDocumentId(documentId);
-
- if (identifier.mObjectHandle != CursorHelper.DUMMY_HANDLE_FOR_ROOT) {
- MtpObjectInfo objectInfo;
- try {
- objectInfo = mMtpManager.getObjectInfo(
- identifier.mDeviceId, identifier.mObjectHandle);
- } catch (IOException e) {
- throw new FileNotFoundException(e.getMessage());
- }
- final MatrixCursor cursor = new MatrixCursor(projection);
- CursorHelper.addToCursor(
- objectInfo,
- new Identifier(identifier.mDeviceId, identifier.mStorageId),
- cursor.newRow());
- return cursor;
- } else {
- MtpRoot[] roots;
- try {
- roots = mMtpManager.getRoots(identifier.mDeviceId);
- } catch (IOException e) {
- throw new FileNotFoundException(e.getMessage());
- }
- for (final MtpRoot root : roots) {
- if (identifier.mStorageId != root.mStorageId)
- continue;
- final MatrixCursor cursor = new MatrixCursor(projection);
- CursorHelper.addToCursor(mResources, root, cursor.newRow());
- return cursor;
- }
- }
-
- throw new FileNotFoundException();
+ return mDatabase.queryDocument(documentId, projection);
}
@Override
@@ -170,7 +143,7 @@
public ParcelFileDescriptor openDocument(
String documentId, String mode, CancellationSignal signal)
throws FileNotFoundException {
- final Identifier identifier = Identifier.createFromDocumentId(documentId);
+ final Identifier identifier = mDatabase.createIdentifier(documentId);
try {
switch (mode) {
case "r":
@@ -195,7 +168,7 @@
String documentId,
Point sizeHint,
CancellationSignal signal) throws FileNotFoundException {
- final Identifier identifier = Identifier.createFromDocumentId(documentId);
+ final Identifier identifier = mDatabase.createIdentifier(documentId);
try {
return new AssetFileDescriptor(
getPipeManager(identifier).readThumbnail(mMtpManager, identifier),
@@ -209,22 +182,24 @@
@Override
public void deleteDocument(String documentId) throws FileNotFoundException {
try {
- final Identifier identifier = Identifier.createFromDocumentId(documentId);
- final int parentHandle =
- mMtpManager.getParent(identifier.mDeviceId, identifier.mObjectHandle);
+ final Identifier identifier = mDatabase.createIdentifier(documentId);
+ final Identifier parentIdentifier =
+ mDatabase.createIdentifier(mDatabase.getParentId(documentId));
mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
- final Identifier parentIdentifier = new Identifier(
- identifier.mDeviceId, identifier.mStorageId, parentHandle);
+ mDatabase.deleteDocument(documentId);
getDocumentLoader(parentIdentifier).clearTask(parentIdentifier);
- notifyChildDocumentsChange(parentIdentifier.toDocumentId());
+ notifyChildDocumentsChange(parentIdentifier.mDocumentId);
} catch (IOException error) {
+ for (final StackTraceElement element : error.getStackTrace()) {
+ Log.e("hirono", element.toString());
+ }
throw new FileNotFoundException(error.getMessage());
}
}
@Override
public void onTrimMemory(int level) {
- synchronized (mDeviceToolkits) {
+ synchronized (mDeviceListLock) {
for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
toolkit.mDocumentLoader.clearCompletedTasks();
}
@@ -235,19 +210,23 @@
public String createDocument(String parentDocumentId, String mimeType, String displayName)
throws FileNotFoundException {
try {
- final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId);
+ final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
pipe[0].close(); // 0 bytes for a new document.
- final int objectHandle = mMtpManager.createDocument(
- parentId.mDeviceId,
- new MtpObjectInfo.Builder()
- .setStorageId(parentId.mStorageId)
- .setParent(parentId.mObjectHandle)
- .setFormat(CursorHelper.mimeTypeToFormatType(displayName, mimeType))
- .setName(displayName)
- .build(), pipe[1]);
- final String documentId = new Identifier(parentId.mDeviceId, parentId.mStorageId,
- objectHandle).toDocumentId();
+ final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
+ MtpConstants.FORMAT_ASSOCIATION :
+ MediaFile.getFormatCode(displayName, mimeType);
+ final MtpObjectInfo info = new MtpObjectInfo.Builder()
+ .setStorageId(parentId.mStorageId)
+ .setParent(parentId.mObjectHandle)
+ .setFormat(formatCode)
+ .setName(displayName)
+ .build();
+ final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]);
+ final MtpObjectInfo infoWithHandle =
+ new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
+ final String documentId = mDatabase.putNewDocument(
+ parentId.mDeviceId, parentDocumentId, infoWithHandle);
getDocumentLoader(parentId).clearTask(parentId);
notifyChildDocumentsChange(parentDocumentId);
return documentId;
@@ -258,47 +237,26 @@
}
void openDevice(int deviceId) throws IOException {
- synchronized (mDeviceToolkits) {
+ synchronized (mDeviceListLock) {
mMtpManager.openDevice(deviceId);
- mDeviceToolkits.put(deviceId, new DeviceToolkit(mMtpManager, mResolver, mDatabase));
+ mDeviceToolkits.put(
+ deviceId, new DeviceToolkit(mMtpManager, mResolver, mDatabase));
}
mRootScanner.resume();
}
void closeDevice(int deviceId) throws IOException, InterruptedException {
- // TODO: Flush the device before closing (if not closed externally).
- synchronized (mDeviceToolkits) {
- getDeviceToolkit(deviceId).mDocumentLoader.clearTasks();
- mDeviceToolkits.remove(deviceId);
+ synchronized (mDeviceListLock) {
+ closeDeviceInternal(deviceId);
mDatabase.removeDeviceRows(deviceId);
- mMtpManager.closeDevice(deviceId);
}
mRootScanner.notifyChange();
- if (!hasOpenedDevices()) {
- mRootScanner.pause();
- }
- }
-
- synchronized void closeAllDevices() throws InterruptedException {
- boolean closed = false;
- for (int deviceId : mMtpManager.getOpenedDeviceIds()) {
- try {
- mDatabase.removeDeviceRows(deviceId);
- mMtpManager.closeDevice(deviceId);
- getDeviceToolkit(deviceId).mDocumentLoader.clearTasks();
- closed = true;
- } catch (IOException d) {
- Log.d(TAG, "Failed to close the MTP device: " + deviceId);
- }
- }
- if (closed) {
- mRootScanner.notifyChange();
- mRootScanner.pause();
- }
}
boolean hasOpenedDevices() {
- return mMtpManager.getOpenedDeviceIds().length != 0;
+ synchronized (mDeviceListLock) {
+ return mMtpManager.getOpenedDeviceIds().length != 0;
+ }
}
/**
@@ -306,14 +264,18 @@
*/
@Override
public void shutdown() {
- try {
- closeAllDevices();
- } catch (InterruptedException e) {
- // It should fail unit tests by throwing runtime exception.
- throw new RuntimeException(e.getMessage());
- } finally {
- mDatabase.close();
- super.shutdown();
+ synchronized (mDeviceListLock) {
+ try {
+ for (final int id : mMtpManager.getOpenedDeviceIds()) {
+ closeDeviceInternal(id);
+ }
+ } catch (InterruptedException|IOException e) {
+ // It should fail unit tests by throwing runtime exception.
+ throw new RuntimeException(e);
+ } finally {
+ mDatabase.close();
+ super.shutdown();
+ }
}
}
@@ -324,8 +286,35 @@
false);
}
+ /**
+ * Reopens MTP devices based on database state.
+ */
+ private void resume() {
+ synchronized (mDeviceListLock) {
+ mDatabase.getMapper().clearMapping();
+ final int[] ids = mDatabase.getDeviceIds();
+ for (final int id : ids) {
+ try {
+ openDevice(id);
+ } catch (IOException exception) {
+ mDatabase.removeDeviceRows(id);
+ }
+ }
+ }
+ }
+
+ private void closeDeviceInternal(int deviceId) throws IOException, InterruptedException {
+ // TODO: Flush the device before closing (if not closed externally).
+ getDeviceToolkit(deviceId).mDocumentLoader.clearTasks();
+ mDeviceToolkits.remove(deviceId);
+ mMtpManager.closeDevice(deviceId);
+ if (!hasOpenedDevices()) {
+ mRootScanner.pause();
+ }
+ }
+
private DeviceToolkit getDeviceToolkit(int deviceId) throws FileNotFoundException {
- synchronized (mDeviceToolkits) {
+ synchronized (mDeviceListLock) {
final DeviceToolkit toolkit = mDeviceToolkits.get(deviceId);
if (toolkit == null) {
throw new FileNotFoundException();
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
index 723dc14..9b3c20f 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
@@ -55,22 +55,20 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- if (intent == null) {
- // If intent is null, the service was restarted.
- // TODO: Recover opened devices here.
- return START_STICKY;
- }
- if (intent.getAction().equals(ACTION_OPEN_DEVICE)) {
- final UsbDevice device = intent.<UsbDevice>getParcelableExtra(EXTRA_DEVICE);
- try {
- final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
- provider.openDevice(device.getDeviceId());
- return START_STICKY;
- } catch (IOException error) {
- Log.e(MtpDocumentsProvider.TAG, error.getMessage());
+ // If intent is null, the service was restarted.
+ if (intent != null) {
+ if (intent.getAction().equals(ACTION_OPEN_DEVICE)) {
+ final UsbDevice device = intent.<UsbDevice>getParcelableExtra(EXTRA_DEVICE);
+ try {
+ final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
+ provider.openDevice(device.getDeviceId());
+ return START_STICKY;
+ } catch (IOException error) {
+ Log.e(MtpDocumentsProvider.TAG, error.getMessage());
+ }
+ } else {
+ Log.e(MtpDocumentsProvider.TAG, "Received unknown intent action.");
}
- } else {
- Log.w(MtpDocumentsProvider.TAG, "Received unknown intent action.");
}
stopSelfIfNeeded();
return Service.START_NOT_STICKY;
@@ -78,14 +76,8 @@
@Override
public void onDestroy() {
- final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
unregisterReceiver(mReceiver);
mReceiver = null;
- try {
- provider.closeAllDevices();
- } catch (InterruptedException e) {
- Log.e(MtpDocumentsProvider.TAG, e.getMessage());
- }
super.onDestroy();
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 714936d..cd52f31 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -32,6 +32,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
/**
* The model wrapping android.mtp API.
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index affaebd..16523bc 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -22,10 +22,8 @@
import android.util.Log;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index b0962dd..df2ab01 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -113,13 +113,14 @@
for (int deviceId : deviceIds) {
try {
final MtpRoot[] roots = mManager.getRoots(deviceId);
- mDatabase.startAddingRootDocuments(deviceId);
+ mDatabase.getMapper().startAddingRootDocuments(deviceId);
try {
- if (mDatabase.putRootDocuments(deviceId, mResources, roots)) {
+ if (mDatabase.getMapper().putRootDocuments(
+ deviceId, mResources, roots)) {
changed = true;
}
} finally {
- if (mDatabase.stopAddingRootDocuments(deviceId)) {
+ if (mDatabase.getMapper().stopAddingRootDocuments(deviceId)) {
changed = true;
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index a80eb51..f0b4343 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -40,11 +40,11 @@
@Override
public void setUp() {
mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, new TestResources(), new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, new TestResources(), new MtpRoot[] {
new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "")
});
- mDatabase.stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
mManager = new BlockableTestMtpManager(getContext());
mResolver = new TestContentResolver();
mLoader = new DocumentLoader(mManager, mResolver, mDatabase);
@@ -57,7 +57,7 @@
public void testBasic() throws Exception {
final Uri uri = DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, mParentIdentifier.toDocumentId());
+ MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId);
setUpDocument(mManager, 40);
mManager.blockDocument(0, 15);
mManager.blockDocument(0, 35);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 25dd1c8..6d9193d 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -20,10 +20,15 @@
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import java.io.FileNotFoundException;
+
+import static com.android.mtp.MtpDatabase.strings;
+
@SmallTest
public class MtpDatabaseTest extends AndroidTestCase {
private final String[] COLUMN_NAMES = new String[] {
@@ -55,8 +60,8 @@
}
public void testPutRootDocuments() throws Exception {
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, ""),
new MtpRoot(0, 2, "Device", "Storage", 2000, 4000, ""),
new MtpRoot(0, 3, "Device", "/@#%&<>Storage", 3000, 6000,"")
@@ -97,7 +102,7 @@
Root.COLUMN_ICON,
Root.COLUMN_TITLE,
Root.COLUMN_SUMMARY,
- Root.COLUMN_DOCUMENT_ID + "_",
+ Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES,
Root.COLUMN_CAPACITY_BYTES
});
@@ -147,8 +152,8 @@
}
public void testPutChildDocuments() throws Exception {
- mDatabase.startAddingChildDocuments("parentId");
- mDatabase.putChildDocuments(0, "parentId", new MtpObjectInfo[] {
+ mDatabase.getMapper().startAddingChildDocuments("parentId");
+ mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
@@ -222,8 +227,8 @@
Root.COLUMN_AVAILABLE_BYTES
};
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage A", 1000, 0, ""),
new MtpRoot(0, 101, "Device", "Storage B", 1001, 0, "")
});
@@ -254,7 +259,7 @@
cursor.close();
}
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
{
final Cursor cursor = mDatabase.queryRootDocuments(columns);
@@ -282,8 +287,8 @@
cursor.close();
}
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 200, "Device", "Storage A", 2000, 0, ""),
new MtpRoot(0, 202, "Device", "Storage C", 2002, 0, "")
});
@@ -321,7 +326,7 @@
cursor.close();
}
- mDatabase.stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
{
final Cursor cursor = mDatabase.queryRootDocuments(columns);
@@ -356,13 +361,13 @@
MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
DocumentsContract.Document.COLUMN_DISPLAY_NAME
};
- mDatabase.startAddingChildDocuments("parentId");
- mDatabase.putChildDocuments(0, "parentId", new MtpObjectInfo[] {
+ mDatabase.getMapper().startAddingChildDocuments("parentId");
+ mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
});
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
{
final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId");
@@ -386,8 +391,8 @@
cursor.close();
}
- mDatabase.startAddingChildDocuments("parentId");
- mDatabase.putChildDocuments(0, "parentId", new MtpObjectInfo[] {
+ mDatabase.getMapper().startAddingChildDocuments("parentId");
+ mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
});
@@ -404,7 +409,7 @@
cursor.close();
}
- mDatabase.stopAddingChildDocuments("parentId");
+ mDatabase.getMapper().stopAddingChildDocuments("parentId");
{
final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId");
@@ -433,12 +438,12 @@
Root.COLUMN_ROOT_ID,
Root.COLUMN_AVAILABLE_BYTES
};
- mDatabase.startAddingRootDocuments(0);
- mDatabase.startAddingRootDocuments(1);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().startAddingRootDocuments(1);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage", 0, 0, "")
});
- mDatabase.putRootDocuments(1, resources, new MtpRoot[] {
+ mDatabase.getMapper().putRootDocuments(1, resources, new MtpRoot[] {
new MtpRoot(1, 100, "Device", "Storage", 0, 0, "")
});
@@ -468,18 +473,18 @@
cursor.close();
}
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
- mDatabase.startAddingRootDocuments(0);
- mDatabase.startAddingRootDocuments(1);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().startAddingRootDocuments(1);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 200, "Device", "Storage", 2000, 0, "")
});
- mDatabase.putRootDocuments(1, resources, new MtpRoot[] {
+ mDatabase.getMapper().putRootDocuments(1, resources, new MtpRoot[] {
new MtpRoot(1, 300, "Device", "Storage", 3000, 0, "")
});
- mDatabase.stopAddingRootDocuments(0);
- mDatabase.stopAddingRootDocuments(1);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(1);
{
final Cursor cursor = mDatabase.queryRootDocuments(columns);
@@ -514,25 +519,25 @@
MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
};
- mDatabase.startAddingChildDocuments("parentId1");
- mDatabase.startAddingChildDocuments("parentId2");
- mDatabase.putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
+ mDatabase.getMapper().startAddingChildDocuments("parentId1");
+ mDatabase.getMapper().startAddingChildDocuments("parentId2");
+ mDatabase.getMapper().putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
- mDatabase.putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
- mDatabase.startAddingChildDocuments("parentId1");
- mDatabase.startAddingChildDocuments("parentId2");
- mDatabase.putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
+ mDatabase.getMapper().startAddingChildDocuments("parentId1");
+ mDatabase.getMapper().startAddingChildDocuments("parentId2");
+ mDatabase.getMapper().putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
- mDatabase.putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
- mDatabase.stopAddingChildDocuments("parentId1");
+ mDatabase.getMapper().stopAddingChildDocuments("parentId1");
{
final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId1");
@@ -563,23 +568,23 @@
Root.COLUMN_AVAILABLE_BYTES
};
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
});
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
});
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 300, "Device", "Storage", 3000, 0, ""),
});
- mDatabase.stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
{
final Cursor cursor = mDatabase.queryRootDocuments(columns);
@@ -611,18 +616,18 @@
Root.COLUMN_AVAILABLE_BYTES
};
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
});
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
new MtpRoot(0, 201, "Device", "Storage", 2001, 0, ""),
});
- mDatabase.stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
{
final Cursor cursor = mDatabase.queryRootDocuments(columns);
@@ -653,17 +658,17 @@
public void testReplaceExistingRoots() {
// The client code should be able to replace existing rows with new information.
// Add one.
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
});
- mDatabase.stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
// Replace it.
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage B", 1000, 1000, ""),
});
- mDatabase.stopAddingRootDocuments(0);
+ mDatabase.getMapper().stopAddingRootDocuments(0);
{
final String[] columns = new String[] {
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
@@ -692,26 +697,155 @@
}
}
- public void _testFailToReplaceExisitingUnmappedRoots() {
+ public void testFailToReplaceExisitingUnmappedRoots() {
// The client code should not be able to replace rows before resolving 'unmapped' rows.
// Add one.
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
});
- mDatabase.clearMapping();
+ mDatabase.getMapper().clearMapping();
+ final Cursor oldCursor = mDatabase.queryRoots(strings(Root.COLUMN_ROOT_ID));
+ assertEquals(1, oldCursor.getCount());
+
// Add one.
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
- new MtpRoot(0, 100, "Device", "Storage B", 1000, 1000, ""),
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+ new MtpRoot(0, 101, "Device", "Storage B", 1000, 1000, ""),
});
// Add one more before resolving unmapped documents.
- try {
- mDatabase.putRootDocuments(0, resources, new MtpRoot[] {
- new MtpRoot(0, 100, "Device", "Storage B", 1000, 1000, ""),
- });
- fail();
- } catch (Throwable e) {
- assertTrue(e instanceof Error);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+ new MtpRoot(0, 102, "Device", "Storage B", 1000, 1000, ""),
+ });
+ mDatabase.getMapper().stopAddingRootDocuments(0);
+
+ // Because the roots shares the same name, the roots should have new IDs.
+ final Cursor newCursor = mDatabase.queryRoots(strings(Root.COLUMN_ROOT_ID));
+ assertEquals(2, newCursor.getCount());
+ oldCursor.moveToNext();
+ newCursor.moveToNext();
+ assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
+ newCursor.moveToNext();
+ assertFalse(oldCursor.getString(0).equals(newCursor.getString(0)));
+
+ oldCursor.close();
+ newCursor.close();
+ }
+
+ public void testQueryDocument() {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+ new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+ });
+ mDatabase.getMapper().stopAddingRootDocuments(0);
+
+ final Cursor cursor = mDatabase.queryDocument("1", strings(Document.COLUMN_DISPLAY_NAME));
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("Device Storage A", cursor.getString(0));
+ cursor.close();
+ }
+
+ public void testGetParentId() throws FileNotFoundException {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+ new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+ });
+ mDatabase.getMapper().stopAddingRootDocuments(0);
+
+ mDatabase.getMapper().startAddingChildDocuments("1");
+ mDatabase.getMapper().putChildDocuments(
+ 0,
+ "1",
+ new MtpObjectInfo[] {
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
+ mDatabase.getMapper().stopAddingChildDocuments("1");
+
+ assertEquals("1", mDatabase.getParentId("2"));
+ }
+
+ public void testDeleteDocument() {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+ new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+ });
+ mDatabase.getMapper().stopAddingRootDocuments(0);
+
+ mDatabase.getMapper().startAddingChildDocuments("1");
+ mDatabase.getMapper().putChildDocuments(
+ 0,
+ "1",
+ new MtpObjectInfo[] {
+ createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
+ });
+ mDatabase.getMapper().stopAddingChildDocuments("1");
+
+ mDatabase.getMapper().startAddingChildDocuments("2");
+ mDatabase.getMapper().putChildDocuments(
+ 0,
+ "2",
+ new MtpObjectInfo[] {
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
+ mDatabase.getMapper().stopAddingChildDocuments("2");
+
+ mDatabase.deleteDocument("2");
+
+ {
+ // Do not query deleted documents.
+ final Cursor cursor =
+ mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "1");
+ assertEquals(0, cursor.getCount());
+ cursor.close();
+ }
+
+ {
+ // Child document should be deleted also.
+ final Cursor cursor =
+ mDatabase.queryDocument("3", strings(Document.COLUMN_DOCUMENT_ID));
+ assertEquals(0, cursor.getCount());
+ cursor.close();
+ }
+ }
+
+ public void testPutNewDocument() {
+ mDatabase.getMapper().startAddingRootDocuments(0);
+ mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+ new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+ });
+ mDatabase.getMapper().stopAddingRootDocuments(0);
+
+ assertEquals(
+ "2",
+ mDatabase.putNewDocument(
+ 0, "1", createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
+
+ {
+ final Cursor cursor =
+ mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "1");
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("2", cursor.getString(0));
+ cursor.close();
+ }
+
+ // The new document should not be mapped with existing invalidated document.
+ mDatabase.getMapper().clearMapping();
+ mDatabase.getMapper().startAddingChildDocuments("1");
+ mDatabase.putNewDocument(
+ 0,
+ "1",
+ createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024));
+ mDatabase.getMapper().stopAddingChildDocuments("1");
+
+ {
+ final Cursor cursor =
+ mDatabase.queryChildDocuments(strings(Document.COLUMN_DOCUMENT_ID), "1");
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("3", cursor.getString(0));
+ cursor.close();
}
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index cabb08d..b20b3bb 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -23,10 +23,14 @@
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import static com.android.mtp.MtpDatabase.strings;
@SmallTest
public class MtpDocumentsProviderTest extends AndroidTestCase {
@@ -42,17 +46,16 @@
public void setUp() throws IOException {
mResolver = new TestContentResolver();
mMtpManager = new TestMtpManager(getContext());
- mProvider = new MtpDocumentsProvider();
- mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
- mProvider.onCreateForTesting(mResources, mMtpManager, mResolver, mDatabase);
}
@Override
public void tearDown() {
mProvider.shutdown();
+ MtpDatabase.deleteDatabase(getContext());
}
public void testOpenAndCloseDevice() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mMtpManager.setRoots(0, new MtpRoot[] {
new MtpRoot(
@@ -73,6 +76,7 @@
}
public void testOpenAndCloseErrorDevice() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
try {
mProvider.openDevice(1);
fail();
@@ -104,6 +108,7 @@
}
public void testQueryRoots() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mMtpManager.addValidDevice(1);
mMtpManager.setRoots(0, new MtpRoot[] {
@@ -138,7 +143,7 @@
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
assertEquals("Device A Storage A", cursor.getString(3));
- assertEquals("0_1_0", cursor.getString(4));
+ assertEquals("1", cursor.getString(4));
assertEquals(1024, cursor.getInt(5));
}
@@ -154,12 +159,13 @@
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
assertEquals("Device B Storage B", cursor.getString(3));
- assertEquals("1_1_0", cursor.getString(4));
+ assertEquals("2", cursor.getString(4));
assertEquals(2048, cursor.getInt(5));
}
}
public void testQueryRoots_error() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mMtpManager.addValidDevice(1);
// Not set roots for device 0 so that MtpManagerMock#getRoots throws IOException.
@@ -186,29 +192,39 @@
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
assertEquals("Device B Storage B", cursor.getString(3));
- assertEquals("1_1_0", cursor.getString(4));
+ assertEquals("1", cursor.getString(4));
assertEquals(2048, cursor.getInt(5));
}
}
- public void testQueryDocument() throws IOException {
+ public void testQueryDocument() throws IOException, InterruptedException, TimeoutException {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
- mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(2)
- .setStorageId(1)
- .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
- .setName("image.jpg")
- .setDateModified(1422716400000L)
- .setCompressedSize(1024 * 1024 * 5)
- .setThumbCompressedSize(1024 * 50)
- .build());
- final Cursor cursor = mProvider.queryDocument("0_1_2", null);
+
+ setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+ setupDocuments(
+ 0,
+ 0,
+ MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
+ "1",
+ new MtpObjectInfo[] {
+ new MtpObjectInfo.Builder()
+ .setObjectHandle(100)
+ .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
+ .setName("image.jpg")
+ .setDateModified(1422716400000L)
+ .setCompressedSize(1024 * 1024 * 5)
+ .setThumbCompressedSize(50 * 1024)
+ .build()
+ });
+
+ final Cursor cursor = mProvider.queryDocument("2", null);
assertEquals(1, cursor.getCount());
cursor.moveToNext();
- assertEquals("0_1_2", cursor.getString(0));
+ assertEquals("2", cursor.getString(0));
assertEquals("image/jpeg", cursor.getString(1));
assertEquals("image.jpg", cursor.getString(2));
assertEquals(1422716400000L, cursor.getLong(3));
@@ -220,21 +236,33 @@
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
}
- public void testQueryDocument_directory() throws IOException {
+ public void testQueryDocument_directory()
+ throws IOException, InterruptedException, TimeoutException {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
- mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(2)
- .setStorageId(1)
- .setFormat(MtpConstants.FORMAT_ASSOCIATION)
- .setName("directory")
- .setDateModified(1422716400000L)
- .build());
- final Cursor cursor = mProvider.queryDocument("0_1_2", null);
+
+ setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+ setupDocuments(
+ 0,
+ 0,
+ MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
+ "1",
+ new MtpObjectInfo[] {
+ new MtpObjectInfo.Builder()
+ .setObjectHandle(2)
+ .setStorageId(1)
+ .setFormat(MtpConstants.FORMAT_ASSOCIATION)
+ .setName("directory")
+ .setDateModified(1422716400000L)
+ .build()
+ });
+
+ final Cursor cursor = mProvider.queryDocument("2", null);
assertEquals(1, cursor.getCount());
cursor.moveToNext();
- assertEquals("0_1_2", cursor.getString(0));
+ assertEquals("2", cursor.getString(0));
assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
assertEquals("directory", cursor.getString(2));
assertEquals(1422716400000L, cursor.getLong(3));
@@ -246,10 +274,13 @@
assertEquals(0, cursor.getInt(5));
}
- public void testQueryDocument_forRoot() throws IOException {
+ public void testQueryDocument_forRoot()
+ throws IOException, InterruptedException, TimeoutException {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
- mMtpManager.setRoots(0, new MtpRoot[] {
+
+ setupRoots(0, new MtpRoot[] {
new MtpRoot(
0 /* deviceId */,
1 /* storageId */,
@@ -259,11 +290,11 @@
4096 /* total space */,
"" /* no volume identifier */)
});
- final Cursor cursor = mProvider.queryDocument("0_1_0", null);
+ final Cursor cursor = mProvider.queryDocument("1", null);
assertEquals(1, cursor.getCount());
cursor.moveToNext();
- assertEquals("0_1_0", cursor.getString(0));
+ assertEquals("1", cursor.getString(0));
assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
assertEquals("Device A Storage A", cursor.getString(2));
assertTrue(cursor.isNull(3));
@@ -272,44 +303,47 @@
}
public void testQueryChildDocuments() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
- mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
- mDatabase.startAddingRootDocuments(0);
- mDatabase.putRootDocuments(0, mResources, new MtpRoot[] {
- new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "")
- });
- mDatabase.stopAddingRootDocuments(0);
+ setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+ setupDocuments(
+ 0,
+ 0,
+ MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
+ "1",
+ new MtpObjectInfo[] {
+ new MtpObjectInfo.Builder()
+ .setObjectHandle(100)
+ .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
+ .setName("image.jpg")
+ .setCompressedSize(1024 * 1024 * 5)
+ .setThumbCompressedSize(5 * 1024)
+ .setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY)
+ .build()
+ });
- mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(1)
- .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
- .setName("image.jpg")
- .setCompressedSize(1024 * 1024 * 5)
- .setThumbCompressedSize(5 * 1024)
- .setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY)
- .build());
-
- final Cursor cursor = mProvider.queryChildDocuments("0_0_0", null, null);
+ final Cursor cursor = mProvider.queryChildDocuments("1", null, null);
assertEquals(1, cursor.getCount());
assertTrue(cursor.moveToNext());
- assertEquals("0_0_1", cursor.getString(0));
+ assertEquals("2", cursor.getString(0));
assertEquals("image/jpeg", cursor.getString(1));
assertEquals("image.jpg", cursor.getString(2));
assertEquals(0, cursor.getLong(3));
assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
- assertFalse(cursor.moveToNext());
+ cursor.close();
}
public void testQueryChildDocuments_cursorError() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
try {
- mProvider.queryChildDocuments("0_0_0", null, null);
+ mProvider.queryChildDocuments("1", null, null);
fail();
} catch (Throwable error) {
assertTrue(error instanceof FileNotFoundException);
@@ -317,44 +351,134 @@
}
public void testQueryChildDocuments_documentError() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
+ setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
try {
- mProvider.queryChildDocuments("0_0_0", null, null);
+ mProvider.queryChildDocuments("1", null, null);
fail();
} catch (Throwable error) {
assertTrue(error instanceof FileNotFoundException);
}
}
- public void testDeleteDocument() throws IOException {
+ public void testDeleteDocument() throws IOException, InterruptedException, TimeoutException {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
- mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(1)
- .setParent(2)
- .build());
- mProvider.deleteDocument("0_0_1");
+ setupRoots(0, new MtpRoot[] {
+ new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")
+ });
+ setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
+ new MtpObjectInfo.Builder()
+ .setName("test.txt")
+ .setObjectHandle(1)
+ .setParent(-1)
+ .build()
+ });
+
+ mProvider.deleteDocument("2");
assertEquals(1, mResolver.getChangeCount(
DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, "0_0_2")));
+ MtpDocumentsProvider.AUTHORITY, "1")));
}
- public void testDeleteDocument_error() throws IOException {
+ public void testDeleteDocument_error()
+ throws IOException, InterruptedException, TimeoutException {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(0);
mProvider.openDevice(0);
- mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(2)
- .build());
+ setupRoots(0, new MtpRoot[] {
+ new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")
+ });
+ setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
+ new MtpObjectInfo.Builder()
+ .setName("test.txt")
+ .setObjectHandle(1)
+ .setParent(-1)
+ .build()
+ });
try {
- mProvider.deleteDocument("0_0_1");
+ mProvider.deleteDocument("3");
fail();
} catch (Throwable e) {
assertTrue(e instanceof IOException);
}
assertEquals(0, mResolver.getChangeCount(
DocumentsContract.buildChildDocumentsUri(
- MtpDocumentsProvider.AUTHORITY, "0_0_2")));
+ MtpDocumentsProvider.AUTHORITY, "1")));
+ }
+
+ @MediumTest
+ public void testPauseAndResume() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
+ mMtpManager.addValidDevice(0);
+ mProvider.openDevice(0);
+ setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")});
+
+ {
+ final Cursor cursor = mProvider.queryRoots(
+ strings(DocumentsContract.Root.COLUMN_ROOT_ID));
+ cursor.moveToNext();
+ assertEquals(1, cursor.getInt(0));
+ }
+
+ mProvider.shutdown();
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
+
+ {
+ // We can still fetch roots after relaunching the provider.
+ final Cursor cursor = mProvider.queryRoots(
+ strings(DocumentsContract.Root.COLUMN_ROOT_ID));
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(1, cursor.getInt(0));
+ assertEquals(1, mMtpManager.getOpenedDeviceIds().length);
+ }
+ }
+
+ private void setupProvider(int flag) {
+ mDatabase = new MtpDatabase(getContext(), flag);
+ mProvider = new MtpDocumentsProvider();
+ mProvider.onCreateForTesting(mResources, mMtpManager, mResolver, mDatabase);
+ }
+
+ private String[] getStrings(Cursor cursor) {
+ try {
+ final String[] results = new String[cursor.getCount()];
+ for (int i = 0; cursor.moveToNext(); i++) {
+ results[i] = cursor.getString(0);
+ }
+ return results;
+ } finally {
+ cursor.close();
+ }
+ }
+
+ private String[] setupRoots(int deviceId, MtpRoot[] roots)
+ throws FileNotFoundException, InterruptedException, TimeoutException {
+ final int changeCount = mResolver.getChangeCount(ROOTS_URI);
+ mMtpManager.setRoots(deviceId, roots);
+ mResolver.waitForNotification(ROOTS_URI, changeCount + 1);
+ return getStrings(mProvider.queryRoots(strings(DocumentsContract.Root.COLUMN_ROOT_ID)));
+ }
+
+ private String[] setupDocuments(
+ int deviceId,
+ int storageId,
+ int parentHandle,
+ String parentDocumentId,
+ MtpObjectInfo[] objects) throws FileNotFoundException {
+ final int[] handles = new int[objects.length];
+ int i = 0;
+ for (final MtpObjectInfo info : objects) {
+ handles[i] = info.getObjectHandle();
+ mMtpManager.setObjectInfo(deviceId, info);
+ }
+ mMtpManager.setObjectHandles(deviceId, storageId, parentHandle, handles);
+ return getStrings(mProvider.queryChildDocuments(
+ parentDocumentId, strings(DocumentsContract.Document.COLUMN_DOCUMENT_ID), null));
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index 7c947f5..ccdea03 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -44,13 +44,13 @@
public void testReadDocument_basic() throws Exception {
mtpManager.setImportFileBytes(0, 1, HELLO_BYTES);
final ParcelFileDescriptor descriptor = mPipeManager.readDocument(
- mtpManager, new Identifier(0, 0, 1));
+ mtpManager, new Identifier(0, 0, 1, null));
assertDescriptor(descriptor, HELLO_BYTES);
}
public void testReadDocument_error() throws Exception {
final ParcelFileDescriptor descriptor =
- mPipeManager.readDocument(mtpManager, new Identifier(0, 0, 1));
+ mPipeManager.readDocument(mtpManager, new Identifier(0, 0, 1, null));
assertDescriptorError(descriptor);
}
@@ -62,7 +62,7 @@
// Upload testing bytes.
final ParcelFileDescriptor descriptor = mPipeManager.writeDocument(
- getContext(), mtpManager, new Identifier(0, 0, 1));
+ getContext(), mtpManager, new Identifier(0, 0, 1, null));
final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
@@ -94,13 +94,13 @@
public void testReadThumbnail_basic() throws Exception {
mtpManager.setThumbnail(0, 1, HELLO_BYTES);
final ParcelFileDescriptor descriptor = mPipeManager.readThumbnail(
- mtpManager, new Identifier(0, 0, 1));
+ mtpManager, new Identifier(0, 0, 1, null));
assertDescriptor(descriptor, HELLO_BYTES);
}
public void testReadThumbnail_error() throws Exception {
final ParcelFileDescriptor descriptor =
- mPipeManager.readThumbnail(mtpManager, new Identifier(0, 0, 1));
+ mPipeManager.readThumbnail(mtpManager, new Identifier(0, 0, 1, null));
assertDescriptorError(descriptor);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 67e170f..6521565 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -556,8 +556,7 @@
// Make sure the IME is not on the way of preview as
// the user may have used it to type copies or range.
- InputMethodManager imm = (InputMethodManager) getSystemService(
- Context.INPUT_METHOD_SERVICE);
+ InputMethodManager imm = getSystemService(InputMethodManager.class);
imm.hideSoftInputFromWindow(mDestinationSpinner.getWindowToken(), 0);
}
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 8fa5abf..98a171e 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -72,7 +72,7 @@
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sparuj"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SPARUJ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anuluj"</string>
- <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Parowanie spowoduje przyznanie dostępu do historii połączeń i Twoich kontaktów w trakcie połączenia."</string>
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Sparowanie powoduje przyznanie dostępu do historii połączeń i Twoich kontaktów w trakcie połączenia."</string>
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nie można sparować z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nie można sparować z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ze względu na błędny kod PIN lub klucz."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Nie można skomunikować się z urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 029962e..c3c287c 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -38,7 +38,7 @@
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"กำลังตัดการเชื่อมต่อ..."</string>
<string name="bluetooth_connecting" msgid="8555009514614320497">"กำลังเชื่อมต่อ…"</string>
<string name="bluetooth_connected" msgid="6038755206916626419">"เชื่อมต่อแล้ว"</string>
- <string name="bluetooth_pairing" msgid="1426882272690346242">"กำลังกำหนดค่าอุปกรณ์ให้ตรงกัน..."</string>
+ <string name="bluetooth_pairing" msgid="1426882272690346242">"กำลังจับคู่อุปกรณ์..."</string>
<string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"เชื่อมต่อแล้ว (ยกเว้นเสียงโทรศัพท์)"</string>
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"เชื่อมต่อแล้ว (ยกเว้นเสียงสื่อ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"เชื่อมต่อแล้ว (ไม่มีการเข้าถึงข้อความ)"</string>
@@ -69,14 +69,14 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ใช้สำหรับระบบเสียงของโทรศัพท์"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ใช้สำหรับการโอนไฟล์"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ใช้สำหรับการป้อนข้อมูล"</string>
- <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"กำหนดค่าอุปกรณ์ให้ตรงกัน"</string>
+ <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"จับคู่อุปกรณ์"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"จับคู่อุปกรณ์"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ยกเลิก"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"การจับคู่อุปกรณ์จะให้สิทธิ์การเข้าถึงที่อยู่ติดต่อและประวัติการโทรเมื่อเชื่อมต่อแล้ว"</string>
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"ไม่สามารถจับคู่กับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"ไม่สามารถจับคู่กับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ได้เพราะ PIN หรือรหัสผ่านไม่ถูกต้อง"</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"ไม่สามารถเชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"การกำหนดค่าอุปกรณ์ให้ตรงกันถูกปฏิเสธโดย <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ปฏิเสธการจับคู่อุปกรณ์"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi ปิดอยู่"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"ไม่ได้เชื่อมต่อ Wi-Fi"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"สัญญาณ Wi-Fi 1 ขีด"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 6102bef..00dadb8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -143,6 +143,9 @@
public boolean openTile(DashboardTile tile) {
closeDrawer();
+ if (tile == null) {
+ return false;
+ }
int numUserHandles = tile.userHandle.size();
if (numUserHandles > 1) {
ProfileSelectDialog.show(getFragmentManager(), tile);
diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml
index 40735cc..ba1431d 100644
--- a/packages/SettingsProvider/res/values-it/strings.xml
+++ b/packages/SettingsProvider/res/values-it/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4567566098528588863">"Archiviazione impostazioni"</string>
+ <string name="app_label" msgid="4567566098528588863">"Memoria impostazioni"</string>
</resources>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index bf3982d..25346ac 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -144,6 +144,7 @@
android:name=".BugreportReceiver"
android:permission="android.permission.DUMP">
<intent-filter>
+ <action android:name="android.intent.action.BUGREPORT_STARTED" />
<action android:name="android.intent.action.BUGREPORT_FINISHED" />
</intent-filter>
</receiver>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index 4469d38..cff36f7 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -17,6 +17,8 @@
<resources>
<string name="app_label">Shell</string>
+ <!-- Title of notification indicating a bugreport process is in progress. [CHAR LIMIT=50] -->
+ <string name="bugreport_in_progress_title">Bug report in progress</string>
<!-- Title of notification indicating a bugreport has been successfully captured. [CHAR LIMIT=50] -->
<string name="bugreport_finished_title">Bug report captured</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index a2030ef..d0e91d2 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -21,11 +21,16 @@
import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintWriter;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -45,26 +50,102 @@
import android.content.res.Configuration;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcelable;
+import android.os.Process;
import android.os.SystemProperties;
import android.support.v4.content.FileProvider;
+import android.text.format.DateUtils;
import android.util.Log;
import android.util.Patterns;
+import android.util.SparseArray;
import android.widget.Toast;
+/**
+ * Service used to keep progress of bug reports processes ({@code dumpstate}).
+ * <p>
+ * The workflow is:
+ * <ol>
+ * <li>When {@code dumpstate} starts, it sends a {@code BUGREPORT_STARTED} with its pid and the
+ * estimated total effort.
+ * <li>{@link BugreportReceiver} receives the intent and delegates it to this service.
+ * <li>Upon start, this service:
+ * <ol>
+ * <li>Issues a system notification so user can watch the progresss (which is 0% initially).
+ * <li>Polls the {@link SystemProperties} for updates on the {@code dumpstate} progress.
+ * <li>If the progress changed, it updates the system notification.
+ * </ol>
+ * <li>As {@code dumpstate} progresses, it updates the system property.
+ * <li>When {@code dumpstate} finishes, it sends a {@code BUGREPORT_FINISHED} intent.
+ * <li>{@link BugreportReceiver} receives the intent and delegates it to this service, which in
+ * turn:
+ * <ol>
+ * <li>Updates the system notification so user can share the bug report.
+ * <li>Stops monitoring that {@code dumpstate} process.
+ * <li>Stops itself if it doesn't have any process left to monitor.
+ * </ol>
+ * </ol>
+ */
public class BugreportProgressService extends Service {
private static final String TAG = "Shell";
+ private static final boolean DEBUG = false;
private static final String AUTHORITY = "com.android.shell";
+ static final String INTENT_BUGREPORT_STARTED = "android.intent.action.BUGREPORT_STARTED";
+ static final String INTENT_BUGREPORT_FINISHED = "android.intent.action.BUGREPORT_FINISHED";
+
static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
+ static final String EXTRA_PID = "android.intent.extra.PID";
+ static final String EXTRA_MAX = "android.intent.extra.MAX";
+ static final String EXTRA_NAME = "android.intent.extra.NAME";
+ static final String EXTRA_ORIGINAL_INTENT = "android.intent.extra.ORIGINAL_INTENT";
+
+ private static final int MSG_SERVICE_COMMAND = 1;
+ private static final int MSG_POLL = 2;
+
+ /** Polling frequency, in milliseconds. */
+ private static final long POLLING_FREQUENCY = 500;
+
+ /** How long (in ms) a dumpstate process will be monitored if it didn't show progress. */
+ private static final long INACTIVITY_TIMEOUT = 3 * DateUtils.MINUTE_IN_MILLIS;
+
+ /** System property used for monitoring progress. */
+ private static final String PROGRESS_PROPERTY_TEMPLATE = "dumpstate.%d.progress";
+
+ /** Managed dumpstate processes (keyed by pid) */
+ private final SparseArray<BugreportInfo> mProcesses = new SparseArray<>();
+
+ private Looper mServiceLooper;
+ private ServiceHandler mServiceHandler;
+
+ @Override
+ public void onCreate() {
+ HandlerThread thread = new HandlerThread("BugreportProgressServiceThread",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+
+ mServiceLooper = thread.getLooper();
+ mServiceHandler = new ServiceHandler(mServiceLooper);
+ }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
- onBugreportFinished(intent);
+ // Handle it in a separate thread.
+ Message msg = mServiceHandler.obtainMessage();
+ msg.what = MSG_SERVICE_COMMAND;
+ msg.obj = intent;
+ mServiceHandler.sendMessage(msg);
}
+
+ // If service is killed it cannot be recreated because it would not know which
+ // dumpstate PIDs it would have to watch.
return START_NOT_STICKY;
}
@@ -73,26 +154,249 @@
return null;
}
- private void onBugreportFinished(Intent intent) {
- final Context context = getApplicationContext();
- final Configuration conf = context.getResources().getConfiguration();
- final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
- final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
+ @Override
+ public void onDestroy() {
+ mServiceLooper.quit();
+ super.onDestroy();
+ }
- if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
- triggerLocalNotification(context, bugreportFile, screenshotFile);
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.printf("Monitored dumpstate processes: \n");
+ synchronized (mProcesses) {
+ for (int i = 0; i < mProcesses.size(); i++) {
+ writer.printf("\t%s\n", mProcesses.valueAt(i));
+ }
}
- stopSelf();
+ }
+
+ private final class ServiceHandler extends Handler {
+ public ServiceHandler(Looper looper) {
+ super(looper);
+ pollProgress();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_POLL) {
+ pollProgress();
+ return;
+ }
+
+ if (msg.what != MSG_SERVICE_COMMAND) {
+ // Sanity check.
+ Log.e(TAG, "Invalid message type: " + msg.what);
+ return;
+ }
+
+ // At this point it's handling onStartCommand(), whose intent contains the extras
+ // originally received by BugreportReceiver.
+ if (!(msg.obj instanceof Intent)) {
+ // Sanity check.
+ Log.e(TAG, "Internal error: invalid msg.obj: " + msg.obj);
+ return;
+ }
+ final Parcelable parcel = ((Intent) msg.obj).getParcelableExtra(EXTRA_ORIGINAL_INTENT);
+ if (!(parcel instanceof Intent)) {
+ // Sanity check.
+ Log.e(TAG, "Internal error: msg.obj is missing extra " + EXTRA_ORIGINAL_INTENT);
+ return;
+ }
+
+ final Intent intent = (Intent) parcel;
+ final String action = intent.getAction();
+ int pid = intent.getIntExtra(EXTRA_PID, 0);
+ int max = intent.getIntExtra(EXTRA_MAX, -1);
+ String name = intent.getStringExtra(EXTRA_NAME);
+
+ if (DEBUG) Log.v(TAG, "action: " + action + ", name: " + name + ", pid: " + pid
+ + ", max: "+ max);
+ switch (action) {
+ case INTENT_BUGREPORT_STARTED:
+ if (!startProgress(name, pid, max)) {
+ stopSelfWhenDone();
+ return;
+ }
+ break;
+ case INTENT_BUGREPORT_FINISHED:
+ if (pid == -1) {
+ // Shouldn't happen, unless BUGREPORT_FINISHED is received from a legacy,
+ // out-of-sync dumpstate process.
+ Log.w(TAG, "Missing " + EXTRA_PID + " on intent " + intent);
+ }
+ stopProgress(pid, intent);
+ break;
+ default:
+ Log.w(TAG, "Unsupported intent: " + action);
+ }
+ return;
+
+ }
+
+ /**
+ * Creates the {@link BugreportInfo} for a process and issue a system notification to
+ * indicate its progress.
+ *
+ * @return whether it succeeded or not.
+ */
+ private boolean startProgress(String name, int pid, int max) {
+ if (name == null) {
+ Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent");
+ name = "N/A";
+ }
+ if (pid == -1) {
+ Log.e(TAG, "Missing " + EXTRA_PID + " on start intent");
+ return false;
+ }
+ if (max <= 0) {
+ Log.e(TAG, "Invalid value for extra " + EXTRA_MAX + ": " + max);
+ return false;
+ }
+
+ final BugreportInfo info = new BugreportInfo(pid, name, max);
+ synchronized (mProcesses) {
+ if (mProcesses.indexOfKey(pid) >= 0) {
+ Log.w(TAG, "PID " + pid + " already watched");
+ } else {
+ mProcesses.put(info.pid, info);
+ }
+ }
+ updateProgress(info);
+ return true;
+ }
+
+ /**
+ * Updates the system notification for a given bug report.
+ */
+ private void updateProgress(BugreportInfo info) {
+ if (info.max <= 0 || info.progress < 0 || info.name == null) {
+ Log.e(TAG, "Invalid progress values for " + info);
+ return;
+ }
+
+ final Context context = getApplicationContext();
+ final NumberFormat nf = NumberFormat.getPercentInstance();
+ nf.setMinimumFractionDigits(2);
+ nf.setMaximumFractionDigits(2);
+ final String percentText = nf.format((double) info.progress / info.max);
+
+ final String title = context.getString(R.string.bugreport_in_progress_title);
+ final Notification notification = new Notification.Builder(context)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setContentTitle(title)
+ .setTicker(title)
+ .setContentText(info.name)
+ .setContentInfo(percentText)
+ .setProgress(info.max, info.progress, false)
+ // TODO: .setOngoing(true) once it has a CANCEL action
+ .setLocalOnly(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .build();
+
+ NotificationManager.from(context).notify(TAG, info.pid, notification);
+ }
+
+ /**
+ * Finalizes the progress on a given process and sends the finished intent.
+ */
+ private void stopProgress(int pid, Intent intent) {
+ synchronized (mProcesses) {
+ if (mProcesses.indexOfKey(pid) < 0) {
+ Log.w(TAG, "PID not watched: " + pid);
+ } else {
+ mProcesses.remove(pid);
+ }
+ stopSelfWhenDone();
+ }
+ if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): cancel notification");
+ NotificationManager.from(getApplicationContext()).cancel(TAG, pid);
+ if (intent != null) {
+ // Bug report finished fine: send a new, different notification.
+ if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): finish bug report");
+ onBugreportFinished(pid, intent);
+ }
+ }
+
+ /**
+ * Poll {@link SystemProperties} to get the progress on each monitored process.
+ */
+ private void pollProgress() {
+ synchronized (mProcesses) {
+ if (mProcesses.size() == 0) {
+ Log.d(TAG, "No process to poll progress.");
+ }
+ for (int i = 0; i < mProcesses.size(); i++) {
+ int pid = mProcesses.keyAt(i);
+ String property = String.format(PROGRESS_PROPERTY_TEMPLATE, pid);
+ int progress;
+ try {
+ progress = SystemProperties.getInt(property, 0);
+ } catch (IllegalArgumentException e) {
+ Log.v(TAG, "Could not read system property " + property, e);
+ continue;
+ }
+ if (progress == 0) {
+ Log.v(TAG, "System property " + property + " is not set yet");
+ continue;
+ }
+
+ BugreportInfo info = mProcesses.valueAt(i);
+
+ if (progress != info.progress) {
+ if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + " from "
+ + info.progress + " to " + progress);
+ info.progress = progress;
+ info.lastUpdate = System.currentTimeMillis();
+ updateProgress(info);
+ } else {
+ long inactiveTime = System.currentTimeMillis() - info.lastUpdate;
+ if (inactiveTime >= INACTIVITY_TIMEOUT) {
+ Log.w(TAG, "No progress update for process " + pid + " since "
+ + info.getFormattedLastUpdate());
+ stopProgress(info.pid, null);
+ }
+ }
+ }
+ // Keep polling...
+ sendEmptyMessageDelayed(MSG_POLL, POLLING_FREQUENCY);
+ }
+ }
+
+ /**
+ * Finishes the service when it's not monitoring any more processes.
+ */
+ private void stopSelfWhenDone() {
+ synchronized (mProcesses) {
+ if (mProcesses.size() > 0) {
+ if (DEBUG) Log.v(TAG, "Staying alive, waiting for pids " + mProcesses);
+ return;
+ }
+ Log.v(TAG, "No more pids to handle, shutting down");
+ stopSelf();
+ }
+ }
+
+ private void onBugreportFinished(int pid, Intent intent) {
+ final Context context = getApplicationContext();
+ final Configuration conf = context.getResources().getConfiguration();
+ final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
+ final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
+
+ if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
+ triggerLocalNotification(context, pid, bugreportFile, screenshotFile);
+ }
+ }
}
/**
- * Responsible for triggering a notification that allows the user to start a
- * "share" intent with the bug report. On watches we have other methods to allow the user to
- * start this intent (usually by triggering it on another connected device); we don't need to
- * display the notification in this case.
+ * Responsible for triggering a notification that allows the user to start a "share" intent with
+ * the bug report. On watches we have other methods to allow the user to start this intent
+ * (usually by triggering it on another connected device); we don't need to display the
+ * notification in this case.
*/
- private static void triggerLocalNotification(final Context context, final File bugreportFile,
- final File screenshotFile) {
+ private static void triggerLocalNotification(final Context context, final int pid,
+ final File bugreportFile, final File screenshotFile) {
if (!bugreportFile.exists() || !bugreportFile.canRead()) {
Log.e(TAG, "Could not read bugreport file " + bugreportFile);
Toast.makeText(context, context.getString(R.string.bugreport_unreadable_text),
@@ -103,10 +407,10 @@
boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
if (!isPlainText) {
// Already zipped, send it right away.
- sendBugreportNotification(context, bugreportFile, screenshotFile);
+ sendBugreportNotification(context, pid, bugreportFile, screenshotFile);
} else {
// Asynchronously zip the file first, then send it.
- sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+ sendZippedBugreportNotification(context, pid, bugreportFile, screenshotFile);
}
}
@@ -155,7 +459,7 @@
/**
* Sends a bugreport notitication.
*/
- private static void sendBugreportNotification(Context context, File bugreportFile,
+ private static void sendBugreportNotification(Context context, int pid, File bugreportFile,
File screenshotFile) {
// Files are kept on private storage, so turn into Uris that we can
// grant temporary permissions for.
@@ -173,10 +477,11 @@
}
notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final String title = context.getString(R.string.bugreport_finished_title);
final Notification.Builder builder = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
- .setContentTitle(context.getString(R.string.bugreport_finished_title))
- .setTicker(context.getString(R.string.bugreport_finished_title))
+ .setContentTitle(title)
+ .setTicker(title)
.setContentText(context.getString(R.string.bugreport_finished_text))
.setContentIntent(PendingIntent.getActivity(
context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
@@ -185,19 +490,19 @@
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
- NotificationManager.from(context).notify(TAG, 0, builder.build());
+ NotificationManager.from(context).notify(TAG, pid, builder.build());
}
/**
* Sends a zipped bugreport notification.
*/
private static void sendZippedBugreportNotification(final Context context,
- final File bugreportFile, final File screenshotFile) {
+ final int pid, final File bugreportFile, final File screenshotFile) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
File zippedFile = zipBugreport(bugreportFile);
- sendBugreportNotification(context, zippedFile, screenshotFile);
+ sendBugreportNotification(context, pid, zippedFile, screenshotFile);
return null;
}
}.execute();
@@ -213,8 +518,8 @@
Log.v(TAG, "zipping " + bugreportPath + " as " + zippedPath);
File bugreportZippedFile = new File(zippedPath);
try (InputStream is = new FileInputStream(bugreportFile);
- ZipOutputStream zos = new ZipOutputStream(
- new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) {
+ ZipOutputStream zos = new ZipOutputStream(
+ new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) {
ZipEntry entry = new ZipEntry(bugreportFile.getName());
entry.setTime(bugreportFile.lastModified());
zos.putNextEntry(entry);
@@ -230,8 +535,8 @@
}
return bugreportZippedFile;
} catch (IOException e) {
- Log.e(TAG, "exception zipping file " + zippedPath, e);
- return bugreportFile; // Return original.
+ Log.e(TAG, "exception zipping file " + zippedPath, e);
+ return bugreportFile; // Return original.
}
}
@@ -281,4 +586,55 @@
return null;
}
}
+
+ /**
+ * Information about a bug report process while its in progress.
+ */
+ private static final class BugreportInfo {
+ /**
+ * {@code pid} of the {@code dumpstate} process generating the bug report.
+ */
+ final int pid;
+
+ /**
+ * Name of the bug report, will be used to rename the final files.
+ * <p>
+ * Initial value is the bug report filename reported by {@code dumpstate}, but user can
+ * change it later to a more meaningful name.
+ */
+ final String name;
+
+ /**
+ * Maximum progress of the bug report generation.
+ */
+ final int max;
+
+ /**
+ * Current progress of the bug report generation.
+ */
+ int progress;
+
+ /**
+ * Time of the last progress update.
+ */
+ long lastUpdate = System.currentTimeMillis();
+
+ BugreportInfo(int pid, String name, int max) {
+ this.pid = pid;
+ this.name = name;
+ this.max = max;
+ }
+
+ String getFormattedLastUpdate() {
+ return SimpleDateFormat.getDateTimeInstance().format(new Date(lastUpdate));
+ }
+
+ @Override
+ public String toString() {
+ final float percent = ((float) progress * 100 / max);
+ return String.format("Progress for %s (pid=%d): %d/%d (%2.2f%%) Last update: %s", name,
+ pid, progress, max, percent,
+ getFormattedLastUpdate());
+ }
+ }
}
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index f1da14d..5133162 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -17,6 +17,8 @@
package com.android.shell;
import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
+import static com.android.shell.BugreportProgressService.EXTRA_ORIGINAL_INTENT;
+import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
import static com.android.shell.BugreportProgressService.getFileExtra;
import java.io.File;
@@ -50,13 +52,16 @@
// Clean up older bugreports in background
cleanupOldFiles(intent);
- // Delegate to service.
+ // Delegate intent handling to service.
Intent serviceIntent = new Intent(context, BugreportProgressService.class);
- serviceIntent.putExtras(intent.getExtras());
+ serviceIntent.putExtra(EXTRA_ORIGINAL_INTENT, intent);
context.startService(serviceIntent);
}
private void cleanupOldFiles(Intent intent) {
+ if (!INTENT_BUGREPORT_FINISHED.equals(intent.getAction())) {
+ return;
+ }
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
final PendingResult result = goAsync();
new AsyncTask<Void, Void, Void>() {
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 1bdd9dd..33c4ef1 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -19,7 +19,12 @@
import static android.test.MoreAsserts.assertContainsRegex;
import static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
+import static com.android.shell.BugreportProgressService.EXTRA_MAX;
+import static com.android.shell.BugreportProgressService.EXTRA_NAME;
+import static com.android.shell.BugreportProgressService.EXTRA_PID;
import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
+import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
+import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
@@ -96,6 +101,33 @@
cancelExistingNotifications();
}
+ public void testFullWorkflow() throws Exception {
+ final String name = "BUG, Y U NO REPORT?";
+ // TODO: call method to remove property instead
+ SystemProperties.set("dumpstate.42.progress", "-1");
+
+ Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
+ intent.putExtra(EXTRA_PID, 42);
+ intent.putExtra(EXTRA_NAME, name);
+ intent.putExtra(EXTRA_MAX, 1000);
+ mContext.sendBroadcast(intent);
+
+ assertProgressNotification(name, "0.00%");
+
+ SystemProperties.set("dumpstate.42.progress", "108");
+ assertProgressNotification(name, "10.80%");
+
+ SystemProperties.set("dumpstate.42.progress", "500");
+ assertProgressNotification(name, "50.00%");
+
+ createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
+ createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
+ Bundle extras = sendBugreportFinishedIntent(42, PLAIN_TEXT_PATH, SCREENSHOT_PATH);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
+
+ // TODO: assert service is down
+ }
+
public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
@@ -131,13 +163,32 @@
}
}
+ private void assertProgressNotification(String name, String percent) {
+ // TODO: it current looks for 3 distinct objects, without taking advantage of their
+ // relationship.
+ String title = mContext.getString(R.string.bugreport_in_progress_title);
+ Log.v(TAG, "Looking for progress notification title: '" + title+ "'");
+ mUiBot.getNotification(title);
+ Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
+ mUiBot.getObject(name);
+ mUiBot.getObject(percent);
+ }
+
/**
* Sends a "bugreport finished" intent and waits for the result.
*
* @return extras sent to the bugreport finished consumer.
*/
private Bundle sendBugreportFinishedIntent(String bugreportPath, String screenshotPath) {
- Intent intent = new Intent("android.intent.action.BUGREPORT_FINISHED");
+ return sendBugreportFinishedIntent(null, bugreportPath, screenshotPath);
+ }
+
+ private Bundle sendBugreportFinishedIntent(Integer pid, String bugreportPath,
+ String screenshotPath) {
+ Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
+ if (pid != null) {
+ intent.putExtra(EXTRA_PID, pid);
+ }
if (bugreportPath != null) {
intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
}
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index f5dd31c..fa1714e 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -42,32 +42,49 @@
}
/**
- * Opens the system notification and clicks a given notification.
+ * Opens the system notification and gets a given notification.
*
* @param text Notificaton's text as displayed by the UI.
+ * @return notification object.
*/
- public void clickOnNotification(String text) {
+ public UiObject getNotification(String text) {
boolean opened = mDevice.openNotification();
Log.v(TAG, "openNotification(): " + opened);
boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGED)), mTimeout);
assertTrue("could not get system ui (" + SYSTEMUI_PACKAGED + ")", gotIt);
- gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout);
- assertTrue("object with text '(" + text + "') not visible yet", gotIt);
+ return getObject(text);
+ }
- UiObject notification = getVisibleObject(text);
-
+ /**
+ * Opens the system notification and clicks a given notification.
+ *
+ * @param text Notificaton's text as displayed by the UI.
+ */
+ public void clickOnNotification(String text) {
+ UiObject notification = getNotification(text);
click(notification, "bug report notification");
}
/**
- * Gets an object which is guaranteed to be present in the current UI.\
+ * Gets an object that might not yet be available in current UI.
+ *
+ * @param text Object's text as displayed by the UI.
+ */
+ public UiObject getObject(String text) {
+ boolean gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout);
+ assertTrue("object with text '(" + text + "') not visible yet", gotIt);
+ return getVisibleObject(text);
+ }
+
+ /**
+ * Gets an object which is guaranteed to be present in the current UI.
*
* @param text Object's text as displayed by the UI.
*/
public UiObject getVisibleObject(String text) {
UiObject uiObject = mDevice.findObject(new UiSelector().text(text));
- assertTrue("could not find object with text '(" + text + "')", uiObject.exists());
+ assertTrue("could not find object with text '" + text + "'", uiObject.exists());
return uiObject;
}
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 1e18523..7006d43 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skermvaspen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kon nie <xliff:g id="APP">%s</xliff:g> begin nie."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Meer"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Geskiedenis"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Verdeel horisontaal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verdeel vertikaal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Verdeel gepasmaak"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Herrangskik Kitsinstellings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Wys helderheid in Kitsinstellings"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Aktiveer oproep"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Aktiveer oproep deur die Oorsig-knoppie"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Aktiveer vinnige wissel"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Aktiveer beginuitteltyd terwyl daar opgeroep word"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Aktiveer volskerm-skermkiekies"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Aktiveer volskerm-skermkiekies in Oorsig"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimenteel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Skakel Bluetooth aan?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Jy moet Bluetooth aanskakel om jou sleutelbord aan jou tablet te koppel."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 8dae911..948c538 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"ተጨማሪ"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ታሪክ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"አግድም ክፈል"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ቁልቁል ክፈል"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"በብጁ ክፈል"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ፈጣን ቅንብሮችን ዳግም ያደራጁ"</string>
<string name="show_brightness" msgid="6613930842805942519">"በፈጣን ቅንብሮች ውስጥ ብሩህነትን አሳይ"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"ገጽ መስራትን አንቃ"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"በአጠቃላይ እይታ አዝራር በኩል ገጽ መስራትን አንቃ"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"ፈጣን ቅይይርን አንቃ"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"ገጽ እየሰራ ሳለ የማስጀመሪያ ጊዜ ማብቂያውን አንቃ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"የሙሉ ማያ ገጽ ቅጽበታዊ ገጽ እይታዎችን አንቃ"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"በአጠቃላይ እይታ ውስጥ የሙሉ ማያ ገጽ ቅጽበታዊ ገጽ እይታዎችን አንቃ"</string>
<string name="experimental" msgid="6198182315536726162">"የሙከራ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ብሉቱዝ ይብራ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"የቁልፍ ሰሌዳዎን ከእርስዎ ጡባዊ ጋር ለማገናኘት በመጀመሪያ ብሉቱዝን ማብራት አለብዎት።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b7d85b7..e272364 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -298,6 +298,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"تثبيت الشاشة"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"تعذر بدء <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"المزيد"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"السجلّ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسيم أفقي"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسيم رأسي"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"تقسيم مخصص"</string>
@@ -441,12 +443,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"إعادة ترتيب الإعدادات السريعة"</string>
<string name="show_brightness" msgid="6613930842805942519">"عرض السطوع في الإعدادات السريعة"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"تمكين الترحيل"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"تمكين الترحيل عبر زر \"نظرة عامة\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"تمكين التبديل السريع"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"تمكين مهلة الإطلاق أثناء الترحيل"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"تمكين اللقطات بملء الشاشة"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"تمكين اللقطات بملء الشاشة في النظرة العامة"</string>
<string name="experimental" msgid="6198182315536726162">"إعدادات تجريبية"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"تشغيل البلوتوث؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"لتوصيل لوحة المفاتيح بالجهاز اللوحي، يلزمك تشغيل بلوتوث أولاً."</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index b872db3..7f2a6b07 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sancağı"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"axtarış"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlana bilmir."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Daha çox"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Tarixçə"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Üfüqi Böl"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Şaquli Böl"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Fərdi Böl"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Sürətli Ayarları yenidən tənzimləyin"</string>
<string name="show_brightness" msgid="6613930842805942519">"Sürətli ayarlarda parlaqlılığı göstərin"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Səhifə nömrələməni aktiv edin"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Baxış düyməsi vasitəsilə səhifələməni aktiv edin"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Sürətli keçidi aktiv edin"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Səhifə nömrələyərkən işə salma vaxtının bitməsini aktiv edin"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Tam ekran ani görüntülərini aktiv edin"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Tam ekran ani görüntülərini İcmalda aktiv edin"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivləşsin?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Tabletinizlə klaviaturaya bağlanmaq üçün ilk olaraq Bluetooth\'u aktivləşdirməlisiniz."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index fd5ddbf..6ed2adb 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Още"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"История"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хоризонтално разделяне"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Вертикално разделяне"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Персонализирано разделяне"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Пренареждане на бързите настройки"</string>
<string name="show_brightness" msgid="6613930842805942519">"Показване на яркостта от бързите настройки"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Активиране на разделянето на страници"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Активиране на разделянето на страници чрез бутона за общ преглед"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Активиране на бързото превключване"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Активиране на времето за изчакване при стартиране за разделянето на страници"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Активиране на екранните снимки на цял екран"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Активиране на екранните снимки на цял екран в режима на общ преглед"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментални"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се включи ли Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"За да свържете клавиатурата с таблета си, първо трябва да включите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 442b179..20e2c35 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"স্ক্রীন পিন করা"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"আরো"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ইতিহাস"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"অনুভূমিক স্প্লিট"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"উল্লম্ব স্প্লিট"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"কাস্টম স্প্লিট করুন"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"দ্রুত সেটিংসে পুনরায় সাজান"</string>
<string name="show_brightness" msgid="6613930842805942519">"দ্রুত সেটিংসে উজ্জ্বলতা দেখান"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"পেজিং সক্ষম করুন"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"\'এক নজরে\' বোতামের মাধ্যমে পেজিং সক্ষম করুন"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"\'দ্রুত টগল করা\'র ব্যবস্থাটি সক্ষম করুন"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"পেজিং এর সময় \'লঞ্চ সময় সমাপ্ত\' সক্ষম করুন"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"পূর্ণস্ক্রীন স্ক্রীনশট সক্ষম করুন"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"\'এক নজরে\'র মধ্যে পূর্ণস্ক্রীন স্ক্রীনশট সক্ষম করুন"</string>
<string name="experimental" msgid="6198182315536726162">"পরীক্ষামূলক"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth চালু করবেন?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"আপনার ট্যাবলেটের সাথে আপনার কীবোর্ড সংযুক্ত করতে, আপনাকে প্রথমে Bluetooth চালু করতে হবে।"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index f67b425..0bb4826 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Més"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historial"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisió horitzontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisió vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisió personalitzada"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganitza Configuració ràpida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a Configuració ràpida"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Activa la paginació"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Activa la paginació mitjançant el botó Visió general"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Activa el canvi ràpid"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Activa el temps d\'espera de llançament durant la paginació"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Activa les captures de pantalla completa"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Activa les captures de pantalla completa a Visió general"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vols activar el Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 08d833e..63a16ad 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"připnutí obrazovky"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Další"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historie"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vodorovné rozdělení"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikální rozdělení"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Vlastní rozdělení"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Změnit uspořádání Rychlého nastavení"</string>
<string name="show_brightness" msgid="6613930842805942519">"Zobrazit jas v Rychlém nastavení"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Povolit stránkování"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Povolit stránkování pomocí tlačítka Přehled"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Povolit rychlé přepínání"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Povolit časový limit pro spuštění při stránkování"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Povolit snímky celé obrazovky"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Povolit snímky celé obrazovky v Přehledu"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentální"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnout Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Chcete-li klávesnici připojit k tabletu, nejdříve musíte zapnout Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 1fb1a51..eb8053d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"bliv i app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mere"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historik"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
<string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Aktivér sideopdeling"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Aktivér sideopdeling via knappen Oversigt"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Aktivér hurtigt skift"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Aktivér åbningstimeout ved sideinddeling"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Aktivér skærmbilleder i fuld størrelse"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Aktivér skærmbilleder i fuld størrelse i Oversigt"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a9196d6..e156c92 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Bildschirmfixierung"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mehr"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Verlauf"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Geteilte Schaltfläche – horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Geteilte Schaltfläche – vertikal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Geteilte Schaltfläche – benutzerdefiniert"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Schnelleinstellungen neu anordnen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Helligkeit in den Schnelleinstellungen anzeigen"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Paging aktivieren"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Paging über die Schaltfläche \"Übersicht\" aktivieren"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Schnelles Wechseln aktivieren"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Beim Paging Zeitlimit für Start aktivieren"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Vollbild-Screenshots aktivieren"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Vollbild-Screenshots in der Übersicht aktivieren"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentell"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivieren?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Zum Verbinden von Tastatur und Tablet muss Bluetooth aktiviert sein."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index e982df6..b0dcc40 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Περισσότερα"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Ιστορικό"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Οριζόντιος διαχωρισμός"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Κάθετος διαχωρισμός"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Προσαρμοσμένος διαχωρισμός"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Αναδιάταξη Γρήγορων ρυθμίσεων"</string>
<string name="show_brightness" msgid="6613930842805942519">"Εμφάνιση φωτεινότητας στις Γρήγορες ρυθμίσεις"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Ενεργοποίηση σελιδοποίησης"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Ενεργοποίηση σελιδοποίησης μέσω του κουμπιού \"Επισκόπηση\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Ενεργοποίηση γρήγορης εναλλαγής"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Ενεργοποίηση του χρονικού ορίου λήξης εκκίνησης κατά τη σελιδοποίηση"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Ενεργοποίηση στιγμιοτύπων πλήρους οθόνης"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Ενεργοποίηση των στιγμιοτύπων πλήρους οθόνης στην Προεπισκόπηση"</string>
<string name="experimental" msgid="6198182315536726162">"Σε πειραματικό στάδιο"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ενεργοποίηση Bluetooth;"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Για να συνδέσετε το πληκτρολόγιο με το tablet σας, θα πρέπει πρώτα να ενεργοποιήσετε το Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 32c486f..84f1785 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"More"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"History"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Enable paging"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Enable paging via the Overview button"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Enable fast toggle"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Enable launch timeout while paging"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Enable fullscreen screenshots"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Enable fullscreen screenshots in Overview"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 32c486f..84f1785 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"More"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"History"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Enable paging"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Enable paging via the Overview button"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Enable fast toggle"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Enable launch timeout while paging"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Enable fullscreen screenshots"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Enable fullscreen screenshots in Overview"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 32c486f..84f1785 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"More"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"History"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Enable paging"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Enable paging via the Overview button"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Enable fast toggle"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Enable launch timeout while paging"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Enable fullscreen screenshots"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Enable fullscreen screenshots in Overview"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 27451ec6..c9af193 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Más"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historial"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar la Configuración rápida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar el brillo en la Configuración rápida"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Habilitar paginación"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Habilita la paginación a través del botón Recientes"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Habilitar la activación rápida"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Habilita el tiempo de espera de inicio durante la paginación"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Habilitar capturas de pantalla en pantalla completa"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Habilita las capturas de pantalla en pantalla completa en Recientes"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar el teclado con la tablet, primero debes activar Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 1a7fea5..51984bf 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Más"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historial"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Ajustes rápidos"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Ajustes rápidos"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Habilitar paginación"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Habilitar paginación con el botón Visión general"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Habilitar activación rápida"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Habilitar tiempo de espera de lanzamiento durante paginación"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Habilitar capturas de pantalla completa"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Habilitar capturas de pantalla completa en Visión general"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para poder conectar tu teclado a tu tablet, debes activar el Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 1369252..b527b9f 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekraanikuva kinnitamine"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Rohkem"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Ajalugu"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horisontaalne poolitamine"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikaalne poolitamine"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Kohandatud poolitamine"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Korralda kiirseaded ümber"</string>
<string name="show_brightness" msgid="6613930842805942519">"Kuva kiirseadetes heledus"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Luba sirvimine"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Saate lubada sirvimise nupuga Ülevaade"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Luba kiire vahetamine"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Luba sirvimisel käivitamise ajalõpp"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Luba täisekraanil ekraanipildid"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Saate lubada lehel Ülevaade täisekraanil ekraanipildid"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentaalne"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Kas lülitada Bluetooth sisse?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviatuuri ühendamiseks tahvelarvutiga peate esmalt Bluetoothi sisse lülitama."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 6a5212e..b7cfb2a2 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Gehiago"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historia"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Banaketa horizontala"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Banaketa bertikala"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Banaketa pertsonalizatua"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Berrantolatu ezarpen bizkorrak"</string>
<string name="show_brightness" msgid="6613930842805942519">"Erakutsi distira Ezarpen bizkorretan"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Gaitu orriak pasatzeko aukera"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Gaitu ikuspegi orokorraren botoiaren bidez orriak pasatzeko aukera"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Gaitu bizkor aldatzeko aukera"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Gaitu orriak pasatu bitarteko abiarazteen denbora-muga"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Gaitu pantaila osoko pantaila-argazkiak"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Gaitu pantaila osoko pantaila-argazkiak ikuspegi orokorrean"</string>
<string name="experimental" msgid="6198182315536726162">"Esperimentala"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth eginbidea aktibatu nahi duzu?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Teklatua tabletara konektatzeko, Bluetooth eginbidea aktibatu behar duzu."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6bfef66..b3d8216 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"پین کردن صفحه"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> شروع نشد."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"بیشتر"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"سابقه"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسیم افقی"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسیم عمودی"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"سفارشی کردن تقسیم"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیههای ساعت را در نوار وضعیت نشان میدهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ترتیب مجدد در تنظیمات سریع"</string>
<string name="show_brightness" msgid="6613930842805942519">"نمایش روشنایی در تنظیمات سریع"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"فعال کردن صفحهبندی"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"فعال کردن صفحهبندی از طریق دکمه «نمای کلی»"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"فعال کردن جابهجایی سریع"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"فعال کردن مهلت زمانی راهاندازی هنگام صفحهبندی"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"فعال کردن عکسهای صفحهنمایش تمامصفحه"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"فعال کردن عکسهای صفحهنمایش تمامصفحه در مرور کلی"</string>
<string name="experimental" msgid="6198182315536726162">"آزمایشی"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوتوث روشن شود؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"برای مرتبط کردن صفحهکلید با رایانه لوحی، ابتدا باید بلوتوث را روشن کنید."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4d0debe..235eef0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Lisää"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historia"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vaakasuuntainen jako"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pystysuuntainen jako"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Muokattu jako"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Järjestä pika-asetukset uudelleen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Näytä kirkkaus pika-asetuksissa"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Ota sivutus käyttöön"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Ottaa sivutuksen käyttöön Yleiskatsaus-painikkeen avulla."</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Ota käyttöön nopea päälle/pois-toiminto."</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Ottaa käynnistyksen aikakatkaisun käyttöön sivutuksen aikana."</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Salli koko ruudun kuvakaappaukset"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Sallii koko ruudun kuvakaappaukset Viimeisimmät-näkymässä."</string>
<string name="experimental" msgid="6198182315536726162">"Kokeellinen"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Otetaanko Bluetooth käyttöön?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Jotta voit yhdistää näppäimistön tablettiisi, sinun on ensin otettava Bluetooth käyttöön."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 24a033f..3493067 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Plus"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historique"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser les paramètres rapides"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans les paramètres rapides"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Activer la mise en page"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Activer la mise en page à l\'aide du bouton Aperçu"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Activer le basculement rapide"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Activer le délai avant expiration du lancement pendant la mise en page"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Activer les saisies d\'écran plein écran"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Activer les saisies d\'écran plein écran dans Aperçu"</string>
<string name="experimental" msgid="6198182315536726162">"Fonctions expérimentales"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter votre clavier à votre tablette, vous devez d\'abord activer la connectivité Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d652251..ebed6e9 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Plus"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historique"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser la fenêtre de configuration rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Activer la mise en page"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Activer la mise en page via le bouton Aperçu"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Activer le basculement rapide"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Activer le délai avant expiration du lancement pendant la mise en page"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Activer les captures d\'écran en plein écran"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Activer les captures d\'écran en plein écran en mode Aperçu"</string>
<string name="experimental" msgid="6198182315536726162">"Paramètres expérimentaux"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer le Bluetooth ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 3a8b986..a9648b9 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Máis"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historial"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dividir en horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dividir en vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dividir de xeito personalizado"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Configuración rápida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Configuración rápida"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Activar paxinación"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Activar paxinación a través do botón Visión xeral"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Activar alternancia rápida"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Activa o tempo de espera do lanzamento durante a paxinación"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Activa as capturas de pantalla en pantalla completa"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Activa as capturas de pantalla en pantalla completa en Visión xeral"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Queres activar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teu teclado co tablet, primeiro tes que activar o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 86c1502..804a940 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"સ્ક્રીન પિનિંગ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"શોધ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> પ્રારંભ કરી શકાયું નથી."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"વધુ"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ઇતિહાસ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"આડું વિભક્ત કરો"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ઊભું વિભક્ત કરો"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"કસ્ટમ વિભક્ત કરો"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
<string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"પેજિંગ સક્ષમ કરો"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"વિહંગાવલોકન બટન મારફતે પેજિંગ સક્ષમ કરો"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"ઝડપી ટૉગલ સક્ષમ કરો"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"પેજિંગ વખતે લોંચ સમયસમાપ્તિ સક્ષમ કરો"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"પૂર્ણસ્ક્રીન સ્ક્રીનશોટ્સ સક્ષમ કરો"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"વિહંગાવલોકનમાં પૂર્ણસ્ક્રીન સ્ક્રીનશોટ્સ સક્ષમ કરો"</string>
<string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ચાલુ કરવુ છે?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં Bluetooth ચાલુ કરવાની જરૂર પડશે."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 834d025..354de04 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करना"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"अधिक"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"इतिहास"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज रूप से विभाजित करें"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"लम्बवत रूप से विभाजित करें"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"कस्टम रूप से विभाजित करें"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"त्वरित सेटिंग को पुन: व्यवस्थित करें"</string>
<string name="show_brightness" msgid="6613930842805942519">"त्वरित सेटिंग में स्क्रीन की रोशनी दिखाएं"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"पेजिंग सक्षम करें"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"अवलोकन बटन के माध्यम से पेजिंग सक्षम करें"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"तेज़ टॉगल सक्षम करें"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"पेजिंग के दौरान लॉन्च समयबाह्य सक्षम करें"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"पूर्णस्क्रीन स्क्रीनशॉट सक्षम करें"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"अवलोकन में पूर्ण स्क्रीनशॉट सक्षम करें"</string>
<string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index c929d9c..b35360e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -295,6 +295,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikvačivanje zaslona"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Više"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Povijest"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podijeli vodoravno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podijeli okomito"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podijeli prilagođeno"</string>
@@ -438,12 +440,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Promijeni raspored Brzih postavki"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaži svjetlinu u Brzim postavkama"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Omogući pregledavanje stranica"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Omogućivanje pregledavanja stranica gumbom Pregled"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Omogući brzo prebacivanje"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Omogućivanje vremenskog ograničenja pokretanja tijekom pregledavanja stranica"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Omogući snimanje cijelog zaslona"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Omogući snimanje cijelog zaslona u Pregledu"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li uključiti Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tipkovnicu s tabletom, morate uključiti Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 145d904..7956a21 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"képernyő rögzítése"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Továbbiak"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Előzmények"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Osztott vízszintes"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Osztott függőleges"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Osztott egyéni"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Gyorsbeállítások átrendezése"</string>
<string name="show_brightness" msgid="6613930842805942519">"Fényerő megjelenítése a gyorsbeállításokban"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Lapozás engedélyezése"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Lapozás engedélyezése az Áttekintés gombbal"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Gyors váltás engedélyezése"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Indítási időtúllépés engedélyezése lapozás közben"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Teljes képernyős képernyőképek engedélyezése"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Teljes képernyős képernyőképek engedélyezése Áttekintés módban"</string>
<string name="experimental" msgid="6198182315536726162">"Kísérleti"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Engedélyezi a Bluetooth-kapcsolatot?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ha a billentyűzetet csatlakoztatni szeretné táblagépéhez, először engedélyeznie kell a Bluetooth-kapcsolatot."</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 5a6ec62..de70fec 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Ավելին"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Պատմություն"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Հորիզոնական տրոհում"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ուղղահայաց տրոհում"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Հատուկ տրոհում"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Վերադասավորել Արագ կարգավորումները"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ցույց տալ պայծառությունն Արագ կարգավորումներում"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Միացնել թերթումը"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Միացնել Համատեսք կոճակի միջոցով թերթումը"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Միացնել արագ փոխարկումը"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Միացնել գործարկման ժամանակի սպառումը թերթելու ժամանակ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Միացնել էկրանի պատկերների լիաէկրան ցուցադրումը"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Միացնել էկրանի պատկերների լիաէկրան ցուցադրումը Համատեսքում"</string>
<string name="experimental" msgid="6198182315536726162">"Փորձնական"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Միացնե՞լ Bluetooth-ը:"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ստեղնաշարը ձեր պլանշետին միացնելու համար նախ անհրաժեշտ է միացնել Bluetooth-ը:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index cb2fe53..51ddcc0 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pin ke layar"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Lainnya"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Riwayat"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Pisahkan Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pisahkan Vertikal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pisahkan Khusus"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Atur Ulang Setelan Cepat"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tampilkan kecerahan di Setelan Cepat"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Aktifkan tampilan laman"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Mengaktifkan tampilan laman melalui tombol Ringkasan"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Mengaktifkan pengalih cepat"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Aktifkan waktu tunggu peluncuran saat menampilkan laman"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Aktifkan tangkapan layar untuk layar penuh"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Aktifkan tangkapan layar untuk layar penuh di Ringkasan"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Aktifkan Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menghubungkan keyboard dengan tablet, terlebih dahulu aktifkan Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 63a4fe8..20d8693 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Meira"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Ferill"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Lárétt skipting"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Lóðrétt skipting"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Sérsniðin skipting"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Endurraða flýtistillingum"</string>
<string name="show_brightness" msgid="6613930842805942519">"Sýna birtustig í flýtistillingum"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Kveikja á síðuskoðun"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Virkja síðuskoðun með yfirlitshnappinum"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Kveikja á flýtiskiptingum"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Kveikja á tímamörkum ræsingar þegar flett er"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Kveikja á skjámyndum sem fylla upp í skjáinn"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Kveikja á skjámyndum sem fylla upp í skjáinn í yfirliti"</string>
<string name="experimental" msgid="6198182315536726162">"Tilraunastillingar"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Kveikja á Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Til að geta tengt lyklaborðið við spjaldtölvuna þarftu fyrst að kveikja á Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 24bb49f3..87267995 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Altro"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Cronologia"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisione in orizzontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisione in verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisione personalizzata"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Riorganizza Impostazioni rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostra luminosità in Impostazioni rapide"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Attiva paging"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Attiva il paging tramite il pulsante Panoramica"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Abilita attivazione/disattivazione veloce"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Attiva timeout lancio durante il paging"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Attiva screenshot a schermo intero"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Attiva screenshot a schermo intero in Panoramica"</string>
<string name="experimental" msgid="6198182315536726162">"Sperimentali"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Attivare il Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connettere la tastiera al tablet, devi prima attivare il Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 54a9ffe..a28dc2a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"הצמדת מסך"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"לא ניתן היה להפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"עוד"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"היסטוריה"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"פיצול אופקי"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"פיצול אנכי"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"פיצול מותאם אישית"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"סידור מחדש של הגדרות מהירות"</string>
<string name="show_brightness" msgid="6613930842805942519">"הצג בהירות בהגדרות מהירות"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"אפשר דפדוף"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"הפעל דפדוף באמצעות לחצן הסקירה"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"הפעל החלפת מצב מהירה"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"אפשר זמן קצוב להפעלה במהלך הדפדוף"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"אפשר צילומי מסך במסך מלא"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"אפשר צילומי מסך במסך מלא ב\'סקירה\'"</string>
<string name="experimental" msgid="6198182315536726162">"ניסיוניות"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"האם להפעיל את ה-Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b0a1974..13217a0 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"もっと見る"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"履歴"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"横に分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"縦に分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"分割(カスタム)"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"クイック設定を並べ替え"</string>
<string name="show_brightness" msgid="6613930842805942519">"クイック設定に明るさ調整バーを表示する"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"ページ切り替えを有効にする"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"[概要] ボタンによるページ切り替えを有効にします"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"高速切り替えを有効にする"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"ページ切り替え中の起動タイムアウトを有効にします"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"全画面スクリーンショットを有効にする"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"[概要] で全画面スクリーンショットを有効にします"</string>
<string name="experimental" msgid="6198182315536726162">"試験運用版"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"BluetoothをONにしますか?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"タブレットでキーボードに接続するには、最初にBluetoothをONにする必要があります。"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index ce8b417..c4e84a8 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ეკრანზე ჩამაგრება"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"მეტი"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ისტორია"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ჰორიზონტალური გაყოფა"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ვერტიკალური გაყოფა"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ინდივიდუალური გაყობა"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"სწრაფი პარამეტრების გადაწყობა"</string>
<string name="show_brightness" msgid="6613930842805942519">"სიკაშკაშის ჩვენება სწრაფ პარამეტრებში"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"გვერდების გადაფურცვლის ჩართვა"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"მიმოხილვის ღილაკის მეშვეობით გვერდების გადაფურცვლის ჩართვა"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"სწრაფი გადართვის ჩართვა"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"გვერდების გადაფურცვლისას გაშვების დროის ლიმიტის ჩართვა"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"სრულეკრანიანი ეკრანის ანაბეჭდების ჩართვა"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"მიმოხილვაში სრულეკრანიანი ეკრანის ანაბეჭდების ჩართვა"</string>
<string name="experimental" msgid="6198182315536726162">"ექსპერიმენტული"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"გსურთ Bluetooth-ის ჩართვა?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"კლავიატურის ტაბლეტთან დასაკავშირებლად, ჯერ უნდა ჩართოთ Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 586b1bf9..2133170 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Қосымша"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Тарих"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Бөлінген көлденең"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Бөлінген тік"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Бөлінген теңшелетін"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Жылдам параметрлерді қайта реттеу"</string>
<string name="show_brightness" msgid="6613930842805942519">"Жылдам параметрлерде жарықтықты көрсету"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Беттерді аудару"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"\"Шолу\" түймесі арқылы беттерді аударуды қосу"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Тез ауыстырып қосуды қосу"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Беттерді аудару кезінде іске қосуды күту уақытын қосу"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Толық экрандық скриншоттарды қосу"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"\"Шолу\" ішінде толық экрандық скриншоттарды қосу"</string>
<string name="experimental" msgid="6198182315536726162">"Эксперименттік"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth функциясын қосу керек пе?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Пернетақтаны планшетке қосу үшін алдымен Bluetooth функциясын қосу керек."</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index f0f0d5f..6fbb325 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ការភ្ជាប់អេក្រង់"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"មិនអាចចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"ច្រើនទៀត"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ប្រវត្តិ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"បំបែកផ្តេក"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"បំបែកបញ្ឈរ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"បំបែកផ្ទាល់ខ្លួន"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"រៀបចំការកំណត់រហ័សឡើងវិញ"</string>
<string name="show_brightness" msgid="6613930842805942519">"បង្ហាញកម្រិតពន្លឺនៅក្នុងការកំណត់រហ័ស"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"បើកដំណើរការចុះទំព័រ"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"បើកដំណើការចុះទំព័រតាមរយៈប៊ូតុងទិដ្ឋភាព"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"បើកដំណើរការបិទ/បើករហ័ស"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"បើកដំណើរការអស់ពេលចាប់ផ្តើមខណៈពេលចុះទំព័រ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"បើកដំណើរការរូបថតអេក្រង់ពេញអេក្រង់"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"បើកដំណើរការរូបថតអេក្រង់ពេញអេក្រង់នៅក្នុងទិដ្ឋភាព"</string>
<string name="experimental" msgid="6198182315536726162">"ពិសោធន៍"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"បើកប៊្លូធូសឬ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ដើម្បីភ្ជាប់ក្តារចុចរបស់អ្នកជាមួយនឹងថេប្លេតរបស់អ្នក អ្នកត្រូវតែបើកប៊្លូធូសជាមុនសិន។"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 9dec425..c8fc91d 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ಸ್ಕ್ರೀನ್ ಪಿನ್ನಿಂಗ್"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"ಇನ್ನಷ್ಟು"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ಇತಿಹಾಸ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ಅಡ್ಡಲಾಗಿ ವಿಭಜಿಸಿದ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ಲಂಬವಾಗಿ ವಿಭಜಿಸಿದ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ಕಸ್ಟಮ್ ವಿಭಜಿಸಿದ"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
<string name="show_brightness" msgid="6613930842805942519">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಪ್ರಖರತೆಯನ್ನು ತೋರಿಸಿ"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"ಪೇಜಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"ಸಮಗ್ರ ನೋಟದ ಬಟನ್ ಮೂಲಕ ಪೇಜಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"ವೇಗವಾಗಿ ಟಾಗಲ್ ಮಾಡುವಿಕೆ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"ಪೇಜಿಂಗ್ ಸಂದರ್ಭದಲ್ಲಿ ಪ್ರಾರಂಭಿಸುವಿಕೆ ಕಾಲಾವಧಿಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"ಪೂರ್ಣ ಪರದೆ ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"ಸಮಗ್ರ ನೋಟದಲ್ಲಿ ಪೂರ್ಣ ಪರದೆ ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="experimental" msgid="6198182315536726162">"ಪ್ರಾಯೋಗಿಕ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡುವುದೇ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್ಗೆ ಸಂಪರ್ಕಿಸಲು, ನೀವು ಮೊದಲು ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 126d84a8..1296d21 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"더보기"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"기록"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"수평 분할"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"수직 분할"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"맞춤 분할"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"빠른 설정 재정렬"</string>
<string name="show_brightness" msgid="6613930842805942519">"빠른 설정에서 밝기 표시"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"페이징을 사용 설정합니다."</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"최근 사용 버튼을 통해 페이징 사용"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"빠른 전환 사용"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"페이징하는 동안 실행 제한시간을 사용 설정합니다."</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"전체 화면 스크린샷을 사용 설정합니다."</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"최근 사용에서 전체 화면 스크린샷을 사용 설정합니다."</string>
<string name="experimental" msgid="6198182315536726162">"베타"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"블루투스를 켜시겠습니까?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"키보드를 태블릿에 연결하려면 먼저 블루투스를 켜야 합니다."</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 1be6f05..ead55c7 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Дагы"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Таржымал"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Туурасынан бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Тигинен бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ыңгайлаштырылган бөлүү"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ыкчам жөндөөлөрдү кайра коюу"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ыкчам жөндөөлөрдөн жарык деңгээлин көрсөтүү"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Барактоону иштетүү"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Сереп баскычы менен барактоону иштетүү"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Тез которгучту иштетүү"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Барактап жатканда таймаутту иштетүү"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Толук экран скриншотторун иштетүү"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Толук экран скриншотторун Серепте иштетүү"</string>
<string name="experimental" msgid="6198182315536726162">"Сынамык"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth күйгүзүлсүнбү?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Баскычтобуңузду планшетиңизге туташтыруу үчүн, адегенде Bluetooth\'ту күйгүзүшүңүз керек."</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 2fac9b9..c0689c3 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ການປັກໝຸດໜ້າຈໍ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"ບໍ່ສາມາດເລີ່ມ <xliff:g id="APP">%s</xliff:g> ໄດ້."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"ເພີ່ມເຕີມ"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ປະຫວັດ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ການແຍກລວງຂວາງ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ການແຍກລວງຕັ້ງ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ການແຍກກຳນົດເອງ"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ສະແດງວິນາທີໂມງຢູ່ໃນແຖບສະຖານະ. ອາດຈະມີຜົນກະທົບຕໍ່ອາຍຸແບັດເຕີຣີ."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ຈັດວາງການຕັ້ງຄ່າດ່ວນຄືນໃໝ່"</string>
<string name="show_brightness" msgid="6613930842805942519">"ສະແດງຄວາມແຈ້ງຢູ່ໃນການຕັ້ງຄ່າດ່ວນ"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"ເປີດໃຊ້ງານການແບ່ງໜ້າ"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"ເປີດນຳໃຊ້ການແບ່ງໜ້າຜ່ານປຸ່ມພາບລວມ"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"ເປີດນຳໃຊ້ການສັບປ່ຽນໄວ"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"ເປີດໃຊ້ງານການໝົດເວລາການເປີດໃຊ້ ໃນຂະນະທີ່ແບ່ງໜ້າ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"ເປີດໃຊ້ງານພາບໜ້າຈໍແບບເຕັມຈໍ"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"ເປີດໃຊ້ງານພາບໜ້າຈໍແບບເຕັມຈໍໃນໂໝດພາບລວມ"</string>
<string name="experimental" msgid="6198182315536726162">"ຍັງຢູ່ໃນການທົດລອງ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ເປີດໃຊ້ Bluetooth ບໍ່?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ເພື່ອເຊື່ອມຕໍ່ແປ້ນພິມຂອງທ່ານກັບແທັບເລັດຂອງທ່ານ, ກ່ອນອື່ນໝົດທ່ານຕ້ອງເປີດ Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 1533ae8d..4425d31 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Daugiau"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Istorija"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontalus skaidymas"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikalus skaidymas"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tinkintas skaidymas"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Pertvarkyti sparčiuosius nustatymus"</string>
<string name="show_brightness" msgid="6613930842805942519">"Rodyti skaistį sparčiuosiuose nustatymuose"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Įgalinti puslapių kaitą"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Įgalinti puslapių kaitą apžvalgos mygtuku"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Įgalinti greitą perjungimą"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Įgalinti paleidimo skirtąjį laiką keičiant puslapius"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Įgalinti viso ekrano kopijas"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Įgalinti viso ekrano kopijas apžvalgoje"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentinė versija"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Įjungti „Bluetooth“?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Kad galėtumėte prijungti klaviatūrą prie planšetinio kompiuterio, pirmiausia turite įjungti „Bluetooth“."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 3479320..eca57a6 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -295,6 +295,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Vairāk"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Vēsture"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontāls dalījums"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikāls dalījums"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pielāgots dalījums"</string>
@@ -438,12 +440,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Pārkārtot ātros iestatījumus"</string>
<string name="show_brightness" msgid="6613930842805942519">"Rādīt spilgtumu ātrajos iestatījumos"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Iespējot lapošanu"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Iespējot lapošanu, izmantojot pogu Pārskats"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Iespējot ātro pārslēgšanu"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Iespējot palaišanas noildzi lapošanas laikā"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Iespējot pilnekrāna ekrānuzņēmumus"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Iespējot pilnekrāna ekrānuzņēmumus sadaļā Pārskats"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentāli"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vai ieslēgt Bluetooth savienojumu?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Lai pievienotu tastatūru planšetdatoram, vispirms ir jāieslēdz Bluetooth savienojums."</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 277a519..038c669 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"прикачување екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Повеќе"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Историја"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Раздели хоризонтално"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Раздели вертикално"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Раздели прилагодено"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Преуредете ги Брзи поставки"</string>
<string name="show_brightness" msgid="6613930842805942519">"Прикажете ја осветленоста во Брзи поставки"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Овозможете прелистување страници"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Овозможете прелистување страници со копчето Краток преглед"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Овозможете брзо префрлање"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Овозможете истек на време при стартување додека прелистувате страници"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Овозможете слики од цел екран"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Овозможете слики од цел екран во Преглед"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се вклучи Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"За да ја поврзете тастатурата со таблетот, најпрво треба да вклучите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index a448d9b..f4964d0 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"കൂടുതൽ"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ചരിത്രം"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"തിരശ്ചീനമായി വേർതിരിക്കുക"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ലംബമായി വേർതിരിക്കുക"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ഇഷ്ടാനുസൃതമായി വേർതിരിക്കുക"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ദ്രുത ക്രമീകരണം പുനഃസജ്ജീകരിക്കുക"</string>
<string name="show_brightness" msgid="6613930842805942519">"ദ്രുത ക്രമീകരണത്തിൽ തെളിച്ചം കാണിക്കുക"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"പേജിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"ചുരുക്കവിവരണ ബട്ടൺ വഴി പേജിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"അതിവേഗ ടോഗിൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"പേജിംഗിനിടെ ലോഞ്ച് ടൈമൗട്ട് പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"പൂർണ്ണസ്ക്രീൻ സ്ക്രീൻഷോട്ടുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"ചുരുക്കവിവരണത്തിൽ പൂർണ്ണസ്ക്രീൻ സ്ക്രീൻഷോട്ടുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="experimental" msgid="6198182315536726162">"പരീക്ഷണാത്മകം!"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ഓണാക്കണോ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"നിങ്ങളുടെ ടാബ്ലെറ്റുമായി കീബോർഡ് കണക്റ്റുചെയ്യുന്നതിന്, ആദ്യം Bluetooth ഓണാക്കേണ്ടതുണ്ട്."</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 8dcb6d98..122068c 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -292,6 +292,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"дэлгэц тогтоох"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Илүү"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Түүх"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хэвтээ чиглэлд хуваах"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Босоо чиглэлд хуваах"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Хүссэн хэлбэрээр хуваах"</string>
@@ -435,12 +437,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Түргэн тохиргоог дахин засварлах"</string>
<string name="show_brightness" msgid="6613930842805942519">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Өгөгдөл хадгалах/сэргээхийг идэвхжүүлэх"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Тойм товчлуурыг ашиглан өгөгдөл хадгалах/сэргээхийг идэвхжүүлэх"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Түргэн унтраах/асаахыг идэвхжүүлэх"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Өгөгдөл хадгалах/сэргээх явцад завсарлагыг эхлүүлэх"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Бүтэн дэлгэцийн дэлгэцийн агшинг идэвхжүүлэх"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Тойм хэсэгт бүтэн дэлгэцийн \"Дэлгэцийн агшинг\" идэвхжүүлэх"</string>
<string name="experimental" msgid="6198182315536726162">"Туршилтын"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth-г асаах уу?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 00c4965..6415adb 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करणे"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"अधिक"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"इतिहास"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज विभाजित करा"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"अनुलंब विभाजित करा"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"सानुकूल विभाजित करा"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्ये घड्याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्य प्रभावित होऊ शकते."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिंग्जची पुनर्रचना करा"</string>
<string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिंग्जमध्ये चमक दर्शवा"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"लिखाण सक्षम करा"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"विहंगावलोकन बटणाद्वारे लिखाण सक्षम करा"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"जलद टॉगल करा सक्षम करा"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"लिखाण करताना लाँच कालबाह्य सक्षम करा"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"पूर्ण स्क्रीन स्क्रीनशॉट सक्षम करा"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"विहंगावलोकनामध्ये पूर्ण स्क्रीन स्क्रीनशॉट सक्षम करा"</string>
<string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटुथ सुरू करायचे?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड आपल्या टॅब्लेटसह कनेक्ट करण्यासाठी, आपल्याला प्रथम ब्लूटुथ चालू करणे आवश्यक आहे."</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 7b53a6c..ceefc29 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Lagi"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Sejarah"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Mendatar Terpisah"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Menegak Terpisah"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tersuai Terpisah"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Susun Semula Tetapan Pantas"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tunjukkan kecerahan dalam Tetapan Pantas"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Dayakan penghalamanan"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Mendayakan penghalamanan melalui butang Ikhtisar"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Dayakan togol pantas"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Membolehkan pelancaran tamat masa semasa penghalamanan"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Dayakan tangkapan skrin skrin penuh"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Mendayakan tangkapan skrin skrin penuh dalam Ikhtisar"</string>
<string name="experimental" msgid="6198182315536726162">"Percubaan"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Hidupkan Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menyambungkan papan kekunci anda dengan tablet, anda perlu menghidupkan Bluetooth terlebih dahulu."</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 2f52a02..81c0932 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"နောက်ထပ်"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"မှတ်တမ်း"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ရေပြင်ညီ ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ဒေါင်လိုက်ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"စိတ်ကြိုက် ပိုင်းမည်"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"အမြန် ဆက်တင်များကို ပြန်စီစဉ်ရန်"</string>
<string name="show_brightness" msgid="6613930842805942519">"အမြန် ဆက်တင်များထဲက တောက်ပမှုကို ပြရန်"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"စာမျက်နှာပြောင်းမှု ဖွင့်ပါ"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"အနှစ်ချုပ်ကြည့်မှု မှတစ်ဆင့် စာမျက်နှာပြောင်းမှုကို ဖွင့်ပါ"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"အမြန်ဖွင့်/ပိတ်ခြင်း ဖွင့်ရန်"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"စာမျက်နှာပြောင်းမှု ဖွင့်တင်ရန်အတွက် ကန့်သတ်ချိန်ကို ဖွင့်ပါ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"မျက်နှာပြင်အပြည့် လျှပ်တစ်ပြက်ပုံများကို ဖွင့်ပါ"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"အနှစ်ချုပ်ကြည့်မှုထဲတွင် မျက်နှာပြင်အပြည့် လျှပ်တစ်ပြက်ပုံများကို ဖွင့်ပါ"</string>
<string name="experimental" msgid="6198182315536726162">"စမ်းသပ်ရေး"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ဘလူးတုသ် ဖွင့်ရမလား။"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ကီးဘုတ်ကို တပ်ဘလက်နှင့် ချိတ်ဆက်ရန်၊ ပမထဦးစွာ ဘလူးတုသ်ကို ဖွင့်ပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 014a6b1..7f6895e 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mer"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Logg"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Del horisontalt"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Del vertikalt"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Del tilpasset"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Omorganiser hurtiginnstillingene"</string>
<string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i hurtiginnstillingene"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Slå på paginering"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Slå på paginering via Oversikt-knappen"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Slå på hurtigveksling"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Slå på tidsavbrudd mens paginering pågår"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Slå på skjermdumper av fullskjerm"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Slå på skjermdumper av fullskjerm i Oversikt"</string>
<string name="experimental" msgid="6198182315536726162">"På forsøksstadiet"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå på Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"For å koble tastaturet til nettbrettet ditt må du først slå på Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 46fce99..51e8a16 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रिन पिन गर्दै"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"थप"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"इतिहास"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अनुकूलन विभाजन गर्नुहोस्"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
<string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"पेजिंग सक्रिय गर्नुहोस्"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"परिदृश्य बटन मार्फत पेजिङ सक्रिय गर्नुहोस्"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"छिटो टगल सक्रिय गर्नुहोस्"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"जब पेजिंग हुन्छ टाइमआउट प्रक्षेपण सक्रिय गर्नुहोस्"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"पूर्ण स्क्रिन स्क्रीनशटहरू सक्रिय गर्नुहोस्"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"परिदृश्यमा पूर्ण स्क्रिन स्क्रीनशटहरू सक्रिय गर्नुहोस्"</string>
<string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लुटुथ सक्रिय पार्ने हो?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"आफ्नो ट्याब्लेटसँग किबोर्ड जोड्न, पहिले तपाईँले ब्लुटुथ सक्रिय गर्नुपर्छ।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index dbcaab8..88d0b4b 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -283,7 +283,7 @@
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zaklamp"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobiele gegevens"</string>
- <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Gegevensgebruik"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datagebruik"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende gegevens"</string>
<string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limiet overschreden"</string>
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> gebruikt"</string>
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"scherm vastzetten"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Meer"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Geschiedenis"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontaal splitsen"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verticaal splitsen"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Aangepast splitsen"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Snelle instellingen opnieuw indelen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Helderheid weergeven in Snelle instellingen"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Paginering inschakelen"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Paginering via de knop Overzicht inschakelen"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Snel schakelen inschakelen"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Starttime-out tijdens paginering inschakelen"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Screenshots op volledig scherm inschakelen"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Screenshots op volledig scherm in Overzicht inschakelen"</string>
<string name="experimental" msgid="6198182315536726162">"Experimenteel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth inschakelen?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Als je je toetsenbord wilt verbinden met je tablet, moet je eerst Bluetooth inschakelen."</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 5f21e94..df6c473af 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ਸਕ੍ਰੀਨ ਪਿਨਿੰਗ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ਖੋਜੋ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਚਾਲੂ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"ਹੋਰ"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ਇਤਿਹਾਸ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ਵਰਟੀਕਲ ਸਪਲਿਟ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਕਸਟਮ ਸਪਲਿਟ"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
<string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"ਪੇਜਿੰਗ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"ਰੂਪ-ਰੇਖਾ ਬਟਨ ਦੁਆਰਾ ਪੇਜਿੰਗ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"ਤੇਜ਼ ਬਦਲੋ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"ਪੇਜਿੰਗ ਦੌਰਾਨ ਲਾਂਚ ਸਮਾਂ ਸਮਾਪਤੀ ਦੀ ਮਿਅਾਦ ਯੋਗ ਬਣਾਓ"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"ਪੂਰੀ-ਸਕਰੀਨ ਸਕਰੀਨਸ਼ਾਟ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"ਰੂਪ-ਰੇਖਾ ਵਿੱਚ ਪੂਰੀ-ਸਕਰੀਨ ਸਕਰੀਨਸ਼ਾਟ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
<string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ਚਾਲੂ ਕਰੋ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ਆਪਣੇ ਟੈਬਲੇਟ ਨਾਲ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਕਨੈਕਟ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ Bluetooth ਚਾਲੂ ਕਰਨ ਦੀ ਜ਼ਰੂਰਤ ਹੈ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 68816ef..694132b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Więcej"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historia"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podziel poziomo"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podziel pionowo"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podziel niestandardowo"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Uporządkuj Szybkie ustawienia"</string>
<string name="show_brightness" msgid="6613930842805942519">"Pokaż jasność w Szybkich ustawieniach"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Włącz stronicowanie"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Włącz stronicowanie za pomocą przycisku Przegląd"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Włącz szybkie przełączanie"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Włącz limit czasu uruchomienia podczas stronicowania"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Włącz pełnoekranowe zrzuty ekranu"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Włącz pełnoekranowe zrzuty ekranu w widoku Przegląd"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperymentalne"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Włączyć Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Aby połączyć klawiaturę z tabletem, musisz najpierw włączyć Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c875922..e806bfc 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mais"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Histórico"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Ativar paginação"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Ativar paginação pelo botão \"Visão geral\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Ativar alternância rápida"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Ativar tempo limite de inicialização ao fazer paginação"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Ativar capturas de tela em tela cheia"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Ativar capturas de tela em tela cheia em \"Visão geral\""</string>
<string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 1594dca..468c75d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação no ecrã"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mais"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Histórico"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar as Definições rápidas"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar luminosidade nas Definições rápidas"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Ativar a paginação"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Ativar a paginação através do botão Vista geral"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Ativar alternância rápida"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Ativar o limite de tempo de lançamento durante a paginação"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Ativar capturas de ecrã inteiro"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Ativar capturas de ecrã inteiro na Vista geral"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Pretende ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para ligar o teclado ao tablet, tem de ativar primeiro o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c875922..e806bfc 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mais"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Histórico"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Ativar paginação"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Ativar paginação pelo botão \"Visão geral\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Ativar alternância rápida"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Ativar tempo limite de inicialização ao fazer paginação"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Ativar capturas de tela em tela cheia"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Ativar capturas de tela em tela cheia em \"Visão geral\""</string>
<string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ab182a2..1b8e8de 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -295,6 +295,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mai mult"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Istoric"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divizare pe orizontală"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divizare pe verticală"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divizare personalizată"</string>
@@ -438,12 +440,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearanjați Setările rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afișați luminozitatea în Setările rapide"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Activați paginarea"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Activați paginarea prin butonul Recente"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Activați comutarea rapidă"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Activați timpul limită pentru lansare în timpul paginării"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Activați capturile de ecran pe ecran complet"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Activați capturile de ecran pe ecran complet în modul Prezentare generală"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentale"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activați Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pentru a conecta tastatura la tabletă, mai întâi trebuie să activați Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ecacd4b..9068e0b 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Ещё"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Журнал"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Разделить по горизонтали"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Разделить по вертикали"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Разделить по-другому"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Изменить порядок Быстрых настроек"</string>
<string name="show_brightness" msgid="6613930842805942519">"Добавить яркость в Быстрые настройки"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Включить подкачку страниц"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Разрешить подкачку страниц с помощью кнопки \"Обзор\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Быстрое переключение"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Включить тайм-аут запуска при подкачке страниц"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Разрешить скриншоты всего экрана"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Разрешить скриншоты всего экрана в режиме обзора"</string>
<string name="experimental" msgid="6198182315536726162">"Экспериментальная функция"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Подключение по Bluetooth"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Чтобы подключить клавиатуру к планшету, включите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index a8f9469..3be3718 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"තවත්"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ඉතිහාසය"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"තිරස්ව වෙන් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"සිරස්ව වෙන් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"අභිමත ලෙස වෙන් කරන්න"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ඉක්මන් සැකසීම් යළි පිළිවෙළට සකසන්න"</string>
<string name="show_brightness" msgid="6613930842805942519">"ඉක්මන් සැකසීම්වල දීප්තිය පෙන්වන්න"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"පේජින් සබල කිරීම"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"දළ විශ්ලේෂණ බොත්තම හරහා පේජින් සබල කිරීම"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"වේගවත් ටොගල කිරීම සබල කරන්න"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"පේජින් අතරතුර දියත් කිරීමේ කාල නිමාව සබල කිරීම"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"පූර්ණ තිරයේ තිර රූ සබල කිරීම"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"දළ විශ්ලේෂණය තුළ පූර්ණ තිරයේ තිර රූ සබල කිරීම"</string>
<string name="experimental" msgid="6198182315536726162">"පරීක්ෂණාත්මක"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"බ්ලූටූත් ක්රියාත්මක කරන්නද?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ඔබේ යතුරු පුවරුව ඔබේ ටැබ්ලට් පරිගණකයට සම්බන්ධ කිරීමට, ඔබ පළමුව බ්ලූටූත් ක්රියාත්මක කළ යුතුය."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index bd7e210..d96194c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripnutie k obrazovke"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Viac"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"História"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Rozdeliť vodorovné"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Rozdeliť zvislé"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Rozdeliť vlastné"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Zmeniť usporiadanie Rýchlych nastavení"</string>
<string name="show_brightness" msgid="6613930842805942519">"Zobraziť jas v Rýchlych nastaveniach"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Povoliť prechádzanie po stranách"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Povoľte prechádzanie po stranách prostredníctvom tlačidla Prehľad"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Povoliť rýchle prepínanie"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Povolenie časového limitu pre spustenie počas prechádzania po stranách"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Povoliť snímky celej obrazovky"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Povolenie snímok celej obrazovky v Prehľade"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentálne"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnúť Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ak chcete klávesnicu pripojiť k tabletu, najprv musíte zapnúť Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6d7fbc0..f3d3b39 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripenjanje zaslona"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Več"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Zgodovina"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Razdeli vodoravno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Razdeli navpično"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Razdeli po meri"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Preuredi hitre nastavitve"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaz svetlosti v hitrih nastavitvah"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Omogočanje pregleda strani"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Omogoči pregled strani z gumbom za pregled"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Omogoči hiter preklop"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Omogoči potek časovne omejitve za odpiranje med pregledom strani"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Omogočanje celozaslonskih posnetkov zaslona"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Omogoči celozaslonske posnetke zaslona v Pregledu"</string>
<string name="experimental" msgid="6198182315536726162">"Poskusno"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite vklopiti Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Če želite povezati tipkovnico in tablični računalnik, vklopite Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 38066be..afad772 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"gozhdimi i ekranit"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"kërko"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nuk mundi të nisej."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Më shumë"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historiku"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Ndaje horizontalisht"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ndaj vertikalisht"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ndaj të personalizuarën"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
<string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Aktivizo shfletimin"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Aktivizo shfletimin me butonin \"Përmbledhja\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Aktivizo ndërrimin e shpejtë"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Aktivizo kohën e pritjes të nisjes gjatë shfletimit"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Aktivizo pamjet e ekranit në ekranin e plotë"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Aktivizo pamjet e ekranit në ekranin e plotë te \"Përmbledhja\""</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Të aktivizohet \"bluetooth-i\"?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Për të lidhur tastierën me tabletin, në fillim duhet të aktivizosh \"bluetooth-in\"."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 5fd78f0..ad14d26 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -295,6 +295,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Још"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Историја"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Подели хоризонтално"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Подели вертикално"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Прилагођено дељење"</string>
@@ -438,12 +440,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Преуреди Брза подешавања"</string>
<string name="show_brightness" msgid="6613930842805942519">"Прикажи осветљеност у Брзим подешавањима"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Омогући листање"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Омогућава листање помоћу дугмета Преглед"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Омогући брзо листање"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Омогућава временско ограничење покретања при листању"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Омогући снимке екрана преко целог екрана"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Омогућава снимке екрана преко целог екрана у Прегледу"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Желите ли да укључите Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Да бисте повезали тастатуру са таблетом, прво морате да укључите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index bec7593..15e8b12 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mer"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historik"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ordna snabbinställningarna"</string>
<string name="show_brightness" msgid="6613930842805942519">"Visa ljusstyrka i snabbinställningarna"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Aktivera sidindelning"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Aktivera sidindelning via knappen Översikt"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Aktivera snabb aktivering och inaktivering"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Aktivera timeout i lanseringen vid sidindelning"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Aktivera skärmdumpar på helskärm"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Aktivera skärmdumpar på helskärm i översikten"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentella"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vill du aktivera Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Om du vill ansluta tangentbordet till surfplattan måste du först aktivera Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8cc6712..1d231fc 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Zaidi"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Historia"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gawanya Mlalo"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Gawanya Wima"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Maalum Iliyogawanywa"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Panga Upya Mipangilio ya Haraka"</string>
<string name="show_brightness" msgid="6613930842805942519">"Onyesha unga\'avu katika Mipangilio ya Haraka"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Washa kipengee cha kupata kumbukumbu"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Washa kipengee cha kupata kumbukumbu kupitia kitufe cha Muhtasari"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Washa kugeuza haraka"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Washa kipengee cha kuisha kwa muda wa uzinduzi unapopata kumbukumbu"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Washa picha za skrini nzima"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Washa picha za skrini nzima katika Muhtasari"</string>
<string name="experimental" msgid="6198182315536726162">"Ya majaribio"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Je, ungependa kuwasha Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ili uunganishe Kibodi yako kwenye kompyuta yako kibao, lazima kwanza uwashe Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 5896c3001..c41494b 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"மேலும்"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"வரலாறு"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"கிடைமட்டமாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"செங்குத்தாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"தனிவிருப்பத்தில் பிரி"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"விரைவு அமைப்புகளை மறுவரிசைப்படுத்து"</string>
<string name="show_brightness" msgid="6613930842805942519">"விரைவு அமைப்புகளில் ஒளிர்வுப் பட்டியைக் காட்டு"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"பேஜிங்கை இயக்கு"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"மேலோட்டப் பார்வை பொத்தான் வழியாக பேஜிங்கை இயக்கு"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"வேகமாக மாறுவதை இயக்கு"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"பேஜிங்கின் போது தொடக்க நேர முடிவை இயக்கு"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"முழுத்திரை ஸ்கிரீன் ஷாட்களை இயக்கு"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"மேலோட்டப் பார்வையில் முழுத்திரை ஸ்கிரீன் ஷாட்களை இயக்கு"</string>
<string name="experimental" msgid="6198182315536726162">"சோதனை முயற்சி"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"புளூடூத்தை இயக்கவா?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"உங்கள் டேப்லெட்டுடன் விசைப்பலகையை இணைக்க, முதலில் புளூடூத்தை இயக்க வேண்டும்."</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index dccac8b..a628ef7 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"స్క్రీన్ పిన్నింగ్"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"మరింత"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"చరిత్ర"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"సమతలంగా విభజించు"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"లంబంగా విభజించు"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"అనుకూలంగా విభజించు"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"శీఘ్ర సెట్టింగ్ల ఏర్పాటు క్రమం మార్చు"</string>
<string name="show_brightness" msgid="6613930842805942519">"శీఘ్ర సెట్టింగ్ల్లో ప్రకాశం చూపు"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"పేజింగ్ను ప్రారంభించు"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"స్థూలదృష్టి బటన్ ద్వారా పేజింగ్ను ప్రారంభిస్తుంది"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"వేగవంతమైన టోగుల్ను ప్రారంభించు"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"పేజింగ్ చేస్తున్నప్పుడు గడువు ముగింపు లాంచ్ చేయిని ప్రారంభిస్తుంది"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"పూర్తి స్క్రీన్ స్క్రీన్షాట్లను ప్రారంభించండి"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"స్థూలదృష్టిలో పూర్తి స్క్రీన్ స్క్రీన్షాట్లను ప్రారంభిస్తుంది"</string>
<string name="experimental" msgid="6198182315536726162">"ప్రయోగాత్మకం"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"బ్లూటూత్ ఆన్ చేయాలా?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"మీ కీబోర్డ్ను మీ టాబ్లెట్తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 625b676..44ad1fa 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"การตรึงหน้าจอ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"เพิ่มเติม"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"ประวัติ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"แยกในแนวนอน"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"แยกในแนวตั้ง"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"แยกแบบกำหนดเอง"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"จัดเรียงการตั้งค่าด่วนใหม่"</string>
<string name="show_brightness" msgid="6613930842805942519">"แสดงความสว่างในการตั้งค่าด่วน"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"เปิดใช้การสลับหน้า"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"เปิดใช้การสลับหน้าผ่านทางปุ่มภาพรวม"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"เปิดใช้การสลับแบบด่วน"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"เปิดใช้ระยะหมดเวลาการเปิดขณะสลับหน้า"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"เปิดใช้ภาพหน้าจอแบบเต็มจอ"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"เปิดใช้ภาพหน้าจอแบบเต็มจอใน \"ภาพรวม\""</string>
<string name="experimental" msgid="6198182315536726162">"ทดสอบ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"เปิดบลูทูธไหม"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"หากต้องการเชื่อมต่อแป้นพิมพ์กับแท็บเล็ต คุณต้องเปิดบลูทูธก่อน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e3b8e24..c1bb85c 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pagpi-pin sa screen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Higit pa"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"History"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ayusing Muli ang Mga Mabilisang Setting"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ipakita ang liwanag sa Mga Mabilisang Setting"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"I-enable ang paging"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"I-enable ang paging sa pamamagitan ng button na Pangkalahatang-ideya"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"I-enable ang mabilis na pag-toggle"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"I-enable ang pag-timeout ng paglunsad habang nagsasagawa ng paging"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"I-enable ang mga fullscreen na screenshot"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"I-enable ang mga fullscreen na screenshot sa Pangkalahatang-ideya"</string>
<string name="experimental" msgid="6198182315536726162">"Pang-eksperimento"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"I-on ang Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Upang ikonekta ang iyong keyboard sa iyong tablet, kailangan mo munang i-on ang Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2fe49e5..854f850 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Diğer"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Geçmiş"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Yatay Ayırma"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dikey Ayırma"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Özel Ayırma"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Hızlı Ayarlar\'ı Yeniden Düzenle"</string>
<string name="show_brightness" msgid="6613930842805942519">"Hızlı Ayarlar\'da parlaklığı göster"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Sayfalara ayırmayı etkinleştir"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Genel bakış düğmesiyle sayfalara ayırmayı etkinleştirin"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Hızlı açma/kapatmayı etkinleştir"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Sayfalara ayırma sırasında başlatma zaman aşımını etkinleştirin"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Tam ekran boyutunda ekran görüntülerini etkinleştir"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Genel bakışta tam ekran boyutundaki ekran görüntülerini etkinleştirin"</string>
<string name="experimental" msgid="6198182315536726162">"Deneysel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth açılsın mı?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klavyenizi tabletinize bağlamak için önce Bluetooth\'u açmanız gerekir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5a749c4..5347d93 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -296,6 +296,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Більше"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Історія"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Розділити горизонтально"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Розділити вертикально"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Розділити (власний варіант)"</string>
@@ -439,12 +441,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Упорядкувати швидкі налаштування"</string>
<string name="show_brightness" msgid="6613930842805942519">"Показувати панель яскравості у швидких налаштуваннях"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Увімкнути перехід між сторінками"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Увімкнути перехід між сторінками за допомогою кнопки \"Огляд\""</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Увімкнути швидкий перехід"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Увімкнути очікування на запуск під час переходу на сторінку"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Увімкнути знімки повного екрана"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Увімкнути знімки повного екрана в режимі огляду"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментальні налаштування"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Увімкнути Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Щоб під’єднати клавіатуру до планшета, спершу потрібно ввімкнути Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 7dcb076..b9da6e3 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"مزید"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"سرگزشت"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"بلحاظ افقی الگ کریں"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"بلحاظ عمودی الگ کریں"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"بلحاظ حسب ضرورت الگ کریں"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"فوری ترتیبات کو دوبارہ ترتیب دیں"</string>
<string name="show_brightness" msgid="6613930842805942519">"فوری ترتیبات میں چمکیلا پن دکھائیں"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"پیجنگ فعال کریں"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"مجموعی جائزہ بٹن کے ذریعے پیجنگ فعال کریں"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"تیز ٹوگل فعال کریں"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"پیجنگ کے دوران لانچ ٹائم آؤٹ فعال کریں"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"فل اسکرین کے اسکرین شاٹس فعال کریں"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"مجموعی جائزے میں فل اسکرین کے اسکرین شاٹس فعال کریں"</string>
<string name="experimental" msgid="6198182315536726162">"تجرباتی"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوٹوتھ آن کریں؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"اپنے کی بورڈ کو اپنے ٹیبلٹ کے ساتھ منسلک کرنے کیلئے پہلے آپ کو اپنا بلو ٹوتھ آن کرنا ہو گا۔"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 1f26da6..67cd123 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"o‘zgarmas ekran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Ko‘proq"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Jurnal"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Tezkor sozlamalarni qayta tartiblash"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tezkor sozlamalarda yorqinlikni ko‘rsatish"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Sahifalashni yoqish"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Umumiy ma’lumot tugmasi orqali sahifalashni yoqish"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Tezkor almashtirishni yoqish"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Sahifalashda tanaffusni yoqish"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"To‘liq ekranni skrinshotga olishni yoqish"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Umumiy rejimda to‘liq ekranni skrinshotga olishni yoqish"</string>
<string name="experimental" msgid="6198182315536726162">"Tajribaviy"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth yoqilsinmi?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviaturani planshetingizga ulash uchun Bluetooth xizmatini yoqishingiz kerak."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 41ecb45..aa81068 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Thêm"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Lịch sử"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Phân tách ngang"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Phân tách dọc"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tùy chỉnh phân tách"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Sắp xếp lại Cài đặt nhanh"</string>
<string name="show_brightness" msgid="6613930842805942519">"Hiển thị độ sáng trong Cài đặt nhanh"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Bật đánh số trang"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Bật đánh số trang qua nút Tổng quan"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Bật chuyển đổi nhanh"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Bật thời gian chờ khởi chạy trong khi đánh số trang"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Bật ảnh chụp toàn màn hình"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Bật ảnh chụp toàn màn hình trong Tổng quan"</string>
<string name="experimental" msgid="6198182315536726162">"Thử nghiệm"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bật Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Để kết nối bàn phím với máy tính bảng, trước tiên, bạn phải bật Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index cc78ef7..fa69975 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"更多"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"历史记录"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自定义分割"</string>
@@ -437,17 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速设置"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速设置中显示亮度栏"</string>
- <!-- no translation found for overview_page_on_toggle (7332906295136546986) -->
- <skip />
- <!-- no translation found for overview_page_on_toggle_desc (3350421878356386241) -->
- <skip />
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"启用快速切换"</string>
- <!-- no translation found for overview_fast_toggle_via_button_desc (8983671478896649561) -->
- <skip />
- <!-- no translation found for overview_fullscreen_thumbnails (3052584848522856237) -->
- <skip />
- <!-- no translation found for overview_fullscreen_thumbnails_desc (3588874352141119692) -->
- <skip />
<string name="experimental" msgid="6198182315536726162">"实验性"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要开启蓝牙吗?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"要将您的键盘连接到平板电脑,您必须先开启蓝牙。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 1a02914..7375a92 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"更多"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"記錄"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速設定顯示亮度"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"啟用分頁"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"透過「概覽」按鈕啟用分頁"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"啟用快速切換"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"進行分頁時啟用啟動逾時"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"啟用全螢幕擷取畫面"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"在「概覽」啟用全螢幕擷取畫面"</string>
<string name="experimental" msgid="6198182315536726162">"實驗版"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙嗎?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連接至平板電腦,請先開啟藍牙。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 659334d..5edda84 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"更多"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"紀錄"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速設定中顯示亮度"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"啟用分頁功能"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"啟用透過 [總覽] 按鈕切換分頁的功能"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"啟用快速切換"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"切換分頁時啟用啟動逾時功能"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"啟用全螢幕的螢幕擷取畫面"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"在「總覽」畫面中啟用全螢幕的螢幕擷取畫面"</string>
<string name="experimental" msgid="6198182315536726162">"實驗性"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙功能嗎?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連線到平板電腦,您必須先開啟藍牙。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 8ba9363..51c4389 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -294,6 +294,8 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ukuphina isikrini"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ayikwazanga ukuqala i-<xliff:g id="APP">%s</xliff:g>."</string>
+ <string name="recents_show_history_button_label" msgid="7062088196449747245">"Okuningi"</string>
+ <string name="recents_history_label" msgid="3076213823382198287">"Umlando"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Hlukanisa okuvundlile"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Hlukanisa okumile"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Hlukanisa kwezifiso"</string>
@@ -437,12 +439,6 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Hlela kabusha izilungiselelo ezisheshayo"</string>
<string name="show_brightness" msgid="6613930842805942519">"Bonisa ukukhanya kuzilungiselelo ezisheshayo"</string>
- <string name="overview_page_on_toggle" msgid="7332906295136546986">"Nika amandla ukuphenya"</string>
- <string name="overview_page_on_toggle_desc" msgid="3350421878356386241">"Nika amandla wenkinobho yokubuka konke"</string>
- <string name="overview_fast_toggle_via_button" msgid="8316769524084143500">"Nika amandla ukuguqula ngokushesha"</string>
- <string name="overview_fast_toggle_via_button_desc" msgid="8983671478896649561">"Nika amandla ukuvula kokuphela kwesikhathi ngesikhathi uphenya"</string>
- <string name="overview_fullscreen_thumbnails" msgid="3052584848522856237">"Nika amandla izithombe-skrini ezigcwele"</string>
- <string name="overview_fullscreen_thumbnails_desc" msgid="3588874352141119692">"Nika amandla izithombe-skrini ezigcwele ngokubuka konke"</string>
<string name="experimental" msgid="6198182315536726162">"Okokulinga"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vula i-Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ukuze uxhume ikhibhodi yakho nethebhulethi yakho, kufanele uqale ngokuvula i-Bluetooth."</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c85ada8..82192fe 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -214,9 +214,6 @@
<!-- The amount to offset when animating into an affiliate group. -->
<dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
- <!-- The alpha to apply to a task thumbnail. -->
- <item name="recents_task_view_thumbnail_alpha" format="float" type="dimen">0.9</item>
-
<!-- The height of a task view bar. -->
<dimen name="recents_task_bar_height">56dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 96ee397..d931856 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -180,7 +180,7 @@
mProfileManager = bluetoothManager.getProfileManager();
bluetoothManager.getEventManager().registerCallback(new BluetoothCallbackHandler());
- InputManager im = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ InputManager im = context.getSystemService(InputManager.class);
im.registerOnTabletModeChangedListener(this, mHandler);
mInTabletMode = im.isInTabletMode();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 94c45a4..a0c481a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -724,18 +724,6 @@
getResizeTaskDebugDialog().showResizeTaskDialog(event.task, mRecentsView);
}
- public final void onBusEvent(DragStartEvent event) {
- // Lock the orientation while dragging
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
-
- // TODO: docking requires custom accessibility actions
- }
-
- public final void onBusEvent(DragEndEvent event) {
- // Unlock the orientation when dragging completes
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_BEHIND);
- }
-
public final void onBusEvent(LaunchTaskSucceededEvent event) {
MetricsLogger.histogram(this, "overview_task_launch_index", event.taskIndexFromStackFront);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
index 957da94..3deeb47 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
@@ -19,7 +19,6 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.model.Task;
-import com.android.systemui.recents.views.DragView;
import com.android.systemui.recents.views.DropTarget;
import com.android.systemui.recents.views.TaskView;
@@ -30,15 +29,13 @@
public final Task task;
public final TaskView taskView;
- public final DragView dragView;
public final DropTarget dropTarget;
public final ReferenceCountedTrigger postAnimationTrigger;
- public DragEndEvent(Task task, TaskView taskView, DragView dragView, DropTarget dropTarget,
+ public DragEndEvent(Task task, TaskView taskView, DropTarget dropTarget,
ReferenceCountedTrigger postAnimationTrigger) {
this.task = task;
this.taskView = taskView;
- this.dragView = dragView;
this.dropTarget = dropTarget;
this.postAnimationTrigger = postAnimationTrigger;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
index 2d42a0e..b81c10c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
@@ -16,9 +16,9 @@
package com.android.systemui.recents.events.ui.dragndrop;
+import android.graphics.Point;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.model.Task;
-import com.android.systemui.recents.views.DragView;
import com.android.systemui.recents.views.TaskView;
/**
@@ -28,11 +28,11 @@
public final Task task;
public final TaskView taskView;
- public final DragView dragView;
+ public final Point tlOffset;
- public DragStartEvent(Task task, TaskView taskView, DragView dragView) {
+ public DragStartEvent(Task task, TaskView taskView, Point tlOffset) {
this.task = task;
this.taskView = taskView;
- this.dragView = dragView;
+ this.tlOffset = tlOffset;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 59fb6cf..2b20c07 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -410,7 +410,7 @@
return thumbnail;
}
- Bitmap thumbnail = SystemServicesProxy.getThumbnail(mAm, taskId);
+ Bitmap thumbnail = getThumbnail(taskId);
if (thumbnail != null) {
thumbnail.setHasAlpha(false);
// We use a dumb heuristic for now, if the thumbnail is purely transparent in the top
@@ -430,8 +430,12 @@
/**
* Returns a task thumbnail from the activity manager
*/
- public static Bitmap getThumbnail(ActivityManager activityManager, int taskId) {
- ActivityManager.TaskThumbnail taskThumbnail = activityManager.getTaskThumbnail(taskId);
+ public Bitmap getThumbnail(int taskId) {
+ if (mAm == null) {
+ return null;
+ }
+
+ ActivityManager.TaskThumbnail taskThumbnail = mAm.getTaskThumbnail(taskId);
if (taskThumbnail == null) return null;
Bitmap thumbnail = taskThumbnail.mainThumbnail;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 5921d13..3bb89a3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -128,7 +128,7 @@
boolean isStackTask = true;
if (debugFlags.isHistoryEnabled()) {
boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId);
- isStackTask = !isFreeformTask && (!isHistoricalTask(t) ||
+ isStackTask = isFreeformTask || (!isHistoricalTask(t) ||
(t.lastActiveTime >= lastStackActiveTime &&
i >= (taskCount - MIN_NUM_TASKS)));
if (isStackTask && newLastStackActiveTime < 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 945fdc1..271a2a0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.views;
-import android.animation.ObjectAnimator;
import android.graphics.Outline;
import android.graphics.Rect;
import android.util.IntProperty;
@@ -65,6 +64,15 @@
mCornerRadius = cornerRadius;
}
+ /**
+ * Resets the right and bottom clip for this view.
+ */
+ public void reset() {
+ mClipRect.setEmpty();
+ mSourceView.invalidateOutline();
+ updateClipBounds();
+ }
+
@Override
public void getOutline(View view, Outline outline) {
outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
@@ -82,15 +90,6 @@
}
}
- /**
- * Animates the bottom clip.
- */
- public void animateClipBottom(int bottom) {
- ObjectAnimator animator = ObjectAnimator.ofInt(this, CLIP_BOTTOM, getClipBottom(), bottom);
- animator.setDuration(150);
- animator.start();
- }
-
/** Sets the bottom clip. */
public void setClipBottom(int bottom, boolean force) {
if (bottom != mClipRect.bottom || force) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DragView.java b/packages/SystemUI/src/com/android/systemui/recents/views/DragView.java
deleted file mode 100644
index 96dfaac..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/DragView.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.widget.ImageView;
-
-public class DragView extends ImageView {
-
- // The offset from the top-left of the dragBitmap
- Point mTopLeftOffset;
-
- public DragView(Context context, Bitmap dragBitmap, Point tlOffset) {
- super(context);
-
- mTopLeftOffset = tlOffset;
- setImageBitmap(dragBitmap);
- }
-
- public Point getTopLeftOffset() {
- return mTopLeftOffset;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index 90d62c1..a70b66d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.views;
+import android.graphics.Rect;
import android.util.Log;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -52,8 +53,8 @@
int numFreeformTasks = stackLayout.mNumFreeformTasks;
if (!freeformTasks.isEmpty()) {
// Calculate the cell width/height depending on the number of freeform tasks
- mFreeformCellXCount = Math.max(2, (int) Math.ceil(Math.sqrt(numFreeformTasks)));
- mFreeformCellYCount = Math.max(2, (int) Math.ceil((float) numFreeformTasks /
+ mFreeformCellXCount = Math.max(1, (int) Math.ceil(Math.sqrt(numFreeformTasks)));
+ mFreeformCellYCount = Math.max(1, (int) Math.ceil((float) numFreeformTasks /
mFreeformCellXCount));
// For now, make the cells square
mFreeformCellWidth = Math.min(stackLayout.mFreeformRect.width() / mFreeformCellXCount,
@@ -94,15 +95,21 @@
public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut,
TaskStackLayoutAlgorithm stackLayout) {
if (mTaskIndexMap.containsKey(task.key)) {
- // This is a freeform task, so lay it out in the freeform workspace
+ Rect taskRect = stackLayout.mTaskRect;
int taskIndex = mTaskIndexMap.get(task.key);
- int topOffset = (stackLayout.mFreeformRect.top - stackLayout.mTaskRect.top);
+ int topOffset = (stackLayout.mFreeformRect.top - taskRect.top);
int x = taskIndex % mFreeformCellXCount;
int y = taskIndex / mFreeformCellXCount;
- float scale = (float) mFreeformCellWidth / stackLayout.mTaskRect.width();
- int scaleXOffset = (int) (((1f - scale) * stackLayout.mTaskRect.width()) / 2);
- int scaleYOffset = (int) (((1f - scale) * stackLayout.mTaskRect.height()) / 2);
- transformOut.scale = scale * 0.9f;
+
+ int bitmapWidth = task.thumbnail.getWidth();
+ int bitmapHeight = task.thumbnail.getHeight();
+ float thumbnailScale = Math.min((float) mFreeformCellWidth / bitmapWidth,
+ (float) mFreeformCellHeight / bitmapHeight);
+ float thumbnailWidth = bitmapWidth * thumbnailScale;
+ float thumbnailHeight = bitmapHeight * thumbnailScale;
+ int scaleXOffset = (int) (((1f - thumbnailScale) * thumbnailWidth) / 2);
+ int scaleYOffset = (int) (((1f - thumbnailScale) * thumbnailHeight) / 2);
+ transformOut.scale = thumbnailScale * 0.9f;
transformOut.translationX = x * mFreeformCellWidth - scaleXOffset;
transformOut.translationY = topOffset + y * mFreeformCellHeight - scaleYOffset;
transformOut.translationZ = stackLayout.mMaxTranslationZ;
@@ -115,7 +122,6 @@
if (DEBUG) {
Log.d(TAG, "getTransform: " + task.key + ", " + transformOut);
}
-
return transformOut;
}
return null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 0557f65..5616018 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -81,7 +81,6 @@
RecentsTransitionHelper mTransitionHelper;
RecentsViewTouchHandler mTouchHandler;
- DragView mDragView;
TaskStack.DockState[] mVisibleDockStates = {
TaskStack.DockState.LEFT,
TaskStack.DockState.TOP,
@@ -341,13 +340,6 @@
mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
}
- if (mDragView != null) {
- Rect taskRect = mTaskStackView.mLayoutAlgorithm.mTaskRect;
- mDragView.measure(
- MeasureSpec.makeMeasureSpec(taskRect.width(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(taskRect.height(), MeasureSpec.AT_MOST));
- }
-
// Measure the history button with the full space above the stack, but width-constrained
// to the stack
Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
@@ -379,11 +371,6 @@
mTaskStackView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
}
- if (mDragView != null) {
- mDragView.layout(left, top, left + mDragView.getMeasuredWidth(),
- top + mDragView.getMeasuredHeight());
- }
-
// Layout the history button left-aligned with the stack, but offset from the top of the
// view
Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
@@ -461,10 +448,6 @@
/**** EventBus Events ****/
public final void onBusEvent(DragStartEvent event) {
- // Add the drag view
- mDragView = event.dragView;
- addView(mDragView);
-
updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
TaskStack.DockState.NONE.viewState.dockAreaAlpha);
}
@@ -480,65 +463,17 @@
}
public final void onBusEvent(final DragEndEvent event) {
- final Runnable cleanUpRunnable = new Runnable() {
- @Override
- public void run() {
- // Remove the drag view
- removeView(mDragView);
- mDragView = null;
- }
- };
-
// Animate the overlay alpha back to 0
updateVisibleDockRegions(null, -1);
- if (event.dropTarget == null) {
- // No drop targets for hit, so just animate the task back to its place
- event.postAnimationTrigger.increment();
- event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- cleanUpRunnable.run();
- }
- });
- // Animate the task back to where it was before then clean up afterwards
- TaskViewTransform taskTransform = new TaskViewTransform();
- TaskStackLayoutAlgorithm layoutAlgorithm = mTaskStackView.getStackAlgorithm();
- layoutAlgorithm.getStackTransform(event.task,
- mTaskStackView.getScroller().getStackScroll(), taskTransform, null);
- event.dragView.animate()
- .scaleX(taskTransform.scale)
- .scaleY(taskTransform.scale)
- .translationX((layoutAlgorithm.mTaskRect.left - event.dragView.getLeft())
- + taskTransform.translationX)
- .translationY((layoutAlgorithm.mTaskRect.top - event.dragView.getTop())
- + taskTransform.translationY)
- .setDuration(175)
- .setInterpolator(mFastOutSlowInInterpolator)
- .withEndAction(event.postAnimationTrigger.decrementAsRunnable())
- .start();
-
- } else if (event.dropTarget instanceof TaskStack.DockState) {
+ // Handle the case where we drop onto a dock region
+ if (event.dropTarget instanceof TaskStack.DockState) {
final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
- // For now, just remove the drag view and the original task
- // TODO: Animate the task to the drop target rect before launching it above
- cleanUpRunnable.run();
-
// Dock the task and launch it
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode);
launchTask(event.task, null, INVALID_STACK_ID);
-
- } else {
- // We dropped on another drop target, so just add the cleanup to the post animation
- // trigger
- event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- cleanUpRunnable.run();
- }
- });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index c7edc92..c55f383 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -64,8 +64,8 @@
private Task mDragTask;
private TaskView mTaskView;
- private DragView mDragView;
+ private Point mTaskViewOffset = new Point();
private Point mDownPos = new Point();
private boolean mDragging;
@@ -115,13 +115,16 @@
mDragging = true;
mDragTask = event.task;
mTaskView = event.taskView;
- mDragView = event.dragView;
mDropTargets.clear();
- float x = mDownPos.x - mDragView.getTopLeftOffset().x;
- float y = mDownPos.y - mDragView.getTopLeftOffset().y;
- mDragView.setTranslationX(x);
- mDragView.setTranslationY(y);
+ int[] recentsViewLocation = new int[2];
+ mRv.getLocationInWindow(recentsViewLocation);
+ mTaskViewOffset.set(mTaskView.getLeft() - recentsViewLocation[0] + event.tlOffset.x,
+ mTaskView.getTop() - recentsViewLocation[1] + event.tlOffset.y);
+ float x = mDownPos.x - mTaskViewOffset.x;
+ float y = mDownPos.y - mTaskViewOffset.y;
+ mTaskView.setTranslationX(x);
+ mTaskView.setTranslationY(y);
RecentsConfiguration config = Recents.getConfiguration();
if (!config.hasDockedTasks) {
@@ -140,7 +143,6 @@
mDragging = false;
mDragTask = null;
mTaskView = null;
- mDragView = null;
mLastDropTarget = null;
}
@@ -160,8 +162,8 @@
int height = mRv.getMeasuredHeight();
float evX = ev.getX();
float evY = ev.getY();
- float x = evX - mDragView.getTopLeftOffset().x;
- float y = evY - mDragView.getTopLeftOffset().y;
+ float x = evX - mTaskViewOffset.x;
+ float y = evY - mTaskViewOffset.y;
DropTarget currentDropTarget = null;
for (DropTarget target : mDropTargets) {
@@ -176,8 +178,8 @@
currentDropTarget));
}
- mDragView.setTranslationX(x);
- mDragView.setTranslationY(y);
+ mTaskView.setTranslationX(x);
+ mTaskView.setTranslationY(y);
}
break;
}
@@ -187,7 +189,7 @@
ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(
mRv.getContext(), null, null, null);
postAnimationTrigger.increment();
- EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView, mDragView,
+ EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView,
mLastDropTarget, postAnimationTrigger));
postAnimationTrigger.decrement();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 30efd5f..c02eaf8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,6 +16,10 @@
package com.android.systemui.recents.views;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
@@ -1420,7 +1424,12 @@
}
}
+ private AnimatorSet mDropAnimation;
+
public final void onBusEvent(DragStartEvent event) {
+ // Cancel the existing drop animation
+ Utilities.cancelAnimationWithoutCallbacks(mDropAnimation);
+
if (event.task.isFreeformTask()) {
// Animate to the front of the stack
mStackScroller.animateScroll(mStackScroller.getStackScroll(),
@@ -1441,56 +1450,84 @@
}
public final void onBusEvent(final DragEndEvent event) {
- if (event.dropTarget != mFreeformWorkspaceDropTarget &&
- event.dropTarget != mStackDropTarget) {
- return;
- }
- if (event.task.isFreeformTask() && event.dropTarget == mFreeformWorkspaceDropTarget) {
- // TODO: Animate back into view
- return;
- }
- if (!event.task.isFreeformTask() && event.dropTarget == mStackDropTarget) {
- // TODO: Animate back into view
+ // We don't handle drops on the dock regions
+ if (event.dropTarget instanceof TaskStack.DockState) {
return;
}
- // Move the task to the right position in the stack (ie. the front of the stack if freeform
- // or the front of the stack if fullscreen). Note, we MUST move the tasks before we update
- // their stack ids, otherwise, the keys will have changed.
- if (event.dropTarget == mFreeformWorkspaceDropTarget) {
- mStack.moveTaskToStack(event.task, FREEFORM_WORKSPACE_STACK_ID);
- updateLayout(true);
- } else if (event.dropTarget == mStackDropTarget) {
- mStack.moveTaskToStack(event.task, FULLSCREEN_WORKSPACE_STACK_ID);
- updateLayout(true);
+ boolean isFreeformTask = event.task.isFreeformTask();
+ boolean hasChangedStacks =
+ (!isFreeformTask && event.dropTarget == mFreeformWorkspaceDropTarget) ||
+ (isFreeformTask && event.dropTarget == mStackDropTarget);
+ if (hasChangedStacks) {
+ ArrayList<Animator> animations = new ArrayList<>();
+
+ // Move the task to the right position in the stack (ie. the front of the stack if
+ // freeform or the front of the stack if fullscreen). Note, we MUST move the tasks
+ // before we update their stack ids, otherwise, the keys will have changed.
+ if (event.dropTarget == mFreeformWorkspaceDropTarget) {
+ mStack.moveTaskToStack(event.task, FREEFORM_WORKSPACE_STACK_ID);
+ updateLayout(true);
+
+ // Update the clipping to match the scaled bitmap rect
+ TaskViewThumbnail thumbnailView = event.taskView.mThumbnailView;
+ float thumbnailScale = thumbnailView.computeThumbnailScale(true);
+ RectF bitmapRect = thumbnailView.getScaledBitmapRect(thumbnailScale);
+ AnimateableViewBounds viewBounds = event.taskView.getViewBounds();
+ int clipRight = (int) (thumbnailView.getMeasuredWidth() - bitmapRect.width());
+ int clipBottom = (int) (thumbnailView.getMeasuredHeight() - bitmapRect.height());
+ animations.add(ObjectAnimator.ofFloat(thumbnailView, TaskViewThumbnail.BITMAP_SCALE,
+ thumbnailView.getBitmapScale(), thumbnailScale));
+ animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_BOTTOM,
+ viewBounds.getClipBottom(), clipBottom));
+ animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_RIGHT,
+ viewBounds.getClipRight(), clipRight));
+ } else if (event.dropTarget == mStackDropTarget) {
+ mStack.moveTaskToStack(event.task, FULLSCREEN_WORKSPACE_STACK_ID);
+ updateLayout(true);
+
+ // Reset the clipping when animating to the stack
+ TaskViewThumbnail thumbnailView = event.taskView.mThumbnailView;
+ float thumbnailScale = thumbnailView.computeThumbnailScale(false);
+ AnimateableViewBounds viewBounds = event.taskView.getViewBounds();
+ animations.add(ObjectAnimator.ofFloat(thumbnailView, TaskViewThumbnail.BITMAP_SCALE,
+ thumbnailView.getBitmapScale(), thumbnailScale));
+ animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_BOTTOM,
+ viewBounds.getClipBottom(), 0));
+ animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_RIGHT,
+ viewBounds.getClipRight(), 0));
+ }
+
+ // Move the task to the new stack in the system after the animation completes
+ event.postAnimationTrigger.increment();
+ event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+ @Override
+ public void run() {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.moveTaskToStack(event.task.key.id, event.task.key.stackId);
+ }
+ });
+
+ // Animate the normal properties of the view
+ mDropAnimation = new AnimatorSet();
+ mDropAnimation.playTogether(animations);
+ mDropAnimation.setDuration(250);
+ mDropAnimation.setInterpolator(mFastOutSlowInInterpolator);
+ mDropAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ event.postAnimationTrigger.decrement();
+ }
+ });
+ mDropAnimation.start();
}
event.postAnimationTrigger.increment();
- event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.moveTaskToStack(event.task.key.id, event.task.key.stackId);
- }
- });
+ event.taskView.animate()
+ .withEndAction(event.postAnimationTrigger.decrementAsRunnable());
- // Animate the drag view to the new position
- mLayoutAlgorithm.getStackTransform(event.task, mStackScroller.getStackScroll(),
- mTmpTransform, null);
- event.dragView.animate()
- .scaleX(mTmpTransform.scale)
- .scaleY(mTmpTransform.scale)
- .translationX((mLayoutAlgorithm.mTaskRect.left - event.dragView.getLeft())
- + mTmpTransform.translationX)
- .translationY((mLayoutAlgorithm.mTaskRect.top - event.dragView.getTop())
- + mTmpTransform.translationY)
- .setDuration(175)
- .setInterpolator(mFastOutSlowInInterpolator)
- .withEndAction(event.postAnimationTrigger.decrementAsRunnable())
- .start();
-
- // Animate the other views into place
- requestSynchronizeStackViewsWithModel(175);
+ // Animate the tack view back into position
+ requestSynchronizeStackViewsWithModel(250);
}
public final void onBusEvent(StackViewScrolledEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 6db2eb9..fb84a22 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -22,8 +22,6 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
@@ -244,6 +242,8 @@
void resetViewProperties() {
setDim(0);
setLayerType(View.LAYER_TYPE_NONE, null);
+ setVisibility(View.VISIBLE);
+ getViewBounds().reset();
TaskViewTransform.reset(this);
if (mActionButtonView != null) {
mActionButtonView.setScaleX(1f);
@@ -251,18 +251,6 @@
mActionButtonView.setAlpha(1f);
mActionButtonView.setTranslationZ(mActionButtonTranslationZ);
}
- setVisibility(View.VISIBLE);
- }
-
- /**
- * When we are un/filtering, this method will set up the transform that we are animating to,
- * in order to hide the task.
- */
- void prepareTaskTransformForFilterTaskHidden(TaskViewTransform toTransform) {
- // Fade the view out and slide it away
- toTransform.alpha = 0f;
- toTransform.translationY += 200;
- toTransform.translationZ = 0;
}
/** Prepares this task view for the enter-recents animations. This is called earlier in the
@@ -296,8 +284,6 @@
}
// Apply the current dim
setDim(initialDim);
- // Prepare the thumbnail view alpha
- mThumbnailView.prepareEnterRecentsAnimation(isTaskViewLaunchTargetTask);
}
/** Animates this task view as it enters recents */
@@ -425,9 +411,6 @@
R.dimen.recents_task_view_affiliate_group_enter_offset);
if (isLaunchingTask) {
- // Animate the thumbnail alpha back into full opacity for the window animation out
- mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
-
// Animate the dim
if (mDimAlpha > 0) {
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
@@ -637,7 +620,6 @@
mIsFocused = isFocused;
mIsFocusAnimated = animated;
mHeaderView.onTaskViewFocusChanged(isFocused, animated);
- mThumbnailView.onFocusChanged(isFocused);
if (isFocused) {
if (requestViewFocus && !isFocused()) {
requestFocus();
@@ -746,54 +728,20 @@
// Start listening for drag events
setClipViewInStack(false);
+ // Enlarge the view slightly
final float finalScale = getScaleX() * 1.05f;
- final int width = getWidth();
- final int height = getHeight();
- Bitmap dragBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(dragBitmap);
- mThumbnailView.draw(c);
- mHeaderView.draw(c);
- c.setBitmap(null);
+ animate()
+ .scaleX(finalScale)
+ .scaleY(finalScale)
+ .setDuration(175)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .start();
- // The downTouchPos is relative to the currently transformed TaskView, but we will be
- // dragging a copy of the full task view, which makes it easier for us to animate them
- // when the user drops
- mDownTouchPos.x += ((1f - getScaleX()) * width) / 2;
- mDownTouchPos.y += ((1f - getScaleY()) * height) / 2;
+ mDownTouchPos.x += ((1f - getScaleX()) * getWidth()) / 2;
+ mDownTouchPos.y += ((1f - getScaleY()) * getHeight()) / 2;
- // Initiate the drag
- final DragView dragView = new DragView(getContext(), dragBitmap, mDownTouchPos);
- dragView.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRect(0, 0, width, height);
- }
- });
- dragView.setScaleX(getScaleX());
- dragView.setScaleY(getScaleY());
- dragView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- // Hide this task view after the drag view is attached
- setVisibility(View.INVISIBLE);
- // Animate the alpha slightly to indicate dragging
- dragView.setElevation(getElevation());
- dragView.setTranslationZ(getTranslationZ());
- dragView.animate()
- .scaleX(finalScale)
- .scaleY(finalScale)
- .setDuration(175)
- .setInterpolator(mFastOutSlowInInterpolator)
- .start();
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- // Do nothing
- }
- });
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
- EventBus.getDefault().send(new DragStartEvent(mTask, this, dragView));
+ EventBus.getDefault().send(new DragStartEvent(mTask, this, mDownTouchPos));
return true;
}
return false;
@@ -806,9 +754,6 @@
event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
@Override
public void run() {
- // Show this task view
- setVisibility(View.VISIBLE);
-
// Animate the drag view back from where it is, to the view location, then after
// it returns, update the clip state
setClipViewInStack(true);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index b3d263e..c288afb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -16,9 +16,6 @@
package com.android.systemui.recents.views;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
@@ -31,11 +28,12 @@
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
+import android.util.FloatProperty;
+import android.util.Property;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.systemui.R;
-import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -45,6 +43,19 @@
*/
public class TaskViewThumbnail extends View {
+ public static final Property<TaskViewThumbnail, Float> BITMAP_SCALE =
+ new FloatProperty<TaskViewThumbnail>("bitmapScale") {
+ @Override
+ public void setValue(TaskViewThumbnail object, float scale) {
+ object.setBitmapScale(scale);
+ }
+
+ @Override
+ public Float get(TaskViewThumbnail object) {
+ return object.getBitmapScale();
+ }
+ };
+
private Task mTask;
// Drawing
@@ -60,18 +71,6 @@
Interpolator mFastOutSlowInInterpolator;
- // Thumbnail alpha
- float mThumbnailAlpha;
- ValueAnimator mThumbnailAlphaAnimator;
- ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener
- = new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mThumbnailAlpha = (float) animation.getAnimatedValue();
- updateThumbnailPaintFilter();
- }
- };
-
// Task bar clipping, the top of this thumbnail can be clipped against the opaque header
// bar that overlaps this thumbnail
View mTaskBar;
@@ -105,17 +104,11 @@
}
@Override
- protected void onFinishInflate() {
- mThumbnailAlpha = getResources().getFloat(R.dimen.recents_task_view_thumbnail_alpha);
- updateThumbnailPaintFilter();
- }
-
- @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
mLayoutRect.set(0, 0, getWidth(), getHeight());
- updateThumbnailScale();
+ setBitmapScale(computeThumbnailScale(mTask != null ? mTask.isFreeformTask() : false));
}
}
@@ -137,12 +130,15 @@
Shader.TileMode.CLAMP);
mDrawPaint.setShader(mBitmapShader);
mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight());
- updateThumbnailScale();
} else {
mBitmapShader = null;
mDrawPaint.setShader(null);
}
- updateThumbnailPaintFilter();
+ if (mTask != null) {
+ setBitmapScale(computeThumbnailScale(mTask != null ? mTask.isFreeformTask() : false));
+ } else {
+ setBitmapScale(1f);
+ }
}
/** Updates the paint to draw the thumbnail. */
@@ -150,36 +146,61 @@
if (mInvisible) {
return;
}
- int mul = (int) ((1.0f - mDimAlpha) * mThumbnailAlpha * 255);
- int add = (int) ((1.0f - mDimAlpha) * (1 - mThumbnailAlpha) * 255);
+ int mul = (int) ((1.0f - mDimAlpha) * 255);
if (mBitmapShader != null) {
mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul));
- mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add));
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setColor(0xffffffff);
} else {
- int grey = mul + add;
+ int grey = mul;
mDrawPaint.setColorFilter(null);
mDrawPaint.setColor(Color.argb(255, grey, grey, grey));
}
invalidate();
}
- /** Updates the thumbnail shader's scale transform. */
- void updateThumbnailScale() {
- if (mBitmapShader != null) {
- if (mTask.isFreeformTask()) {
- // For freeform tasks, we scale the bitmap rect to fit in the layout rect
- mBitmapScale = Math.min(mLayoutRect.width() / mBitmapRect.width(),
- mLayoutRect.height() / mBitmapRect.height());
- } else {
- // For stack tasks, we scale the bitmap to fit the width
- mBitmapScale = Math.max(1f, mLayoutRect.width() / mBitmapRect.width());
- }
+ /**
+ * Returns the scale to apply to a thumbnail bitmap relative to this view rect.
+ */
+ public float computeThumbnailScale(boolean isFreeformTask) {
+ if (isFreeformTask) {
+ // For freeform tasks, we scale the bitmap rect to fit in the layout rect
+ return Math.min(mLayoutRect.width() / mBitmapRect.width(),
+ mLayoutRect.height() / mBitmapRect.height());
+ } else {
+ // For stack tasks, we scale the bitmap to fit the width
+ return Math.max(1f, mLayoutRect.width() / mBitmapRect.width());
+ }
+ }
+ /**
+ * Returns the scaled bitmap rect.
+ */
+ public RectF getScaledBitmapRect(float scale) {
+ RectF scaledBitmapRect = new RectF(mBitmapRect);
+ scaledBitmapRect.left *= scale;
+ scaledBitmapRect.top *= scale;
+ scaledBitmapRect.right *= scale;
+ scaledBitmapRect.bottom *= scale;
+ return scaledBitmapRect;
+ }
+
+ /**
+ * Sets the scale of the bitmap relative to this view.
+ */
+ public void setBitmapScale(float scale) {
+ if (mBitmapShader != null) {
+ mBitmapScale = scale;
mScaleMatrix.setScale(mBitmapScale, mBitmapScale);
mBitmapShader.setLocalMatrix(mScaleMatrix);
}
+ if (!mInvisible) {
+ invalidate();
+ }
+ }
+
+ public float getBitmapScale() {
+ return mBitmapScale;
}
/** Updates the clip rect based on the given task bar. */
@@ -227,67 +248,4 @@
mTask = null;
setThumbnail(null);
}
-
- /** Handles focus changes. */
- void onFocusChanged(boolean focused) {
- if (focused) {
- if (Float.compare(getAlpha(), 1f) != 0) {
- startFadeAnimation(1f, 150, null);
- }
- } else {
- float taskViewThumbnailAlpha = getResources().getFloat(
- R.dimen.recents_task_view_thumbnail_alpha);
- if (Float.compare(getAlpha(), taskViewThumbnailAlpha) != 0) {
- startFadeAnimation(taskViewThumbnailAlpha, 150, null);
- }
- }
- }
-
- /**
- * Prepares for the enter recents animation, this gets called before the the view
- * is first visible and will be followed by a startEnterRecentsAnimation() call.
- */
- void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) {
- if (isTaskViewLaunchTargetTask) {
- mThumbnailAlpha = 1f;
- } else {
- mThumbnailAlpha = getResources().getFloat(
- R.dimen.recents_task_view_thumbnail_alpha);
- }
- updateThumbnailPaintFilter();
- }
-
- /** Animates this task thumbnail as it enters Recents. */
- void startEnterRecentsAnimation(Runnable postAnimRunnable) {
- float taskViewThumbnailAlpha = getResources().getFloat(
- R.dimen.recents_task_view_thumbnail_alpha);
- startFadeAnimation(taskViewThumbnailAlpha,
- getResources().getInteger(R.integer.recents_task_enter_from_app_duration),
- postAnimRunnable);
- }
-
- /** Animates this task thumbnail as it exits Recents. */
- void startLaunchTaskAnimation(Runnable postAnimRunnable) {
- int taskViewExitToAppDuration = mContext.getResources().getInteger(
- R.integer.recents_task_exit_to_app_duration);
- startFadeAnimation(1f, taskViewExitToAppDuration, postAnimRunnable);
- }
-
- /** Starts a new thumbnail alpha animation. */
- void startFadeAnimation(float finalAlpha, int duration, final Runnable postAnimRunnable) {
- Utilities.cancelAnimationWithoutCallbacks(mThumbnailAlphaAnimator);
- mThumbnailAlphaAnimator = ValueAnimator.ofFloat(mThumbnailAlpha, finalAlpha);
- mThumbnailAlphaAnimator.setDuration(duration);
- mThumbnailAlphaAnimator.setInterpolator(mFastOutSlowInInterpolator);
- mThumbnailAlphaAnimator.addUpdateListener(mThumbnailAlphaUpdateListener);
- if (postAnimRunnable != null) {
- mThumbnailAlphaAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- postAnimRunnable.run();
- }
- });
- }
- mThumbnailAlphaAnimator.start();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index e1aec6f..cddb1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -143,7 +143,7 @@
private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
@Override
public void onClick(View view) {
- ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
+ mContext.getSystemService(InputMethodManager.class)
.showInputMethodPicker(true /* showAuxiliarySubtypes */);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 93a8fd8..0917528 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -110,7 +110,7 @@
// When enabling location, a user consent dialog will pop up, and the
// setting won't be fully enabled until the user accepts the agreement.
int mode = enabled
- ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY : Settings.Secure.LOCATION_MODE_OFF;
+ ? Settings.Secure.LOCATION_MODE_PREVIOUS : Settings.Secure.LOCATION_MODE_OFF;
// QuickSettings always runs as the owner, so specifically set the settings
// for the current foreground user.
return Settings.Secure
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 3d358ec..11fdbb5 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -433,7 +433,6 @@
AccessibilityEvent.obtain(event)).sendToTarget();
}
event.recycle();
- getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0;
}
return (OWN_PROCESS_ID != Binder.getCallingPid());
}
@@ -1051,9 +1050,7 @@
Service service = state.mBoundServices.get(i);
if (service.mIsDefault == isDefault) {
- if (canDispatchEventToServiceLocked(service, event,
- state.mHandledFeedbackTypes)) {
- state.mHandledFeedbackTypes |= service.mFeedbackType;
+ if (canDispatchEventToServiceLocked(service, event)) {
service.notifyAccessibilityEvent(event);
}
}
@@ -1088,19 +1085,14 @@
/**
* Determines if given event can be dispatched to a service based on the package of the
- * event source and already notified services for that event type. Specifically, a
- * service is notified if it is interested in events from the package and no other service
- * providing the same feedback type has been notified. Exception are services the
- * provide generic feedback (feedback type left as a safety net for unforeseen feedback
- * types) which are always notified.
+ * event source. Specifically, a service is notified if it is interested in events from the
+ * package.
*
* @param service The potential receiver.
* @param event The event.
- * @param handledFeedbackTypes The feedback types for which services have been notified.
* @return True if the listener should be notified, false otherwise.
*/
- private boolean canDispatchEventToServiceLocked(Service service, AccessibilityEvent event,
- int handledFeedbackTypes) {
+ private boolean canDispatchEventToServiceLocked(Service service, AccessibilityEvent event) {
if (!service.canReceiveEventsLocked()) {
return false;
@@ -1121,15 +1113,7 @@
String packageName = (event.getPackageName() != null)
? event.getPackageName().toString() : null;
- if (packageNames.isEmpty() || packageNames.contains(packageName)) {
- int feedbackType = service.mFeedbackType;
- if ((handledFeedbackTypes & feedbackType) != feedbackType
- || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) {
- return true;
- }
- }
-
- return false;
+ return (packageNames.isEmpty() || packageNames.contains(packageName));
}
private void unbindAllServicesLocked(UserState userState) {
@@ -3886,8 +3870,6 @@
public final Set<ComponentName> mTouchExplorationGrantedServices =
new HashSet<>();
- public int mHandledFeedbackTypes = 0;
-
public int mLastSentClientState = -1;
public boolean mIsAccessibilityEnabled;
@@ -3950,7 +3932,6 @@
mBindingServices.clear();
// Clear event management state.
- mHandledFeedbackTypes = 0;
mLastSentClientState = -1;
// Clear state persisted in settings.
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index fc3a322..fcd56eb7 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -446,8 +446,7 @@
String candidateLocale = null;
if (hashCode == 0) {
// Spell checker language settings == "auto"
- final InputMethodManager imm =
- (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null) {
final InputMethodSubtype currentInputMethodSubtype =
imm.getCurrentInputMethodSubtype();
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 9eb66dd..2924cef 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -223,7 +223,7 @@
}
public void systemReady() {
- mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
+ mIm = mContext.getSystemService(InputManager.class);
mSettingObserver = new SettingsObserver(mH);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6687412..3b43633 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -33,7 +33,9 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.NetworkRequest;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.os.Binder;
@@ -213,6 +215,7 @@
checkDunRequired();
}
+ @Override
public void interfaceStatusChanged(String iface, boolean up) {
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
boolean found = false;
@@ -248,6 +251,7 @@
}
}
+ @Override
public void interfaceLinkStateChanged(String iface, boolean up) {
if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
interfaceStatusChanged(iface, up);
@@ -280,6 +284,7 @@
}
}
+ @Override
public void interfaceAdded(String iface) {
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
boolean found = false;
@@ -311,6 +316,7 @@
}
}
+ @Override
public void interfaceRemoved(String iface) {
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mPublicSync) {
@@ -638,7 +644,7 @@
return values;
}
- public void checkDunRequired() {
+ private void checkDunRequired() {
int secureSetting = 2;
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
@@ -1135,10 +1141,8 @@
static final int CMD_TETHER_MODE_UNREQUESTED = 2;
// upstream connection change - do the right thing
static final int CMD_UPSTREAM_CHANGED = 3;
- // we received notice that the cellular DUN connection is up
- static final int CMD_CELL_CONNECTION_RENEW = 4;
// we don't have a valid upstream conn, check again after a delay
- static final int CMD_RETRY_UPSTREAM = 5;
+ static final int CMD_RETRY_UPSTREAM = 4;
// This indicates what a timeout event relates to. A state that
// sends itself a delayed timeout event and handles incoming timeout events
@@ -1157,13 +1161,12 @@
private ArrayList<TetherInterfaceSM> mNotifyList;
- private int mCurrentConnectionSequence;
private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
+ private ConnectivityManager.NetworkCallback mMobileUpstreamCallback;
private String mUpstreamIfaceName = null;
private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
- private static final int CELL_CONNECTION_RENEW_MS = 40000;
TetherMasterSM(String name, Looper looper) {
super(name, looper);
@@ -1190,58 +1193,69 @@
}
class TetherMasterUtilState extends State {
- protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
@Override
public boolean processMessage(Message m) {
return false;
}
- protected String enableString(int apnType) {
- switch (apnType) {
- case ConnectivityManager.TYPE_MOBILE_DUN:
- return Phone.FEATURE_ENABLE_DUN_ALWAYS;
- case ConnectivityManager.TYPE_MOBILE:
- case ConnectivityManager.TYPE_MOBILE_HIPRI:
- return Phone.FEATURE_ENABLE_HIPRI;
- }
- return null;
- }
+
protected boolean turnOnUpstreamMobileConnection(int apnType) {
- boolean retValue = true;
- if (apnType == ConnectivityManager.TYPE_NONE) return false;
- if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
- int result = PhoneConstants.APN_REQUEST_FAILED;
- String enableString = enableString(apnType);
- if (enableString == null) return false;
- result = getConnectivityManager().startUsingNetworkFeature(
- ConnectivityManager.TYPE_MOBILE, enableString);
- switch (result) {
- case PhoneConstants.APN_ALREADY_ACTIVE:
- case PhoneConstants.APN_REQUEST_STARTED:
- mMobileApnReserved = apnType;
- Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
- m.arg1 = ++mCurrentConnectionSequence;
- sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
- break;
- case PhoneConstants.APN_REQUEST_FAILED:
- default:
- retValue = false;
- break;
+ if (apnType == ConnectivityManager.TYPE_NONE) { return false; }
+
+ if (apnType != mMobileApnReserved) {
+ // Unregister any previous mobile upstream callback because
+ // this request, if any, will be different.
+ turnOffUpstreamMobileConnection();
}
- return retValue;
- }
- protected boolean turnOffUpstreamMobileConnection() {
- // ignore pending renewal requests
- ++mCurrentConnectionSequence;
- if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
- getConnectivityManager().stopUsingNetworkFeature(
- ConnectivityManager.TYPE_MOBILE, enableString(mMobileApnReserved));
- mMobileApnReserved = ConnectivityManager.TYPE_NONE;
+ if (mMobileUpstreamCallback != null) {
+ // Looks like we already filed a request for this apnType.
+ return true;
}
+
+ switch (apnType) {
+ case ConnectivityManager.TYPE_MOBILE_DUN:
+ case ConnectivityManager.TYPE_MOBILE:
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ mMobileApnReserved = apnType;
+ break;
+ default:
+ return false;
+ }
+
+ NetworkRequest.Builder builder = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ if (apnType == ConnectivityManager.TYPE_MOBILE_DUN) {
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ } else {
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+ NetworkRequest mobileUpstreamRequest = builder.build();
+ // Other mechanisms notice network and interface changes and act upon them.
+ // TODO, imminently: replace with a proper NetworkCallback-based scheme.
+ //
+ // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
+ // moderate callback time (once timeout callbacks are implemented). This might
+ // be useful for updating some UI. Additionally, we should definitely log a
+ // message to aid in any subsequent debugging.
+ mMobileUpstreamCallback = new ConnectivityManager.NetworkCallback();
+ if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
+ getConnectivityManager().requestNetwork(
+ mobileUpstreamRequest, mMobileUpstreamCallback, 0, apnType);
+
return true;
}
+
+ protected void turnOffUpstreamMobileConnection() {
+ if (mMobileUpstreamCallback != null) {
+ getConnectivityManager().unregisterNetworkCallback(mMobileUpstreamCallback);
+ mMobileUpstreamCallback = null;
+ }
+ mMobileApnReserved = ConnectivityManager.TYPE_NONE;
+ }
+
protected boolean turnOnMasterTetherSettings() {
try {
mNMService.setIpForwardingEnabled(true);
@@ -1304,35 +1318,39 @@
}
if (DBG) {
- Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
- + mPreferredUpstreamMobileApn + ", got type=" + upType);
+ Log.d(TAG, "chooseUpstreamType(" + tryCell + "),"
+ + " preferredApn="
+ + ConnectivityManager.getNetworkTypeName(mPreferredUpstreamMobileApn)
+ + ", got type="
+ + ConnectivityManager.getNetworkTypeName(upType));
}
- // if we're on DUN, put our own grab on it
- if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
- upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
- turnOnUpstreamMobileConnection(upType);
- } else if (upType != ConnectivityManager.TYPE_NONE) {
- /* If we've found an active upstream connection that's not DUN/HIPRI
- * we should stop any outstanding DUN/HIPRI start requests.
- *
- * If we found NONE we don't want to do this as we want any previous
- * requests to keep trying to bring up something we can use.
- */
- turnOffUpstreamMobileConnection();
+ switch (upType) {
+ case ConnectivityManager.TYPE_MOBILE_DUN:
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ // If we're on DUN, put our own grab on it.
+ turnOnUpstreamMobileConnection(upType);
+ break;
+ case ConnectivityManager.TYPE_NONE:
+ if (tryCell &&
+ turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn)) {
+ // We think mobile should be coming up; don't set a retry.
+ } else {
+ sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
+ }
+ break;
+ default:
+ /* If we've found an active upstream connection that's not DUN/HIPRI
+ * we should stop any outstanding DUN/HIPRI start requests.
+ *
+ * If we found NONE we don't want to do this as we want any previous
+ * requests to keep trying to bring up something we can use.
+ */
+ turnOffUpstreamMobileConnection();
+ break;
}
- if (upType == ConnectivityManager.TYPE_NONE) {
- boolean tryAgainLater = true;
- if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
- (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
- // we think mobile should be coming up - don't set a retry
- tryAgainLater = false;
- }
- if (tryAgainLater) {
- sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
- }
- } else {
+ if (upType != ConnectivityManager.TYPE_NONE) {
LinkProperties linkProperties =
getConnectivityManager().getLinkProperties(upType);
if (linkProperties != null) {
@@ -1579,17 +1597,6 @@
chooseUpstreamType(mTryCell);
mTryCell = !mTryCell;
break;
- case CMD_CELL_CONNECTION_RENEW:
- // make sure we're still using a requested connection - may have found
- // wifi or something since then.
- if (mCurrentConnectionSequence == message.arg1) {
- if (VDBG) {
- Log.d(TAG, "renewing mobile connection - requeuing for another " +
- CELL_CONNECTION_RENEW_MS + "ms");
- }
- turnOnUpstreamMobileConnection(mMobileApnReserved);
- }
- break;
case CMD_RETRY_UPSTREAM:
chooseUpstreamType(mTryCell);
mTryCell = !mTryCell;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 946fbb1..38893b8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1286,10 +1286,11 @@
Binder.getCallingUid(), incomingUserId, true, false,
"getAppActiveNotifications", pkg);
- final int N = mNotificationList.size();
- final ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>(N);
+ final ArrayList<StatusBarNotification> list
+ = new ArrayList<StatusBarNotification>(mNotificationList.size());
synchronized (mNotificationList) {
+ final int N = mNotificationList.size();
for (int i = 0; i < N; i++) {
final StatusBarNotification sbn = mNotificationList.get(i).sbn;
if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId) {
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index b32ec2d..4861acc 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -109,7 +109,7 @@
public AppWindowAnimator(final AppWindowToken atoken) {
mAppToken = atoken;
mService = atoken.service;
- mAnimator = atoken.mAnimator;
+ mAnimator = mService.mAnimator;
}
public void setAnimation(Animation anim, int width, int height, boolean skipFirstFrame) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 425ff9b..77a29f3 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -24,6 +24,7 @@
import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
+import android.annotation.NonNull;
import android.content.pm.ActivityInfo;
import android.os.Message;
import android.os.RemoteException;
@@ -49,9 +50,7 @@
// All of the windows and child windows that are included in this
// application token. Note this list is NOT sorted!
final WindowList allAppWindows = new WindowList();
- final AppWindowAnimator mAppAnimator;
-
- final WindowAnimator mAnimator;
+ @NonNull final AppWindowAnimator mAppAnimator;
final boolean voiceInteraction;
@@ -145,7 +144,6 @@
appToken = _token;
voiceInteraction = _voiceInteraction;
mInputApplicationHandle = new InputApplicationHandle(this);
- mAnimator = service.mAnimator;
mAppAnimator = new AppWindowAnimator(this);
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 46fab2a..f20c4e5 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -220,8 +220,8 @@
if (appShowWhenLocked != null) {
allowWhenLocked |= appShowWhenLocked == win.mAppToken
- // Show all SHOW_WHEN_LOCKED windows while they're animating
- || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.isAnimatingLw()
+ // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
+ || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
// Show error dialogs over apps that dismiss keyguard.
|| (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8199250..d7afdf4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5567,8 +5567,8 @@
// InputMethodManager fetches input methods for current user.
// So this can only be set when calling user is the current user
// or parent is current user in case of managed profiles.
- InputMethodManager inputMethodManager = (InputMethodManager) mContext
- .getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager inputMethodManager =
+ mContext.getSystemService(InputMethodManager.class);
List<InputMethodInfo> enabledImes = inputMethodManager.getEnabledInputMethodList();
if (enabledImes != null) {
@@ -5646,8 +5646,8 @@
// If we have a permitted list add all system input methods.
if (result != null) {
- InputMethodManager inputMethodManager = (InputMethodManager) mContext
- .getSystemService(Context.INPUT_METHOD_SERVICE);
+ InputMethodManager inputMethodManager =
+ mContext.getSystemService(InputMethodManager.class);
List<InputMethodInfo> imes = inputMethodManager.getInputMethodList();
long id = mInjector.binderClearCallingIdentity();
try {
@@ -6823,6 +6823,9 @@
public boolean isProvisioningAllowed(String action) {
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
+ if (!hasFeatureManagedUsers()) {
+ return false;
+ }
synchronized (this) {
if (mOwners.hasDeviceOwner()) {
if (!mInjector.userManagerIsSplitSystemUser()) {
@@ -6845,13 +6848,6 @@
// Managed user cannot have a managed profile.
return false;
}
- try {
- if (!mIPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)) {
- return false;
- }
- } catch (RemoteException e) {
- return false;
- }
final long ident = mInjector.binderClearCallingIdentity();
try {
if (!mUserManager.canAddMoreManagedProfiles(callingUserId, true)) {
@@ -6864,10 +6860,17 @@
} else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE.equals(action)) {
return isDeviceOwnerProvisioningAllowed(callingUserId);
} else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_USER.equals(action)) {
+ if (!hasFeatureManagedUsers()) {
+ return false;
+ }
if (!mInjector.userManagerIsSplitSystemUser()) {
// ACTION_PROVISION_MANAGED_USER only supported on split-user systems.
return false;
}
+ if (callingUserId == UserHandle.USER_SYSTEM) {
+ // System user cannot be a managed user.
+ return false;
+ }
if (hasUserSetupCompleted(callingUserId)) {
return false;
}
@@ -6901,6 +6904,14 @@
return true;
}
+ private boolean hasFeatureManagedUsers() {
+ try {
+ return mIPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
@Override
public String getWifiMacAddress() {
// Make sure caller has DO.
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 97e16da..27deb72 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -591,6 +591,12 @@
public void setUp() throws Exception {
super.setUp();
+ // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
+ // http://b/25897652 .
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
mServiceContext = new MockContext(getContext());
mService = new WrappedConnectivityService(mServiceContext,
mock(INetworkManagementService.class),
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4115756..17bd08c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1805,6 +1805,13 @@
public void onReject(String replyMessage) {}
/**
+ * Notifies the Connection of a request to silence the ringer.
+ *
+ * @hide
+ */
+ public void onSilence() {}
+
+ /**
* Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes.
*/
public void onPostDialContinue(boolean proceed) {}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 6223495..b4a7ce0 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -102,6 +102,7 @@
private static final int MSG_MERGE_CONFERENCE = 18;
private static final int MSG_SWAP_CONFERENCE = 19;
private static final int MSG_REJECT_WITH_MESSAGE = 20;
+ private static final int MSG_SILENCE = 21;
private static Connection sNullConnection;
@@ -177,6 +178,11 @@
}
@Override
+ public void silence(String callId) {
+ mHandler.obtainMessage(MSG_SILENCE, callId).sendToTarget();
+ }
+
+ @Override
public void disconnect(String callId) {
mHandler.obtainMessage(MSG_DISCONNECT, callId).sendToTarget();
}
@@ -319,6 +325,9 @@
case MSG_DISCONNECT:
disconnect((String) msg.obj);
break;
+ case MSG_SILENCE:
+ silence((String) msg.obj);
+ break;
case MSG_HOLD:
hold((String) msg.obj);
break;
@@ -708,6 +717,11 @@
findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
}
+ private void silence(String callId) {
+ Log.d(this, "silence %s", callId);
+ findConnectionForAction(callId, "silence").onSilence();
+ }
+
private void disconnect(String callId) {
Log.d(this, "disconnect %s", callId);
if (mConnectionById.containsKey(callId)) {
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index dd253cf..8a54add 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -54,6 +54,8 @@
void disconnect(String callId);
+ void silence(String callId);
+
void hold(String callId);
void unhold(String callId);
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index e22e76d..fb0fe38 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1537,12 +1537,20 @@
std::queue<CompileResourceWorkItem>& workQueue = table.getWorkQueue();
while (!workQueue.empty()) {
CompileResourceWorkItem& workItem = workQueue.front();
- err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.file, &table, xmlFlags);
+ int xmlCompilationFlags = xmlFlags | XML_COMPILE_PARSE_VALUES
+ | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS;
+ if (!workItem.needsCompiling) {
+ xmlCompilationFlags &= ~XML_COMPILE_ASSIGN_ATTRIBUTE_IDS;
+ xmlCompilationFlags &= ~XML_COMPILE_PARSE_VALUES;
+ }
+ err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.xmlRoot,
+ workItem.file, &table, xmlCompilationFlags);
+
if (err == NO_ERROR) {
assets->addResource(workItem.resPath.getPathLeaf(),
- workItem.resPath,
- workItem.file,
- workItem.file->getResourceType());
+ workItem.resPath,
+ workItem.file,
+ workItem.file->getResourceType());
} else {
hasErrors = true;
}
@@ -1737,9 +1745,7 @@
manifestFile->getGroupEntry(),
manifestFile->getResourceType());
err = compileXmlFile(bundle, assets, String16(), manifestFile,
- outManifestFile, &table,
- XML_COMPILE_ASSIGN_ATTRIBUTE_IDS
- | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES);
+ outManifestFile, &table, XML_COMPILE_STANDARD_RESOURCE & ~XML_COMPILE_STRIP_COMMENTS);
if (err < NO_ERROR) {
return err;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index d5a09d8..0e470d9 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -88,8 +88,11 @@
root->setUTF8(true);
}
- bool hasErrors = false;
+ if (table->processBundleFormat(bundle, resourceName, target, root) != NO_ERROR) {
+ return UNKNOWN_ERROR;
+ }
+ bool hasErrors = false;
if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) {
status_t err = root->assignResourceIds(assets, table);
if (err != NO_ERROR) {
@@ -97,9 +100,11 @@
}
}
- status_t err = root->parseValues(assets, table);
- if (err != NO_ERROR) {
- hasErrors = true;
+ if ((options&XML_COMPILE_PARSE_VALUES) != 0) {
+ status_t err = root->parseValues(assets, table);
+ if (err != NO_ERROR) {
+ hasErrors = true;
+ }
}
if (hasErrors) {
@@ -114,7 +119,7 @@
printf("Input XML Resource:\n");
root->print();
}
- err = root->flatten(target,
+ status_t err = root->flatten(target,
(options&XML_COMPILE_STRIP_COMMENTS) != 0,
(options&XML_COMPILE_STRIP_RAW_VALUES) != 0);
if (err != NO_ERROR) {
@@ -4755,9 +4760,9 @@
newConfig.sdkVersion = sdkVersionToGenerate;
sp<AaptFile> newFile = new AaptFile(target->getSourceFile(),
AaptGroupEntry(newConfig), target->getResourceType());
- String8 resPath = String8::format("res/%s/%s",
+ String8 resPath = String8::format("res/%s/%s.xml",
newFile->getGroupEntry().toDirName(target->getResourceType()).string(),
- target->getSourceFile().getPathLeaf().string());
+ String8(resourceName).string());
resPath.convertToResPath();
// Add a resource table entry.
@@ -4784,9 +4789,11 @@
item.resourceName = resourceName;
item.resPath = resPath;
item.file = newFile;
+ item.xmlRoot = newRoot;
+ item.needsCompiling = false; // This step occurs after we parse/assign, so we don't need
+ // to do it again.
mWorkQueue.push(item);
}
-
return NO_ERROR;
}
@@ -4825,3 +4832,226 @@
}
}
}
+
+static String16 buildNamespace(const String16& package) {
+ return String16("http://schemas.android.com/apk/res/") + package;
+}
+
+static sp<XMLNode> findOnlyChildElement(const sp<XMLNode>& parent) {
+ const Vector<sp<XMLNode> >& children = parent->getChildren();
+ sp<XMLNode> onlyChild;
+ for (size_t i = 0; i < children.size(); i++) {
+ if (children[i]->getType() != XMLNode::TYPE_CDATA) {
+ if (onlyChild != NULL) {
+ return NULL;
+ }
+ onlyChild = children[i];
+ }
+ }
+ return onlyChild;
+}
+
+/**
+ * Detects use of the `bundle' format and extracts nested resources into their own top level
+ * resources. The bundle format looks like this:
+ *
+ * <!-- res/drawable/bundle.xml -->
+ * <animated-vector xmlns:aapt="http://schemas.android.com/aapt">
+ * <aapt:attr name="android:drawable">
+ * <vector android:width="60dp"
+ * android:height="60dp">
+ * <path android:name="v"
+ * android:fillColor="#000000"
+ * android:pathData="M300,70 l 0,-70 70,..." />
+ * </vector>
+ * </aapt:attr>
+ * </animated-vector>
+ *
+ * When AAPT sees the <aapt:attr> tag, it will extract its single element and its children
+ * into a new high-level resource, assigning it a name and ID. Then value of the `name`
+ * attribute must be a resource attribute. That resource attribute is inserted into the parent
+ * with the reference to the extracted resource as the value.
+ *
+ * <!-- res/drawable/bundle.xml -->
+ * <animated-vector android:drawable="@drawable/bundle_1.xml">
+ * </animated-vector>
+ *
+ * <!-- res/drawable/bundle_1.xml -->
+ * <vector android:width="60dp"
+ * android:height="60dp">
+ * <path android:name="v"
+ * android:fillColor="#000000"
+ * android:pathData="M300,70 l 0,-70 70,..." />
+ * </vector>
+ */
+status_t ResourceTable::processBundleFormat(const Bundle* bundle,
+ const String16& resourceName,
+ const sp<AaptFile>& target,
+ const sp<XMLNode>& root) {
+ Vector<sp<XMLNode> > namespaces;
+ if (root->getType() == XMLNode::TYPE_NAMESPACE) {
+ namespaces.push(root);
+ }
+ return processBundleFormatImpl(bundle, resourceName, target, root, &namespaces);
+}
+
+status_t ResourceTable::processBundleFormatImpl(const Bundle* bundle,
+ const String16& resourceName,
+ const sp<AaptFile>& target,
+ const sp<XMLNode>& parent,
+ Vector<sp<XMLNode> >* namespaces) {
+ const String16 kAaptNamespaceUri16("http://schemas.android.com/aapt");
+ const String16 kName16("name");
+ const String16 kAttr16("attr");
+ const String16 kAssetPackage16(mAssets->getPackage());
+
+ Vector<sp<XMLNode> >& children = parent->getChildren();
+ for (size_t i = 0; i < children.size(); i++) {
+ const sp<XMLNode>& child = children[i];
+
+ if (child->getType() == XMLNode::TYPE_CDATA) {
+ continue;
+ } else if (child->getType() == XMLNode::TYPE_NAMESPACE) {
+ namespaces->push(child);
+ }
+
+ if (child->getElementNamespace() != kAaptNamespaceUri16 ||
+ child->getElementName() != kAttr16) {
+ status_t result = processBundleFormatImpl(bundle, resourceName, target, child,
+ namespaces);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ if (child->getType() == XMLNode::TYPE_NAMESPACE) {
+ namespaces->pop();
+ }
+ continue;
+ }
+
+ // This is the <aapt:attr> tag. Look for the 'name' attribute.
+ SourcePos source(child->getFilename(), child->getStartLineNumber());
+
+ sp<XMLNode> nestedRoot = findOnlyChildElement(child);
+ if (nestedRoot == NULL) {
+ source.error("<%s:%s> must have exactly one child element",
+ String8(child->getElementNamespace()).string(),
+ String8(child->getElementName()).string());
+ return UNKNOWN_ERROR;
+ }
+
+ // Find the special attribute 'parent-attr'. This attribute's value contains
+ // the resource attribute for which this element should be assigned in the parent.
+ const XMLNode::attribute_entry* attr = child->getAttribute(String16(), kName16);
+ if (attr == NULL) {
+ source.error("inline resource definition must specify an attribute via 'name'");
+ return UNKNOWN_ERROR;
+ }
+
+ // Parse the attribute name.
+ const char* errorMsg = NULL;
+ String16 attrPackage, attrType, attrName;
+ bool result = ResTable::expandResourceRef(attr->string.string(),
+ attr->string.size(),
+ &attrPackage, &attrType, &attrName,
+ &kAttr16, &kAssetPackage16,
+ &errorMsg, NULL);
+ if (!result) {
+ source.error("invalid attribute name for 'name': %s", errorMsg);
+ return UNKNOWN_ERROR;
+ }
+
+ if (attrType != kAttr16) {
+ // The value of the 'name' attribute must be an attribute reference.
+ source.error("value of 'name' must be an attribute reference.");
+ return UNKNOWN_ERROR;
+ }
+
+ // Generate a name for this nested resource and try to add it to the table.
+ // We do this in a loop because the name may be taken, in which case we will
+ // increment a suffix until we succeed.
+ String8 nestedResourceName;
+ String8 nestedResourcePath;
+ int suffix = 1;
+ while (true) {
+ // This child element will be extracted into its own resource file.
+ // Generate a name and path for it from its parent.
+ nestedResourceName = String8::format("%s_%d",
+ String8(resourceName).string(), suffix++);
+ nestedResourcePath = String8::format("res/%s/%s.xml",
+ target->getGroupEntry().toDirName(target->getResourceType())
+ .string(),
+ nestedResourceName.string());
+
+ // Lookup or create the entry for this name.
+ sp<Entry> entry = getEntry(kAssetPackage16,
+ String16(target->getResourceType()),
+ String16(nestedResourceName),
+ source,
+ false,
+ &target->getGroupEntry().toParams(),
+ true);
+ if (entry == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (entry->getType() == Entry::TYPE_UNKNOWN) {
+ // The value for this resource has never been set,
+ // meaning we're good!
+ entry->setItem(source, String16(nestedResourcePath));
+ break;
+ }
+
+ // We failed (name already exists), so try with a different name
+ // (increment the suffix).
+ }
+
+ if (bundle->getVerbose()) {
+ source.printf("generating nested resource %s:%s/%s",
+ mAssets->getPackage().string(), target->getResourceType().string(),
+ nestedResourceName.string());
+ }
+
+ // Build the attribute reference and assign it to the parent.
+ String16 nestedResourceRef = String16(String8::format("@%s:%s/%s",
+ mAssets->getPackage().string(), target->getResourceType().string(),
+ nestedResourceName.string()));
+
+ String16 attrNs = buildNamespace(attrPackage);
+ if (parent->getAttribute(attrNs, attrName) != NULL) {
+ SourcePos(parent->getFilename(), parent->getStartLineNumber())
+ .error("parent of nested resource already defines attribute '%s:%s'",
+ String8(attrPackage).string(), String8(attrName).string());
+ return UNKNOWN_ERROR;
+ }
+
+ // Add the reference to the inline resource.
+ parent->addAttribute(attrNs, attrName, nestedResourceRef);
+
+ // Remove the <aapt:attr> child element from here.
+ children.removeAt(i);
+ i--;
+
+ // Append all namespace declarations that we've seen on this branch in the XML tree
+ // to this resource.
+ // We do this because the order of namespace declarations and prefix usage is determined
+ // by the developer and we do not want to override any decisions. Be conservative.
+ for (size_t nsIndex = namespaces->size(); nsIndex > 0; nsIndex--) {
+ const sp<XMLNode>& ns = namespaces->itemAt(nsIndex - 1);
+ sp<XMLNode> newNs = XMLNode::newNamespace(ns->getFilename(), ns->getNamespacePrefix(),
+ ns->getNamespaceUri());
+ newNs->addChild(nestedRoot);
+ nestedRoot = newNs;
+ }
+
+ // Schedule compilation of the nested resource.
+ CompileResourceWorkItem workItem;
+ workItem.resPath = nestedResourcePath;
+ workItem.resourceName = String16(nestedResourceName);
+ workItem.xmlRoot = nestedRoot;
+ workItem.file = new AaptFile(target->getSourceFile(), target->getGroupEntry(),
+ target->getResourceType());
+ mWorkQueue.push(workItem);
+ }
+ return NO_ERROR;
+}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index c4bdf09..4b7b3cd 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -23,13 +23,14 @@
enum {
XML_COMPILE_STRIP_COMMENTS = 1<<0,
XML_COMPILE_ASSIGN_ATTRIBUTE_IDS = 1<<1,
- XML_COMPILE_COMPACT_WHITESPACE = 1<<2,
- XML_COMPILE_STRIP_WHITESPACE = 1<<3,
- XML_COMPILE_STRIP_RAW_VALUES = 1<<4,
- XML_COMPILE_UTF8 = 1<<5,
+ XML_COMPILE_PARSE_VALUES = 1 << 2,
+ XML_COMPILE_COMPACT_WHITESPACE = 1<<3,
+ XML_COMPILE_STRIP_WHITESPACE = 1<<4,
+ XML_COMPILE_STRIP_RAW_VALUES = 1<<5,
+ XML_COMPILE_UTF8 = 1<<6,
XML_COMPILE_STANDARD_RESOURCE =
- XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS
+ XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS | XML_COMPILE_PARSE_VALUES
| XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES
};
@@ -83,6 +84,8 @@
String16 resourceName;
String8 resPath;
sp<AaptFile> file;
+ sp<XMLNode> xmlRoot;
+ bool needsCompiling = true;
};
class ResourceTable : public ResTable::Accessor
@@ -206,6 +209,12 @@
const sp<AaptFile>& file,
const sp<XMLNode>& root);
+ status_t processBundleFormat(const Bundle* bundle,
+ const String16& resourceName,
+ const sp<AaptFile>& file,
+ const sp<XMLNode>& parent);
+
+
sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
const bool isBase);
@@ -586,6 +595,11 @@
Res_value* outValue);
int getPublicAttributeSdkLevel(uint32_t attrId) const;
+ status_t processBundleFormatImpl(const Bundle* bundle,
+ const String16& resourceName,
+ const sp<AaptFile>& file,
+ const sp<XMLNode>& parent,
+ Vector<sp<XMLNode> >* namespaces);
String16 mAssetsPackage;
PackageType mPackageType;
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index dc08eb8..5b215da 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -693,6 +693,12 @@
return mChildren;
}
+
+Vector<sp<XMLNode> >& XMLNode::getChildren()
+{
+ return mChildren;
+}
+
const String8& XMLNode::getFilename() const
{
return mFilename;
@@ -717,6 +723,18 @@
return NULL;
}
+bool XMLNode::removeAttribute(const String16& ns, const String16& name)
+{
+ for (size_t i = 0; i < mAttributes.size(); i++) {
+ const attribute_entry& ae(mAttributes.itemAt(i));
+ if (ae.ns == ns && ae.name == name) {
+ removeAttribute(i);
+ return true;
+ }
+ }
+ return false;
+}
+
XMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns,
const String16& name)
{
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index b9e5cd5..749bf9f 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -55,7 +55,7 @@
sp<XMLNode> newCData(const String8& filename) {
return new XMLNode(filename);
}
-
+
enum type {
TYPE_NAMESPACE,
TYPE_ELEMENT,
@@ -70,6 +70,7 @@
const String16& getElementNamespace() const;
const String16& getElementName() const;
const Vector<sp<XMLNode> >& getChildren() const;
+ Vector<sp<XMLNode> >& getChildren();
const String8& getFilename() const;
@@ -97,6 +98,7 @@
const Vector<attribute_entry>& getAttributes() const;
const attribute_entry* getAttribute(const String16& ns, const String16& name) const;
+ bool removeAttribute(const String16& ns, const String16& name);
attribute_entry* editAttribute(const String16& ns, const String16& name);
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index 17a658e..90e35d5 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -22,6 +22,7 @@
#include "compile/IdAssigner.h"
#include "compile/Png.h"
#include "compile/XmlIdCollector.h"
+#include "flatten/Archive.h"
#include "flatten/FileExportWriter.h"
#include "flatten/TableFlattener.h"
#include "flatten/XmlFlattener.h"
@@ -31,6 +32,7 @@
#include "xml/XmlDom.h"
#include "xml/XmlPullParser.h"
+#include <dirent.h>
#include <fstream>
#include <string>
@@ -90,7 +92,7 @@
}
return ResourcePathData{
- Source{ path },
+ Source(path),
util::utf8ToUtf16(dirStr),
util::utf8ToUtf16(name),
extension.toString(),
@@ -101,25 +103,79 @@
struct CompileOptions {
std::string outputPath;
+ Maybe<std::string> resDir;
Maybe<std::u16string> product;
bool verbose = false;
};
-static std::string buildIntermediateFilename(const std::string outDir,
- const ResourcePathData& data) {
+static std::string buildIntermediateFilename(const ResourcePathData& data) {
std::stringstream name;
name << data.resourceDir;
if (!data.configStr.empty()) {
name << "-" << data.configStr;
}
name << "_" << data.name << "." << data.extension << ".flat";
- std::string outPath = outDir;
- file::appendPath(&outPath, name.str());
- return outPath;
+ return name.str();
+}
+
+static bool isHidden(const StringPiece& filename) {
+ return util::stringStartsWith<char>(filename, ".");
+}
+
+/**
+ * Walks the res directory structure, looking for resource files.
+ */
+static bool loadInputFilesFromDir(IAaptContext* context, const CompileOptions& options,
+ std::vector<ResourcePathData>* outPathData) {
+ const std::string& rootDir = options.resDir.value();
+ std::unique_ptr<DIR, decltype(closedir)*> d(opendir(rootDir.data()), closedir);
+ if (!d) {
+ context->getDiagnostics()->error(DiagMessage() << strerror(errno));
+ return false;
+ }
+
+ while (struct dirent* entry = readdir(d.get())) {
+ if (isHidden(entry->d_name)) {
+ continue;
+ }
+
+ std::string prefixPath = rootDir;
+ file::appendPath(&prefixPath, entry->d_name);
+
+ if (file::getFileType(prefixPath) != file::FileType::kDirectory) {
+ continue;
+ }
+
+ std::unique_ptr<DIR, decltype(closedir)*> subDir(opendir(prefixPath.data()), closedir);
+ if (!subDir) {
+ context->getDiagnostics()->error(DiagMessage() << strerror(errno));
+ return false;
+ }
+
+ while (struct dirent* leafEntry = readdir(subDir.get())) {
+ if (isHidden(leafEntry->d_name)) {
+ continue;
+ }
+
+ std::string fullPath = prefixPath;
+ file::appendPath(&fullPath, leafEntry->d_name);
+
+ std::string errStr;
+ Maybe<ResourcePathData> pathData = extractResourcePathData(fullPath, &errStr);
+ if (!pathData) {
+ context->getDiagnostics()->error(DiagMessage() << errStr);
+ return false;
+ }
+
+ outPathData->push_back(std::move(pathData.value()));
+ }
+ }
+ return true;
}
static bool compileTable(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& pathData, const std::string& outputPath) {
+ const ResourcePathData& pathData, IArchiveWriter* writer,
+ const std::string& outputPath) {
ResourceTable table;
{
std::ifstream fin(pathData.source.path, std::ifstream::binary);
@@ -150,6 +206,7 @@
// Ensure we have the compilation package at least.
table.createPackage(context->getCompilationPackage());
+ // Assign an ID to any package that has resources.
for (auto& pkg : table.packages) {
if (!pkg->id) {
// If no package ID was set while parsing (public identifiers), auto assign an ID.
@@ -172,23 +229,24 @@
return false;
}
- // Build the output filename.
- std::ofstream fout(outputPath, std::ofstream::binary);
- if (!fout) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
+ if (!writer->startEntry(outputPath, 0)) {
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to open");
return false;
}
- // Write it to disk.
- if (!util::writeAll(fout, buffer)) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
- return false;
+ if (writer->writeEntry(buffer)) {
+ if (writer->finishEntry()) {
+ return true;
+ }
}
- return true;
+
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to write");
+ return false;
}
static bool compileXml(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& pathData, const std::string& outputPath) {
+ const ResourcePathData& pathData, IArchiveWriter* writer,
+ const std::string& outputPath) {
std::unique_ptr<xml::XmlResource> xmlRes;
@@ -214,7 +272,7 @@
return false;
}
- xmlRes->file.name = ResourceName{ {}, *parseResourceType(pathData.resourceDir), pathData.name };
+ xmlRes->file.name = ResourceName({}, *parseResourceType(pathData.resourceDir), pathData.name);
xmlRes->file.config = pathData.config;
xmlRes->file.source = pathData.source;
@@ -230,25 +288,27 @@
fileExportWriter.finish();
- std::ofstream fout(outputPath, std::ofstream::binary);
- if (!fout) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
+ if (!writer->startEntry(outputPath, 0)) {
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to open");
return false;
}
- // Write it to disk.
- if (!util::writeAll(fout, buffer)) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
- return false;
+ if (writer->writeEntry(buffer)) {
+ if (writer->finishEntry()) {
+ return true;
+ }
}
- return true;
+
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to write");
+ return false;
}
static bool compilePng(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& pathData, const std::string& outputPath) {
+ const ResourcePathData& pathData, IArchiveWriter* writer,
+ const std::string& outputPath) {
BigBuffer buffer(4096);
ResourceFile resFile;
- resFile.name = ResourceName{ {}, *parseResourceType(pathData.resourceDir), pathData.name };
+ resFile.name = ResourceName({}, *parseResourceType(pathData.resourceDir), pathData.name);
resFile.config = pathData.config;
resFile.source = pathData.source;
@@ -269,24 +329,27 @@
fileExportWriter.finish();
- std::ofstream fout(outputPath, std::ofstream::binary);
- if (!fout) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
+ if (!writer->startEntry(outputPath, 0)) {
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to open");
return false;
}
- if (!util::writeAll(fout, buffer)) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
- return false;
+ if (writer->writeEntry(buffer)) {
+ if (writer->finishEntry()) {
+ return true;
+ }
}
- return true;
+
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to write");
+ return false;
}
static bool compileFile(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& pathData, const std::string& outputPath) {
+ const ResourcePathData& pathData, IArchiveWriter* writer,
+ const std::string& outputPath) {
BigBuffer buffer(256);
ResourceFile resFile;
- resFile.name = ResourceName{ {}, *parseResourceType(pathData.resourceDir), pathData.name };
+ resFile.name = ResourceName({}, *parseResourceType(pathData.resourceDir), pathData.name);
resFile.config = pathData.config;
resFile.source = pathData.source;
@@ -299,9 +362,8 @@
return false;
}
- std::ofstream fout(outputPath, std::ofstream::binary);
- if (!fout) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
+ if (!writer->startEntry(outputPath, 0)) {
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to open");
return false;
}
@@ -309,16 +371,17 @@
// the buffer the entire file.
fileExportWriter.getChunkHeader()->size =
util::hostToDevice32(buffer.size() + f.value().getDataLength());
- if (!util::writeAll(fout, buffer)) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
- return false;
+
+ if (writer->writeEntry(buffer)) {
+ if (writer->writeEntry(f.value().getDataPtr(), f.value().getDataLength())) {
+ if (writer->finishEntry()) {
+ return true;
+ }
+ }
}
- if (!fout.write((const char*) f.value().getDataPtr(), f.value().getDataLength())) {
- context->getDiagnostics()->error(DiagMessage(Source{ outputPath }) << strerror(errno));
- return false;
- }
- return true;
+ context->getDiagnostics()->error(DiagMessage(outputPath) << "failed to write");
+ return false;
}
class CompileContext : public IAaptContext {
@@ -359,6 +422,7 @@
Flags flags = Flags()
.requiredFlag("-o", "Output path", &options.outputPath)
.optionalFlag("--product", "Product type to compile", &product)
+ .optionalFlag("--dir", "Directory to scan for resources", &options.resDir)
.optionalSwitch("-v", "Enables verbose logging", &options.verbose);
if (!flags.parse("aapt2 compile", args, &std::cerr)) {
return 1;
@@ -369,19 +433,42 @@
}
CompileContext context;
+ std::unique_ptr<IArchiveWriter> archiveWriter;
std::vector<ResourcePathData> inputData;
- inputData.reserve(flags.getArgs().size());
-
- // Collect data from the path for each input file.
- for (const std::string& arg : flags.getArgs()) {
- std::string errorStr;
- if (Maybe<ResourcePathData> pathData = extractResourcePathData(arg, &errorStr)) {
- inputData.push_back(std::move(pathData.value()));
- } else {
- context.getDiagnostics()->error(DiagMessage() << errorStr << " (" << arg << ")");
+ if (options.resDir) {
+ if (!flags.getArgs().empty()) {
+ // Can't have both files and a resource directory.
+ context.getDiagnostics()->error(DiagMessage() << "files given but --dir specified");
+ flags.usage("aapt2 compile", &std::cerr);
return 1;
}
+
+ if (!loadInputFilesFromDir(&context, options, &inputData)) {
+ return 1;
+ }
+
+ archiveWriter = createZipFileArchiveWriter(context.getDiagnostics(), options.outputPath);
+
+ } else {
+ inputData.reserve(flags.getArgs().size());
+
+ // Collect data from the path for each input file.
+ for (const std::string& arg : flags.getArgs()) {
+ std::string errorStr;
+ if (Maybe<ResourcePathData> pathData = extractResourcePathData(arg, &errorStr)) {
+ inputData.push_back(std::move(pathData.value()));
+ } else {
+ context.getDiagnostics()->error(DiagMessage() << errorStr << " (" << arg << ")");
+ return 1;
+ }
+ }
+
+ archiveWriter = createDirectoryArchiveWriter(context.getDiagnostics(), options.outputPath);
+ }
+
+ if (!archiveWriter) {
+ return false;
}
bool error = false;
@@ -394,32 +481,34 @@
// Overwrite the extension.
pathData.extension = "arsc";
- const std::string outputFilename = buildIntermediateFilename(
- options.outputPath, pathData);
- if (!compileTable(&context, options, pathData, outputFilename)) {
+ const std::string outputFilename = buildIntermediateFilename(pathData);
+ if (!compileTable(&context, options, pathData, archiveWriter.get(), outputFilename)) {
error = true;
}
} else {
- const std::string outputFilename = buildIntermediateFilename(options.outputPath,
- pathData);
+ const std::string outputFilename = buildIntermediateFilename(pathData);
if (const ResourceType* type = parseResourceType(pathData.resourceDir)) {
if (*type != ResourceType::kRaw) {
if (pathData.extension == "xml") {
- if (!compileXml(&context, options, pathData, outputFilename)) {
+ if (!compileXml(&context, options, pathData, archiveWriter.get(),
+ outputFilename)) {
error = true;
}
} else if (pathData.extension == "png" || pathData.extension == "9.png") {
- if (!compilePng(&context, options, pathData, outputFilename)) {
+ if (!compilePng(&context, options, pathData, archiveWriter.get(),
+ outputFilename)) {
error = true;
}
} else {
- if (!compileFile(&context, options, pathData, outputFilename)) {
+ if (!compileFile(&context, options, pathData, archiveWriter.get(),
+ outputFilename)) {
error = true;
}
}
} else {
- if (!compileFile(&context, options, pathData, outputFilename)) {
+ if (!compileFile(&context, options, pathData, archiveWriter.get(),
+ outputFilename)) {
error = true;
}
}
diff --git a/tools/aapt2/flatten/Archive.cpp b/tools/aapt2/flatten/Archive.cpp
index 6db13b8..3a244c0 100644
--- a/tools/aapt2/flatten/Archive.cpp
+++ b/tools/aapt2/flatten/Archive.cpp
@@ -18,7 +18,7 @@
#include "util/Files.h"
#include "util/StringPiece.h"
-#include <fstream>
+#include <cstdio>
#include <memory>
#include <string>
#include <vector>
@@ -30,70 +30,85 @@
struct DirectoryWriter : public IArchiveWriter {
std::string mOutDir;
- std::vector<std::unique_ptr<ArchiveEntry>> mEntries;
+ std::unique_ptr<FILE, decltype(fclose)*> mFile = { nullptr, fclose };
- explicit DirectoryWriter(const StringPiece& outDir) : mOutDir(outDir.toString()) {
+ bool open(IDiagnostics* diag, const StringPiece& outDir) {
+ mOutDir = outDir.toString();
+ file::FileType type = file::getFileType(mOutDir);
+ if (type == file::FileType::kNonexistant) {
+ diag->error(DiagMessage() << "directory " << mOutDir << " does not exist");
+ return false;
+ } else if (type != file::FileType::kDirectory) {
+ diag->error(DiagMessage() << mOutDir << " is not a directory");
+ return false;
+ }
+ return true;
}
- ArchiveEntry* writeEntry(const StringPiece& path, uint32_t flags,
- const BigBuffer& buffer) override {
+ bool startEntry(const StringPiece& path, uint32_t flags) override {
+ if (mFile) {
+ return false;
+ }
+
std::string fullPath = mOutDir;
file::appendPath(&fullPath, path);
file::mkdirs(file::getStem(fullPath));
- std::ofstream fout(fullPath, std::ofstream::binary);
- if (!fout) {
- return nullptr;
+ mFile = { fopen(fullPath.data(), "wb"), fclose };
+ if (!mFile) {
+ return false;
}
-
- if (!util::writeAll(fout, buffer)) {
- return nullptr;
- }
-
- mEntries.push_back(util::make_unique<ArchiveEntry>(fullPath, flags, buffer.size()));
- return mEntries.back().get();
+ return true;
}
- ArchiveEntry* writeEntry(const StringPiece& path, uint32_t flags, android::FileMap* fileMap,
- size_t offset, size_t len) override {
- std::string fullPath = mOutDir;
- file::appendPath(&fullPath, path);
- file::mkdirs(file::getStem(fullPath));
-
- std::ofstream fout(fullPath, std::ofstream::binary);
- if (!fout) {
- return nullptr;
+ bool writeEntry(const BigBuffer& buffer) override {
+ if (!mFile) {
+ return false;
}
- if (!fout.write((const char*) fileMap->getDataPtr() + offset, len)) {
- return nullptr;
+ for (const BigBuffer::Block& b : buffer) {
+ if (fwrite(b.buffer.get(), 1, b.size, mFile.get()) != b.size) {
+ mFile.reset(nullptr);
+ return false;
+ }
}
-
- mEntries.push_back(util::make_unique<ArchiveEntry>(fullPath, flags, len));
- return mEntries.back().get();
+ return true;
}
- virtual ~DirectoryWriter() {
+ bool writeEntry(const void* data, size_t len) override {
+ if (fwrite(data, 1, len, mFile.get()) != len) {
+ mFile.reset(nullptr);
+ return false;
+ }
+ return true;
+ }
+ bool finishEntry() override {
+ if (!mFile) {
+ return false;
+ }
+ mFile.reset(nullptr);
+ return true;
}
};
struct ZipFileWriter : public IArchiveWriter {
- FILE* mFile;
+ std::unique_ptr<FILE, decltype(fclose)*> mFile = { nullptr, fclose };
std::unique_ptr<ZipWriter> mWriter;
- std::vector<std::unique_ptr<ArchiveEntry>> mEntries;
- explicit ZipFileWriter(const StringPiece& path) {
- mFile = fopen(path.data(), "w+b");
- if (mFile) {
- mWriter = util::make_unique<ZipWriter>(mFile);
+ bool open(IDiagnostics* diag, const StringPiece& path) {
+ mFile = { fopen(path.data(), "w+b"), fclose };
+ if (!mFile) {
+ diag->error(DiagMessage() << "failed to open " << path << ": " << strerror(errno));
+ return false;
}
+ mWriter = util::make_unique<ZipWriter>(mFile.get());
+ return true;
}
- ArchiveEntry* writeEntry(const StringPiece& path, uint32_t flags,
- const BigBuffer& buffer) override {
+ bool startEntry(const StringPiece& path, uint32_t flags) override {
if (!mWriter) {
- return nullptr;
+ return false;
}
size_t zipFlags = 0;
@@ -107,75 +122,63 @@
int32_t result = mWriter->StartEntry(path.data(), zipFlags);
if (result != 0) {
- return nullptr;
+ return false;
}
+ return true;
+ }
+ bool writeEntry(const void* data, size_t len) override {
+ int32_t result = mWriter->WriteBytes(data, len);
+ if (result != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ bool writeEntry(const BigBuffer& buffer) override {
for (const BigBuffer::Block& b : buffer) {
- result = mWriter->WriteBytes(reinterpret_cast<const uint8_t*>(b.buffer.get()), b.size);
+ int32_t result = mWriter->WriteBytes(b.buffer.get(), b.size);
if (result != 0) {
- return nullptr;
+ return false;
}
}
-
- result = mWriter->FinishEntry();
- if (result != 0) {
- return nullptr;
- }
-
- mEntries.push_back(util::make_unique<ArchiveEntry>(path.toString(), flags, buffer.size()));
- return mEntries.back().get();
+ return true;
}
- ArchiveEntry* writeEntry(const StringPiece& path, uint32_t flags, android::FileMap* fileMap,
- size_t offset, size_t len) override {
- if (!mWriter) {
- return nullptr;
- }
-
- size_t zipFlags = 0;
- if (flags & ArchiveEntry::kCompress) {
- zipFlags |= ZipWriter::kCompress;
- }
-
- if (flags & ArchiveEntry::kAlign) {
- zipFlags |= ZipWriter::kAlign32;
- }
-
- int32_t result = mWriter->StartEntry(path.data(), zipFlags);
+ bool finishEntry() override {
+ int32_t result = mWriter->FinishEntry();
if (result != 0) {
- return nullptr;
+ return false;
}
-
- result = mWriter->WriteBytes((const char*) fileMap->getDataPtr() + offset, len);
- if (result != 0) {
- return nullptr;
- }
-
- result = mWriter->FinishEntry();
- if (result != 0) {
- return nullptr;
- }
-
- mEntries.push_back(util::make_unique<ArchiveEntry>(path.toString(), flags, len));
- return mEntries.back().get();
+ return true;
}
virtual ~ZipFileWriter() {
if (mWriter) {
mWriter->Finish();
- fclose(mFile);
}
}
};
} // namespace
-std::unique_ptr<IArchiveWriter> createDirectoryArchiveWriter(const StringPiece& path) {
- return util::make_unique<DirectoryWriter>(path);
+std::unique_ptr<IArchiveWriter> createDirectoryArchiveWriter(IDiagnostics* diag,
+ const StringPiece& path) {
+
+ std::unique_ptr<DirectoryWriter> writer = util::make_unique<DirectoryWriter>();
+ if (!writer->open(diag, path)) {
+ return {};
+ }
+ return std::move(writer);
}
-std::unique_ptr<IArchiveWriter> createZipFileArchiveWriter(const StringPiece& path) {
- return util::make_unique<ZipFileWriter>(path);
+std::unique_ptr<IArchiveWriter> createZipFileArchiveWriter(IDiagnostics* diag,
+ const StringPiece& path) {
+ std::unique_ptr<ZipFileWriter> writer = util::make_unique<ZipFileWriter>();
+ if (!writer->open(diag, path)) {
+ return {};
+ }
+ return std::move(writer);
}
} // namespace aapt
diff --git a/tools/aapt2/flatten/Archive.h b/tools/aapt2/flatten/Archive.h
index c4ddeb3..6da1d2a 100644
--- a/tools/aapt2/flatten/Archive.h
+++ b/tools/aapt2/flatten/Archive.h
@@ -17,6 +17,7 @@
#ifndef AAPT_FLATTEN_ARCHIVE_H
#define AAPT_FLATTEN_ARCHIVE_H
+#include "Diagnostics.h"
#include "util/BigBuffer.h"
#include "util/Files.h"
#include "util/StringPiece.h"
@@ -42,15 +43,17 @@
struct IArchiveWriter {
virtual ~IArchiveWriter() = default;
- virtual ArchiveEntry* writeEntry(const StringPiece& path, uint32_t flags,
- const BigBuffer& buffer) = 0;
- virtual ArchiveEntry* writeEntry(const StringPiece& path, uint32_t flags,
- android::FileMap* fileMap, size_t offset, size_t len) = 0;
+ virtual bool startEntry(const StringPiece& path, uint32_t flags) = 0;
+ virtual bool writeEntry(const BigBuffer& buffer) = 0;
+ virtual bool writeEntry(const void* data, size_t len) = 0;
+ virtual bool finishEntry() = 0;
};
-std::unique_ptr<IArchiveWriter> createDirectoryArchiveWriter(const StringPiece& path);
+std::unique_ptr<IArchiveWriter> createDirectoryArchiveWriter(IDiagnostics* diag,
+ const StringPiece& path);
-std::unique_ptr<IArchiveWriter> createZipFileArchiveWriter(const StringPiece& path);
+std::unique_ptr<IArchiveWriter> createZipFileArchiveWriter(IDiagnostics* diag,
+ const StringPiece& path);
} // namespace aapt
diff --git a/tools/aapt2/io/Data.h b/tools/aapt2/io/Data.h
new file mode 100644
index 0000000..9081c55
--- /dev/null
+++ b/tools/aapt2/io/Data.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_IO_DATA_H
+#define AAPT_IO_DATA_H
+
+#include <utils/FileMap.h>
+
+#include <memory>
+
+namespace aapt {
+namespace io {
+
+/**
+ * Interface for a block of contiguous memory. An instance of this interface owns the data.
+ */
+class IData {
+public:
+ virtual ~IData() = default;
+
+ virtual const void* data() const = 0;
+ virtual size_t size() const = 0;
+};
+
+/**
+ * Implementation of IData that exposes a memory mapped file. The mmapped file is owned by this
+ * object.
+ */
+class MmappedData : public IData {
+public:
+ explicit MmappedData(android::FileMap&& map) : mMap(std::forward<android::FileMap>(map)) {
+ }
+
+ const void* data() const override {
+ return mMap.getDataPtr();
+ }
+
+ size_t size() const override {
+ return mMap.getDataLength();
+ }
+
+private:
+ android::FileMap mMap;
+};
+
+/**
+ * Implementation of IData that exposes a block of memory that was malloc'ed (new'ed). The
+ * memory is owned by this object.
+ */
+class MallocData : public IData {
+public:
+ MallocData(std::unique_ptr<const uint8_t[]> data, size_t size) :
+ mData(std::move(data)), mSize(size) {
+ }
+
+ const void* data() const override {
+ return mData.get();
+ }
+
+ size_t size() const override {
+ return mSize;
+ }
+
+private:
+ std::unique_ptr<const uint8_t[]> mData;
+ size_t mSize;
+};
+
+} // namespace io
+} // namespace aapt
+
+#endif /* AAPT_IO_DATA_H */
diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h
new file mode 100644
index 0000000..9fca398
--- /dev/null
+++ b/tools/aapt2/io/File.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_IO_FILE_H
+#define AAPT_IO_FILE_H
+
+#include "Source.h"
+#include "io/Data.h"
+
+#include <memory>
+#include <vector>
+
+namespace aapt {
+namespace io {
+
+/**
+ * Interface for a file, which could be a real file on the file system, or a file inside
+ * a ZIP archive.
+ */
+class IFile {
+public:
+ virtual ~IFile() = default;
+
+ /**
+ * Open the file and return it as a block of contiguous memory. How this occurs is
+ * implementation dependent. For example, if this is a file on the file system, it may
+ * simply mmap the contents. If this file represents a compressed file in a ZIP archive,
+ * it may need to inflate it to memory, incurring a copy.
+ *
+ * Returns nullptr on failure.
+ */
+ virtual std::unique_ptr<IData> openAsData() = 0;
+
+ /**
+ * Returns the source of this file. This is for presentation to the user and may not be a
+ * valid file system path (for example, it may contain a '@' sign to separate the files within
+ * a ZIP archive from the path to the containing ZIP archive.
+ */
+ virtual const Source& getSource() const = 0;
+};
+
+/**
+ * Interface for a collection of files, all of which share a common source. That source may
+ * simply be the filesystem, or a ZIP archive.
+ */
+class IFileCollection {
+public:
+ virtual ~IFileCollection() = default;
+
+ using const_iterator = std::vector<std::unique_ptr<IFile>>::const_iterator;
+
+ virtual const_iterator begin() const = 0;
+ virtual const_iterator end() const = 0;
+};
+
+} // namespace io
+} // namespace aapt
+
+#endif /* AAPT_IO_FILE_H */
diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h
new file mode 100644
index 0000000..5dbefcc
--- /dev/null
+++ b/tools/aapt2/io/FileSystem.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_IO_FILESYSTEM_H
+#define AAPT_IO_FILESYSTEM_H
+
+#include "io/File.h"
+#include "util/Files.h"
+
+namespace aapt {
+namespace io {
+
+/**
+ * A regular file from the file system. Uses mmap to open the data.
+ */
+class RegularFile : public IFile {
+public:
+ RegularFile(const Source& source) : mSource(source) {
+ }
+
+ std::unique_ptr<IData> openAsData() override {
+ android::FileMap map;
+ if (Maybe<android::FileMap> map = file::mmapPath(mSource.path, nullptr)) {
+ return util::make_unique<MmappedData>(std::move(map.value()));
+ }
+ return {};
+ }
+
+ const Source& getSource() const override {
+ return mSource;
+ }
+
+private:
+ Source mSource;
+};
+
+/**
+ * An IFileCollection representing the file system.
+ */
+class FileCollection : public IFileCollection {
+public:
+ /**
+ * Adds a file located at path. Returns the IFile representation of that file.
+ */
+ IFile* insertFile(const StringPiece& path) {
+ mFiles.push_back(util::make_unique<RegularFile>(Source(path)));
+ return mFiles.back().get();
+ }
+
+ const_iterator begin() const override {
+ return mFiles.begin();
+ }
+
+ const_iterator end() const override {
+ return mFiles.end();
+ }
+
+private:
+ std::vector<std::unique_ptr<IFile>> mFiles;
+};
+
+} // namespace io
+} // namespace aapt
+
+#endif // AAPT_IO_FILESYSTEM_H
diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h
new file mode 100644
index 0000000..98afc49
--- /dev/null
+++ b/tools/aapt2/io/ZipArchive.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_IO_ZIPARCHIVE_H
+#define AAPT_IO_ZIPARCHIVE_H
+
+#include "io/File.h"
+#include "util/StringPiece.h"
+
+#include <utils/FileMap.h>
+#include <ziparchive/zip_archive.h>
+
+namespace aapt {
+namespace io {
+
+/**
+ * An IFile representing a file within a ZIP archive. If the file is compressed, it is uncompressed
+ * and copied into memory when opened. Otherwise it is mmapped from the ZIP archive.
+ */
+class ZipFile : public IFile {
+public:
+ ZipFile(ZipArchiveHandle handle, const ZipEntry& entry, const Source& source) :
+ mZipHandle(handle), mZipEntry(entry), mSource(source) {
+ }
+
+ std::unique_ptr<IData> openAsData() override {
+ if (mZipEntry.method == kCompressStored) {
+ int fd = GetFileDescriptor(mZipHandle);
+
+ android::FileMap fileMap;
+ bool result = fileMap.create(nullptr, fd, mZipEntry.offset,
+ mZipEntry.uncompressed_length, true);
+ if (!result) {
+ return {};
+ }
+ return util::make_unique<MmappedData>(std::move(fileMap));
+
+ } else {
+ std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(
+ new uint8_t[mZipEntry.uncompressed_length]);
+ int32_t result = ExtractToMemory(mZipHandle, &mZipEntry, data.get(),
+ static_cast<uint32_t>(mZipEntry.uncompressed_length));
+ if (result != 0) {
+ return {};
+ }
+ return util::make_unique<MallocData>(std::move(data), mZipEntry.uncompressed_length);
+ }
+ }
+
+ const Source& getSource() const override {
+ return mSource;
+ }
+
+private:
+ ZipArchiveHandle mZipHandle;
+ ZipEntry mZipEntry;
+ Source mSource;
+};
+
+/**
+ * An IFileCollection that represents a ZIP archive and the entries within it.
+ */
+class ZipFileCollection : public IFileCollection {
+public:
+ static std::unique_ptr<ZipFileCollection> create(const StringPiece& path,
+ std::string* outError) {
+ std::unique_ptr<ZipFileCollection> collection = std::unique_ptr<ZipFileCollection>(
+ new ZipFileCollection());
+
+ int32_t result = OpenArchive(path.data(), &collection->mHandle);
+ if (result != 0) {
+ if (outError) *outError = ErrorCodeString(result);
+ return {};
+ }
+
+ ZipString suffix(".flat");
+ void* cookie = nullptr;
+ result = StartIteration(collection->mHandle, &cookie, nullptr, &suffix);
+ if (result != 0) {
+ if (outError) *outError = ErrorCodeString(result);
+ return {};
+ }
+
+ using IterationEnder = std::unique_ptr<void, decltype(EndIteration)*>;
+ IterationEnder iterationEnder(cookie, EndIteration);
+
+ ZipString zipEntryName;
+ ZipEntry zipData;
+ while ((result = Next(cookie, &zipData, &zipEntryName)) == 0) {
+ std::string nestedPath = path.toString();
+ nestedPath += "@" + std::string(reinterpret_cast<const char*>(zipEntryName.name),
+ zipEntryName.name_length);
+ collection->mFiles.push_back(util::make_unique<ZipFile>(collection->mHandle,
+ zipData,
+ Source(nestedPath)));
+ }
+
+ if (result != -1) {
+ if (outError) *outError = ErrorCodeString(result);
+ return {};
+ }
+ return collection;
+ }
+
+ const_iterator begin() const override {
+ return mFiles.begin();
+ }
+
+ const_iterator end() const override {
+ return mFiles.end();
+ }
+
+ ~ZipFileCollection() override {
+ if (mHandle) {
+ CloseArchive(mHandle);
+ }
+ }
+
+private:
+ ZipFileCollection() : mHandle(nullptr) {
+ }
+
+ ZipArchiveHandle mHandle;
+ std::vector<std::unique_ptr<IFile>> mFiles;
+};
+
+} // namespace io
+} // namespace aapt
+
+#endif /* AAPT_IO_ZIPARCHIVE_H */
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 9850ae5..33d9272 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -22,6 +22,8 @@
#include "flatten/Archive.h"
#include "flatten/TableFlattener.h"
#include "flatten/XmlFlattener.h"
+#include "io/FileSystem.h"
+#include "io/ZipArchive.h"
#include "java/JavaClassGenerator.h"
#include "java/ManifestClassGenerator.h"
#include "java/ProguardRules.h"
@@ -39,7 +41,6 @@
#include <fstream>
#include <sys/stat.h>
-#include <utils/FileMap.h>
#include <vector>
namespace aapt {
@@ -92,7 +93,15 @@
class LinkCommand {
public:
LinkCommand(const LinkOptions& options) :
- mOptions(options), mContext(), mFinalTable() {
+ mOptions(options), mContext(), mFinalTable(), mFileCollection(nullptr) {
+ std::unique_ptr<io::FileCollection> fileCollection =
+ util::make_unique<io::FileCollection>();
+
+ // Get a pointer to the FileCollection for convenience, but it will be owned by the vector.
+ mFileCollection = fileCollection.get();
+
+ // Move it to the collection.
+ mCollections.push_back(std::move(fileCollection));
}
std::string buildResourceFileName(const ResourceFile& resFile) {
@@ -136,20 +145,9 @@
return builder.build();
}
- /**
- * Loads the resource table (not inside an apk) at the given path.
- */
- std::unique_ptr<ResourceTable> loadTable(const std::string& input) {
- std::string errorStr;
- Maybe<android::FileMap> map = file::mmapPath(input, &errorStr);
- if (!map) {
- mContext.getDiagnostics()->error(DiagMessage(input) << errorStr);
- return {};
- }
-
+ std::unique_ptr<ResourceTable> loadTable(const Source& source, const void* data, size_t len) {
std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
- BinaryResourceParser parser(&mContext, table.get(), Source(input),
- map.value().getDataPtr(), map.value().getDataLength());
+ BinaryResourceParser parser(&mContext, table.get(), source, data, len);
if (!parser.parse()) {
return {};
}
@@ -159,90 +157,79 @@
/**
* Inflates an XML file from the source path.
*/
- std::unique_ptr<xml::XmlResource> loadXml(const std::string& path) {
+ static std::unique_ptr<xml::XmlResource> loadXml(const std::string& path, IDiagnostics* diag) {
std::ifstream fin(path, std::ifstream::binary);
if (!fin) {
- mContext.getDiagnostics()->error(DiagMessage(path) << strerror(errno));
+ diag->error(DiagMessage(path) << strerror(errno));
return {};
}
- return xml::inflate(&fin, mContext.getDiagnostics(), Source(path));
+ return xml::inflate(&fin, diag, Source(path));
}
- /**
- * Inflates a binary XML file from the source path.
- */
- std::unique_ptr<xml::XmlResource> loadBinaryXmlSkipFileExport(const std::string& path) {
- // Read header for symbol info and export info.
+ static std::unique_ptr<xml::XmlResource> loadBinaryXmlSkipFileExport(
+ const Source& source,
+ const void* data, size_t len,
+ IDiagnostics* diag) {
std::string errorStr;
- Maybe<android::FileMap> maybeF = file::mmapPath(path, &errorStr);
- if (!maybeF) {
- mContext.getDiagnostics()->error(DiagMessage(path) << errorStr);
- return {};
- }
-
- ssize_t offset = getWrappedDataOffset(maybeF.value().getDataPtr(),
- maybeF.value().getDataLength(), &errorStr);
+ ssize_t offset = getWrappedDataOffset(data, len, &errorStr);
if (offset < 0) {
- mContext.getDiagnostics()->error(DiagMessage(path) << errorStr);
+ diag->error(DiagMessage(source) << errorStr);
return {};
}
std::unique_ptr<xml::XmlResource> xmlRes = xml::inflate(
- (const uint8_t*) maybeF.value().getDataPtr() + (size_t) offset,
- maybeF.value().getDataLength() - offset,
- mContext.getDiagnostics(), Source(path));
+ reinterpret_cast<const uint8_t*>(data) + static_cast<size_t>(offset),
+ len - static_cast<size_t>(offset),
+ diag,
+ source);
if (!xmlRes) {
return {};
}
return xmlRes;
}
- Maybe<ResourceFile> loadFileExportHeader(const std::string& path) {
- // Read header for symbol info and export info.
+ static std::unique_ptr<ResourceFile> loadFileExportHeader(const Source& source,
+ const void* data, size_t len,
+ IDiagnostics* diag) {
+ std::unique_ptr<ResourceFile> resFile = util::make_unique<ResourceFile>();
std::string errorStr;
- Maybe<android::FileMap> maybeF = file::mmapPath(path, &errorStr);
- if (!maybeF) {
- mContext.getDiagnostics()->error(DiagMessage(path) << errorStr);
- return {};
- }
-
- ResourceFile resFile;
- ssize_t offset = unwrapFileExportHeader(maybeF.value().getDataPtr(),
- maybeF.value().getDataLength(),
- &resFile, &errorStr);
+ ssize_t offset = unwrapFileExportHeader(data, len, resFile.get(), &errorStr);
if (offset < 0) {
- mContext.getDiagnostics()->error(DiagMessage(path) << errorStr);
+ diag->error(DiagMessage(source) << errorStr);
return {};
}
- return std::move(resFile);
+ return resFile;
}
- bool copyFileToArchive(const std::string& path, const std::string& outPath, uint32_t flags,
+ bool copyFileToArchive(io::IFile* file, const std::string& outPath, uint32_t flags,
IArchiveWriter* writer) {
+ std::unique_ptr<io::IData> data = file->openAsData();
+ if (!data) {
+ mContext.getDiagnostics()->error(DiagMessage(file->getSource())
+ << "failed to open file");
+ return false;
+ }
+
std::string errorStr;
- Maybe<android::FileMap> maybeF = file::mmapPath(path, &errorStr);
- if (!maybeF) {
- mContext.getDiagnostics()->error(DiagMessage(path) << errorStr);
- return false;
- }
-
- ssize_t offset = getWrappedDataOffset(maybeF.value().getDataPtr(),
- maybeF.value().getDataLength(),
- &errorStr);
+ ssize_t offset = getWrappedDataOffset(data->data(), data->size(), &errorStr);
if (offset < 0) {
- mContext.getDiagnostics()->error(DiagMessage(path) << errorStr);
+ mContext.getDiagnostics()->error(DiagMessage(file->getSource()) << errorStr);
return false;
}
- ArchiveEntry* entry = writer->writeEntry(outPath, flags, &maybeF.value(),
- offset, maybeF.value().getDataLength() - offset);
- if (!entry) {
- mContext.getDiagnostics()->error(
- DiagMessage(mOptions.outputPath) << "failed to write file " << outPath);
- return false;
+ if (writer->startEntry(outPath, flags)) {
+ if (writer->writeEntry(reinterpret_cast<const uint8_t*>(data->data()) + offset,
+ data->size() - static_cast<size_t>(offset))) {
+ if (writer->finishEntry()) {
+ return true;
+ }
+ }
}
- return true;
+
+ mContext.getDiagnostics()->error(
+ DiagMessage(mOptions.outputPath) << "failed to write file " << outPath);
+ return false;
}
Maybe<AppInfo> extractAppInfoFromManifest(xml::XmlResource* xmlRes) {
@@ -285,9 +272,9 @@
std::unique_ptr<IArchiveWriter> makeArchiveWriter() {
if (mOptions.outputToDirectory) {
- return createDirectoryArchiveWriter(mOptions.outputPath);
+ return createDirectoryArchiveWriter(mContext.getDiagnostics(), mOptions.outputPath);
} else {
- return createZipFileArchiveWriter(mOptions.outputPath);
+ return createZipFileArchiveWriter(mContext.getDiagnostics(), mOptions.outputPath);
}
}
@@ -300,13 +287,17 @@
return false;
}
- ArchiveEntry* entry = writer->writeEntry("resources.arsc", ArchiveEntry::kAlign, buffer);
- if (!entry) {
- mContext.getDiagnostics()->error(
- DiagMessage() << "failed to write resources.arsc to archive");
- return false;
+ if (writer->startEntry("resources.arsc", ArchiveEntry::kAlign)) {
+ if (writer->writeEntry(buffer)) {
+ if (writer->finishEntry()) {
+ return true;
+ }
+ }
}
- return true;
+
+ mContext.getDiagnostics()->error(
+ DiagMessage() << "failed to write resources.arsc to archive");
+ return false;
}
bool flattenXml(xml::XmlResource* xmlRes, const StringPiece& path, Maybe<size_t> maxSdkLevel,
@@ -320,13 +311,17 @@
return false;
}
- ArchiveEntry* entry = writer->writeEntry(path, ArchiveEntry::kCompress, buffer);
- if (!entry) {
- mContext.getDiagnostics()->error(
- DiagMessage() << "failed to write " << path << " to archive");
- return false;
+
+ if (writer->startEntry(path, ArchiveEntry::kCompress)) {
+ if (writer->writeEntry(buffer)) {
+ if (writer->finishEntry()) {
+ return true;
+ }
+ }
}
- return true;
+ mContext.getDiagnostics()->error(
+ DiagMessage() << "failed to write " << path << " to archive");
+ return false;
}
bool writeJavaFile(ResourceTable* table, const StringPiece16& packageNameToGenerate,
@@ -412,34 +407,44 @@
return true;
}
- bool mergeResourceTable(const std::string& input, bool override) {
+ bool mergeResourceTable(io::IFile* file, bool override) {
if (mOptions.verbose) {
- mContext.getDiagnostics()->note(DiagMessage() << "linking " << input);
+ mContext.getDiagnostics()->note(DiagMessage() << "linking " << file->getSource());
}
- std::unique_ptr<ResourceTable> table = loadTable(input);
+ std::unique_ptr<io::IData> data = file->openAsData();
+ if (!data) {
+ mContext.getDiagnostics()->error(DiagMessage(file->getSource())
+ << "failed to open file");
+ return false;
+ }
+
+ std::unique_ptr<ResourceTable> table = loadTable(file->getSource(), data->data(),
+ data->size());
if (!table) {
return false;
}
- if (!mTableMerger->merge(Source(input), table.get(), override)) {
+ if (!mTableMerger->merge(file->getSource(), table.get(), override)) {
return false;
}
return true;
}
- bool mergeCompiledFile(const std::string& input, ResourceFile&& file, bool override) {
- if (file.name.package.empty()) {
- file.name.package = mContext.getCompilationPackage().toString();
+ bool mergeCompiledFile(io::IFile* file, std::unique_ptr<ResourceFile> fileDesc, bool override) {
+ // Apply the package name used for this compilation phase if none was specified.
+ if (fileDesc->name.package.empty()) {
+ fileDesc->name.package = mContext.getCompilationPackage().toString();
}
- ResourceNameRef resName = file.name;
-
- Maybe<ResourceName> mangledName = mContext.getNameMangler()->mangleName(file.name);
+ // Mangle the name if necessary.
+ ResourceNameRef resName = fileDesc->name;
+ Maybe<ResourceName> mangledName = mContext.getNameMangler()->mangleName(fileDesc->name);
if (mangledName) {
resName = mangledName.value();
}
+ // If we are overriding resources, we supply a custom resolver function.
std::function<int(Value*,Value*)> resolver;
if (override) {
resolver = [](Value* a, Value* b) -> int {
@@ -456,14 +461,14 @@
}
// Add this file to the table.
- if (!mFinalTable.addFileReference(resName, file.config, file.source,
- util::utf8ToUtf16(buildResourceFileName(file)),
+ if (!mFinalTable.addFileReference(resName, fileDesc->config, fileDesc->source,
+ util::utf8ToUtf16(buildResourceFileName(*fileDesc)),
resolver, mContext.getDiagnostics())) {
return false;
}
// Add the exports of this file to the table.
- for (SourcedResourceName& exportedSymbol : file.exportedSymbols) {
+ for (SourcedResourceName& exportedSymbol : fileDesc->exportedSymbols) {
if (exportedSymbol.name.package.empty()) {
exportedSymbol.name.package = mContext.getCompilationPackage().toString();
}
@@ -477,32 +482,78 @@
}
std::unique_ptr<Id> id = util::make_unique<Id>();
- id->setSource(file.source.withLine(exportedSymbol.line));
+ id->setSource(fileDesc->source.withLine(exportedSymbol.line));
bool result = mFinalTable.addResourceAllowMangled(resName, {}, std::move(id),
- mContext.getDiagnostics());
+ mContext.getDiagnostics());
if (!result) {
return false;
}
}
- mFilesToProcess.insert(FileToProcess{ std::move(file), Source(input) });
+ // Now add this file for later processing. Once the table is assigned IDs, we can compile
+ // this file.
+ mFilesToProcess.insert(FileToProcess{ std::move(fileDesc), file });
return true;
}
- bool processFile(const std::string& input, bool override) {
- if (util::stringEndsWith<char>(input, ".apk")) {
- return mergeStaticLibrary(input);
- } else if (util::stringEndsWith<char>(input, ".arsc.flat")) {
- return mergeResourceTable(input, override);
- } else if (Maybe<ResourceFile> maybeF = loadFileExportHeader(input)) {
- return mergeCompiledFile(input, std::move(maybeF.value()), override);
+ /**
+ * Creates an io::IFileCollection from the ZIP archive and processes the files within.
+ */
+ bool mergeArchive(const std::string& input, bool override) {
+ std::string errorStr;
+ std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
+ input, &errorStr);
+ if (!collection) {
+ mContext.getDiagnostics()->error(DiagMessage(input) << errorStr);
+ return false;
+ }
+
+ bool error = false;
+ for (const std::unique_ptr<io::IFile>& file : *collection) {
+ if (!processFile(file.get(), override)) {
+ error = true;
+ }
+ }
+
+ // Make sure to move the collection into the set of IFileCollections.
+ mCollections.push_back(std::move(collection));
+ return !error;
+ }
+
+ bool processFile(const std::string& path, bool override) {
+ if (util::stringEndsWith<char>(path, ".flata")) {
+ return mergeArchive(path, override);
+ }
+
+ io::IFile* file = mFileCollection->insertFile(path);
+ return processFile(file, override);
+ }
+
+ bool processFile(io::IFile* file, bool override) {
+ const Source& src = file->getSource();
+ if (util::stringEndsWith<char>(src.path, ".arsc.flat")) {
+ return mergeResourceTable(file, override);
+ } else {
+ // Try opening the file and looking for an Export header.
+ std::unique_ptr<io::IData> data = file->openAsData();
+ if (!data) {
+ mContext.getDiagnostics()->error(DiagMessage(src) << "failed to open");
+ return false;
+ }
+
+ std::unique_ptr<ResourceFile> resourceFile = loadFileExportHeader(
+ src, data->data(), data->size(), mContext.getDiagnostics());
+ if (resourceFile) {
+ return mergeCompiledFile(file, std::move(resourceFile), override);
+ }
}
return false;
}
int run(const std::vector<std::string>& inputFiles) {
// Load the AndroidManifest.xml
- std::unique_ptr<xml::XmlResource> manifestXml = loadXml(mOptions.manifestPath);
+ std::unique_ptr<xml::XmlResource> manifestXml = loadXml(mOptions.manifestPath,
+ mContext.getDiagnostics());
if (!manifestXml) {
return 1;
}
@@ -648,20 +699,30 @@
}
for (const FileToProcess& file : mFilesToProcess) {
- if (file.file.name.type != ResourceType::kRaw &&
- util::stringEndsWith<char>(file.source.path, ".xml.flat")) {
+ const StringPiece path = file.file->getSource().path;
+
+ if (file.fileExport->name.type != ResourceType::kRaw &&
+ util::stringEndsWith<char>(path, ".xml.flat")) {
if (mOptions.verbose) {
- mContext.getDiagnostics()->note(DiagMessage()
- << "linking " << file.source.path);
+ mContext.getDiagnostics()->note(DiagMessage() << "linking " << path);
+ }
+
+ std::unique_ptr<io::IData> data = file.file->openAsData();
+ if (!data) {
+ mContext.getDiagnostics()->error(DiagMessage(file.file->getSource())
+ << "failed to open file");
+ return 1;
}
std::unique_ptr<xml::XmlResource> xmlRes = loadBinaryXmlSkipFileExport(
- file.source.path);
+ file.file->getSource(), data->data(), data->size(),
+ mContext.getDiagnostics());
if (!xmlRes) {
return 1;
}
- xmlRes->file = std::move(file.file);
+ // Move the file description over.
+ xmlRes->file = std::move(*file.fileExport);
XmlReferenceLinker xmlLinker;
if (xmlLinker.consume(&mContext, xmlRes.get())) {
@@ -689,12 +750,13 @@
xmlRes->file.config,
sdkLevel)) {
xmlRes->file.config.sdkVersion = sdkLevel;
- if (!mFinalTable.addFileReference(xmlRes->file.name,
- xmlRes->file.config,
- xmlRes->file.source,
- util::utf8ToUtf16(
- buildResourceFileName(xmlRes->file)),
- mContext.getDiagnostics())) {
+ bool added = mFinalTable.addFileReference(
+ xmlRes->file.name,
+ xmlRes->file.config,
+ xmlRes->file.source,
+ util::utf8ToUtf16(buildResourceFileName(xmlRes->file)),
+ mContext.getDiagnostics());
+ if (!added) {
error = true;
continue;
}
@@ -712,11 +774,10 @@
}
} else {
if (mOptions.verbose) {
- mContext.getDiagnostics()->note(DiagMessage() << "copying "
- << file.source.path);
+ mContext.getDiagnostics()->note(DiagMessage() << "copying " << path);
}
- if (!copyFileToArchive(file.source.path, buildResourceFileName(file.file), 0,
+ if (!copyFileToArchive(file.file, buildResourceFileName(*file.fileExport), 0,
archiveWriter.get())) {
error = true;
}
@@ -802,14 +863,18 @@
ResourceTable mFinalTable;
std::unique_ptr<TableMerger> mTableMerger;
+ io::FileCollection* mFileCollection;
+ std::vector<std::unique_ptr<io::IFileCollection>> mCollections;
+
struct FileToProcess {
- ResourceFile file;
- Source source;
+ std::unique_ptr<ResourceFile> fileExport;
+ io::IFile* file;
};
struct FileToProcessComparator {
bool operator()(const FileToProcess& a, const FileToProcess& b) {
- return std::tie(a.file.name, a.file.config) < std::tie(b.file.name, b.file.config);
+ return std::tie(a.fileExport->name, a.fileExport->config) <
+ std::tie(b.fileExport->name, b.fileExport->config);
}
};