diff options
146 files changed, 3372 insertions, 2143 deletions
diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java index 1e426d62e4e0..b9fedd365925 100644 --- a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java +++ b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java @@ -33,6 +33,10 @@ public final class LockSettingsCmd extends BaseCommand { " locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n" + " locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n" + " locksettings clear [--old OLD_CREDENTIAL]\n" + + " locksettings verify [--old OLD_CREDENTIAL]\n" + + "\n" + + "flags: \n" + + " --user USER_ID: specify the user, default value is current user\n" + "\n" + "locksettings set-pattern: sets a pattern\n" + " A pattern is specified by a non-separated list of numbers that index the cell\n" + @@ -44,7 +48,9 @@ public final class LockSettingsCmd extends BaseCommand { "\n" + "locksettings set-password: sets a password\n" + "\n" + - "locksettings clear: clears the unlock credential\n"; + "locksettings clear: clears the unlock credential\n" + + "\n" + + "locksettings verify: verifies the credential and unlocks the user\n"; public static void main(String[] args) { (new LockSettingsCmd()).run(args); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 199e856e7a22..06dbe8218450 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -360,6 +360,13 @@ public class ActivityManager { FIRST_START_NON_FATAL_ERROR_CODE + 1; /** + * Result for IActivityManaqer.startActivity: a new activity start was aborted. Never returned + * externally. + * @hide + */ + public static final int START_ABORTED = FIRST_START_NON_FATAL_ERROR_CODE + 2; + + /** * Flag for IActivityManaqer.startActivity: do special start mode where * a new activity is launched only if it is needed. * @hide diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 358787e66428..e9c958857d5c 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -20,12 +20,10 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.os.UserManager; import android.util.DisplayMetrics; -import android.util.Log; /** * A representation of an activity that can belong to this user or a managed @@ -173,12 +171,6 @@ public class LauncherActivityInfo { public Drawable getBadgedIcon(int density) { Drawable originalIcon = getIcon(density); - if (originalIcon instanceof BitmapDrawable) { - // TODO: Go through LauncherAppsService - return mPm.getUserBadgedIcon(originalIcon, mUser); - } else { - Log.e(TAG, "Unable to create badged icon for " + mActivityInfo); - } - return originalIcon; + return mPm.getUserBadgedIcon(originalIcon, mUser); } } diff --git a/core/java/android/hardware/radio/RadioModule.java b/core/java/android/hardware/radio/RadioModule.java deleted file mode 100644 index c0df0f386b09..000000000000 --- a/core/java/android/hardware/radio/RadioModule.java +++ /dev/null @@ -1,234 +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 android.hardware.radio; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.UUID; - -/** - * A RadioModule implements the RadioTuner interface for a broadcast radio tuner physically - * present on the device and exposed by the radio HAL. - * - * @hide - */ -public class RadioModule extends RadioTuner { - private long mNativeContext = 0; - private int mId; - private NativeEventHandlerDelegate mEventHandlerDelegate; - - RadioModule(int moduleId, RadioManager.BandConfig config, boolean withAudio, - RadioTuner.Callback callback, Handler handler) { - mId = moduleId; - mEventHandlerDelegate = new NativeEventHandlerDelegate(callback, handler); - native_setup(new WeakReference<RadioModule>(this), config, withAudio); - } - private native void native_setup(Object module_this, - RadioManager.BandConfig config, boolean withAudio); - - @Override - protected void finalize() { - native_finalize(); - } - private native void native_finalize(); - - boolean initCheck() { - return mNativeContext != 0; - } - - // RadioTuner implementation - public native void close(); - - public native int setConfiguration(RadioManager.BandConfig config); - - public native int getConfiguration(RadioManager.BandConfig[] config); - - public native int setMute(boolean mute); - - public native boolean getMute(); - - public native int step(int direction, boolean skipSubChannel); - - public native int scan(int direction, boolean skipSubChannel); - - public native int tune(int channel, int subChannel); - - public native int cancel(); - - public native int getProgramInformation(RadioManager.ProgramInfo[] info); - - public native boolean startBackgroundScan(); - - public native @NonNull List<RadioManager.ProgramInfo> getProgramList(@Nullable String filter); - - public native boolean isAnalogForced(); - - public native void setAnalogForced(boolean isForced); - - public native boolean isAntennaConnected(); - - public native boolean hasControl(); - - - /* keep in sync with radio_event_type_t in system/core/include/system/radio.h */ - static final int EVENT_HW_FAILURE = 0; - static final int EVENT_CONFIG = 1; - static final int EVENT_ANTENNA = 2; - static final int EVENT_TUNED = 3; - static final int EVENT_METADATA = 4; - static final int EVENT_TA = 5; - static final int EVENT_AF_SWITCH = 6; - static final int EVENT_EA = 7; - static final int EVENT_CONTROL = 100; - static final int EVENT_SERVER_DIED = 101; - - private class NativeEventHandlerDelegate { - private final Handler mHandler; - - NativeEventHandlerDelegate(final RadioTuner.Callback callback, - Handler handler) { - // find the looper for our new event handler - Looper looper; - if (handler != null) { - looper = handler.getLooper(); - } else { - looper = Looper.getMainLooper(); - } - - // construct the event handler with this looper - if (looper != null) { - // implement the event handler delegate - mHandler = new Handler(looper) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case EVENT_HW_FAILURE: - if (callback != null) { - callback.onError(RadioTuner.ERROR_HARDWARE_FAILURE); - } - break; - case EVENT_CONFIG: { - RadioManager.BandConfig config = (RadioManager.BandConfig)msg.obj; - switch(msg.arg1) { - case RadioManager.STATUS_OK: - if (callback != null) { - callback.onConfigurationChanged(config); - } - break; - default: - if (callback != null) { - callback.onError(RadioTuner.ERROR_CONFIG); - } - break; - } - } break; - case EVENT_ANTENNA: - if (callback != null) { - callback.onAntennaState(msg.arg2 == 1); - } - break; - case EVENT_AF_SWITCH: - case EVENT_TUNED: { - RadioManager.ProgramInfo info = (RadioManager.ProgramInfo)msg.obj; - switch (msg.arg1) { - case RadioManager.STATUS_OK: - if (callback != null) { - callback.onProgramInfoChanged(info); - } - break; - case RadioManager.STATUS_TIMED_OUT: - if (callback != null) { - callback.onError(RadioTuner.ERROR_SCAN_TIMEOUT); - } - break; - case RadioManager.STATUS_INVALID_OPERATION: - default: - if (callback != null) { - callback.onError(RadioTuner.ERROR_CANCELLED); - } - break; - } - } break; - case EVENT_METADATA: { - RadioMetadata metadata = (RadioMetadata)msg.obj; - if (callback != null) { - callback.onMetadataChanged(metadata); - } - } break; - case EVENT_TA: - if (callback != null) { - callback.onTrafficAnnouncement(msg.arg2 == 1); - } - break; - case EVENT_EA: - if (callback != null) { - callback.onEmergencyAnnouncement(msg.arg2 == 1); - } - case EVENT_CONTROL: - if (callback != null) { - callback.onControlChanged(msg.arg2 == 1); - } - break; - case EVENT_SERVER_DIED: - if (callback != null) { - callback.onError(RadioTuner.ERROR_SERVER_DIED); - } - break; - default: - // Should not happen - break; - } - } - }; - } else { - mHandler = null; - } - } - - Handler handler() { - return mHandler; - } - } - - - @SuppressWarnings("unused") - private static void postEventFromNative(Object module_ref, - int what, int arg1, int arg2, Object obj) { - RadioModule module = (RadioModule)((WeakReference)module_ref).get(); - if (module == null) { - return; - } - - NativeEventHandlerDelegate delegate = module.mEventHandlerDelegate; - if (delegate != null) { - Handler handler = delegate.handler(); - if (handler != null) { - Message m = handler.obtainMessage(what, arg1, arg2, obj); - handler.sendMessage(m); - } - } - } -} - diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 50b4f8c7facf..56d6e0a62f94 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -369,11 +369,11 @@ public class FileUtils { * constraints remain. * * @param minCount Always keep at least this many files. - * @param minAge Always keep files younger than this age. + * @param minAgeMs Always keep files younger than this age, in milliseconds. * @return if any files were deleted. */ - public static boolean deleteOlderFiles(File dir, int minCount, long minAge) { - if (minCount < 0 || minAge < 0) { + public static boolean deleteOlderFiles(File dir, int minCount, long minAgeMs) { + if (minCount < 0 || minAgeMs < 0) { throw new IllegalArgumentException("Constraints must be positive or 0"); } @@ -393,9 +393,9 @@ public class FileUtils { for (int i = minCount; i < files.length; i++) { final File file = files[i]; - // Keep files newer than minAge + // Keep files newer than minAgeMs final long age = System.currentTimeMillis() - file.lastModified(); - if (age > minAge) { + if (age > minAgeMs) { if (file.delete()) { Log.d(TAG, "Deleted old file " + file); deleted = true; diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java index d921ed409d6c..f9030124cc63 100644 --- a/core/java/android/provider/AlarmClock.java +++ b/core/java/android/provider/AlarmClock.java @@ -82,7 +82,8 @@ public final class AlarmClock { * If neither of the above are given then: * <ul> * <li>If exactly one active alarm exists, it is dismissed. - * <li>If more than one active alarm exists, the user is prompted to choose the alarm to dismiss. + * <li>If more than one active alarm exists, the user is prompted to choose the alarm to + * dismiss. * </ul> * </p><p> * If the extra {@link #EXTRA_ALARM_SEARCH_MODE} is used, and the search results contain two or @@ -104,8 +105,7 @@ public final class AlarmClock { * @see #EXTRA_ALARM_SEARCH_MODE */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_DISMISS_ALARM = - "android.intent.action.DISMISS_ALARM"; + public static final String ACTION_DISMISS_ALARM = "android.intent.action.DISMISS_ALARM"; /** * Activity Action: Snooze a currently ringing alarm. @@ -124,8 +124,7 @@ public final class AlarmClock { * @see #EXTRA_ALARM_SNOOZE_DURATION */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SNOOZE_ALARM = - "android.intent.action.SNOOZE_ALARM"; + public static final String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM"; /** * Activity Action: Set a timer. @@ -155,6 +154,16 @@ public final class AlarmClock { public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER"; /** + * Activity Action: Dismiss timers. + * <p> + * Dismiss all currently expired timers. If there are no expired timers, then this is a no-op. + * </p> + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_DISMISS_TIMER = "android.intent.action.DISMISS_TIMER"; + + /** * Activity Action: Show the timers. * <p> * This action opens the timers page. @@ -200,8 +209,7 @@ public final class AlarmClock { * @see #ALARM_SEARCH_MODE_LABEL * @see #ACTION_DISMISS_ALARM */ - public static final String EXTRA_ALARM_SEARCH_MODE = - "android.intent.extra.alarm.SEARCH_MODE"; + public static final String EXTRA_ALARM_SEARCH_MODE = "android.intent.extra.alarm.SEARCH_MODE"; /** * Search for the alarm that is most closely matched by the search parameters diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index 875f286e1a6b..26f85288699a 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -97,6 +97,10 @@ public abstract class EuiccService extends Service { public static final String ACTION_RESOLVE_NO_PRIVILEGES = "android.service.euicc.action.RESOLVE_NO_PRIVILEGES"; + /** Intent extra set for resolution requests containing the package name of the calling app. */ + public static final String EXTRA_RESOLUTION_CALLING_PACKAGE = + "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE"; + /** Result code for a successful operation. */ public static final int RESULT_OK = 0; /** Result code indicating that an active SIM must be deactivated to perform the operation. */ diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index f6653fbfc08c..bf25915df211 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -208,9 +208,6 @@ public class PopupWindow { private int mGravity = Gravity.NO_GRAVITY; - // Title provided to accessibility services - private CharSequence mAccessibilityTitle; - private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] { com.android.internal.R.attr.state_above_anchor }; @@ -1134,31 +1131,6 @@ public class PopupWindow { return mIsShowing; } - /** - * Set the title for this window to be reported to accessibility services. If no title is set, - * a generic default will be reported. - * - * @param accessibilityTitle The new title, or {@code null} to specify that the default should - * be used. - * @hide - */ - public void setAccessibilityTitle(@Nullable CharSequence accessibilityTitle) { - mAccessibilityTitle = accessibilityTitle; - } - - /** - * Get the title for this window to be reported to accessibility services. - * - * @return The current title. - * @hide - */ - public @NonNull CharSequence getAccessibilityTitle() { - if (mAccessibilityTitle == null) { - mAccessibilityTitle = mContext.getString(R.string.popup_window_default_title); - } - return mAccessibilityTitle; - } - /** @hide */ protected final void setShowing(boolean isShowing) { mIsShowing = isShowing; @@ -1362,6 +1334,10 @@ public class PopupWindow { + "calling setContentView() before attempting to show the popup."); } + if (p.accessibilityTitle == null) { + p.accessibilityTitle = mContext.getString(R.string.popup_window_default_title); + } + // The old decor view may be transitioning out. Make sure it finishes // and cleans up before we try to create another one. if (mDecorView != null) { @@ -1524,7 +1500,6 @@ public class PopupWindow { // Used for debugging. p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); - p.accessibilityTitle = getAccessibilityTitle(); return p; } diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java index f76b702a1ccc..543bd0c4913d 100644 --- a/core/java/com/android/internal/backup/LocalTransport.java +++ b/core/java/com/android/internal/backup/LocalTransport.java @@ -30,6 +30,7 @@ import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.StructStat; +import android.util.ArrayMap; import android.util.Log; import com.android.org.bouncycastle.util.encoders.Base64; @@ -44,7 +45,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import static android.system.OsConstants.SEEK_CUR; /** * Backup transport for stashing stuff into a known location on disk, and @@ -70,9 +70,8 @@ public class LocalTransport extends BackupTransport { // The currently-active restore set always has the same (nonzero!) token private static final long CURRENT_SET_TOKEN = 1; - // Full backup size quota is set to reasonable value. + // Size quotas at reasonable values, similar to the current cloud-storage limits private static final long FULL_BACKUP_SIZE_QUOTA = 25 * 1024 * 1024; - private static final long KEY_VALUE_BACKUP_SIZE_QUOTA = 5 * 1024 * 1024; private Context mContext; @@ -157,6 +156,17 @@ public class LocalTransport extends BackupTransport { return TRANSPORT_OK; } + // Encapsulation of a single k/v element change + private class KVOperation { + final String key; // Element filename, not the raw key, for efficiency + final byte[] value; // null when this is a deletion operation + + KVOperation(String k, byte[] v) { + key = k; + value = v; + } + } + @Override public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) { if (DEBUG) { @@ -175,62 +185,135 @@ public class LocalTransport extends BackupTransport { // Each 'record' in the restore set is kept in its own file, named by // the record key. Wind through the data file, extracting individual - // record operations and building a set of all the updates to apply + // record operations and building a list of all the updates to apply // in this update. - BackupDataInput changeSet = new BackupDataInput(data.getFileDescriptor()); + final ArrayList<KVOperation> changeOps; try { - int bufSize = 512; - byte[] buf = new byte[bufSize]; - while (changeSet.readNextHeader()) { - String key = changeSet.getKey(); - String base64Key = new String(Base64.encode(key.getBytes())); - File entityFile = new File(packageDir, base64Key); + changeOps = parseBackupStream(data); + } catch (IOException e) { + // oops, something went wrong. abort the operation and return error. + Log.v(TAG, "Exception reading backup input", e); + return TRANSPORT_ERROR; + } - int dataSize = changeSet.getDataSize(); + // Okay, now we've parsed out the delta's individual operations. We need to measure + // the effect against what we already have in the datastore to detect quota overrun. + // So, we first need to tally up the current in-datastore size per key. + final ArrayMap<String, Integer> datastore = new ArrayMap<>(); + int totalSize = parseKeySizes(packageDir, datastore); - if (DEBUG) Log.v(TAG, "Got change set key=" + key + " size=" + dataSize - + " key64=" + base64Key); + // ... and now figure out the datastore size that will result from applying the + // sequence of delta operations + if (DEBUG) { + if (changeOps.size() > 0) { + Log.v(TAG, "Calculating delta size impact"); + } else { + Log.v(TAG, "No operations in backup stream, so no size change"); + } + } + int updatedSize = totalSize; + for (KVOperation op : changeOps) { + // Deduct the size of the key we're about to replace, if any + final Integer curSize = datastore.get(op.key); + if (curSize != null) { + updatedSize -= curSize.intValue(); + if (DEBUG && op.value == null) { + Log.v(TAG, " delete " + op.key + ", updated total " + updatedSize); + } + } - if (dataSize >= 0) { - if (entityFile.exists()) { - entityFile.delete(); - } - FileOutputStream entity = new FileOutputStream(entityFile); + // And add back the size of the value we're about to store, if any + if (op.value != null) { + updatedSize += op.value.length; + if (DEBUG) { + Log.v(TAG, ((curSize == null) ? " new " : " replace ") + + op.key + ", updated total " + updatedSize); + } + } + } - if (dataSize > bufSize) { - bufSize = dataSize; - buf = new byte[bufSize]; - } - changeSet.readEntityData(buf, 0, dataSize); - if (DEBUG) { - try { - long cur = Os.lseek(data.getFileDescriptor(), 0, SEEK_CUR); - Log.v(TAG, " read entity data; new pos=" + cur); - } - catch (ErrnoException e) { - Log.w(TAG, "Unable to stat input file in performBackup() on " - + packageInfo.packageName); - } - } + // If our final size is over quota, report the failure + if (updatedSize > KEY_VALUE_BACKUP_SIZE_QUOTA) { + if (DEBUG) { + Log.i(TAG, "New datastore size " + updatedSize + + " exceeds quota " + KEY_VALUE_BACKUP_SIZE_QUOTA); + } + return TRANSPORT_QUOTA_EXCEEDED; + } - try { - entity.write(buf, 0, dataSize); - } catch (IOException e) { - Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath()); - return TRANSPORT_ERROR; - } finally { - entity.close(); - } - } else { - entityFile.delete(); + // No problem with storage size, so go ahead and apply the delta operations + // (in the order that the app provided them) + for (KVOperation op : changeOps) { + File element = new File(packageDir, op.key); + + // this is either a deletion or a rewrite-from-zero, so we can just remove + // the existing file and proceed in either case. + element.delete(); + + // if this wasn't a deletion, put the new data in place + if (op.value != null) { + try (FileOutputStream out = new FileOutputStream(element)) { + out.write(op.value, 0, op.value.length); + } catch (IOException e) { + Log.e(TAG, "Unable to update key file " + element); + return TRANSPORT_ERROR; } } - return TRANSPORT_OK; - } catch (IOException e) { - // oops, something went wrong. abort the operation and return error. - Log.v(TAG, "Exception reading backup input:", e); - return TRANSPORT_ERROR; } + return TRANSPORT_OK; + } + + // Parses a backup stream into individual key/value operations + private ArrayList<KVOperation> parseBackupStream(ParcelFileDescriptor data) + throws IOException { + ArrayList<KVOperation> changeOps = new ArrayList<>(); + BackupDataInput changeSet = new BackupDataInput(data.getFileDescriptor()); + while (changeSet.readNextHeader()) { + String key = changeSet.getKey(); + String base64Key = new String(Base64.encode(key.getBytes())); + int dataSize = changeSet.getDataSize(); + if (DEBUG) { + Log.v(TAG, " Delta operation key " + key + " size " + dataSize + + " key64 " + base64Key); + } + + byte[] buf = (dataSize >= 0) ? new byte[dataSize] : null; + if (dataSize >= 0) { + changeSet.readEntityData(buf, 0, dataSize); + } + changeOps.add(new KVOperation(base64Key, buf)); + } + return changeOps; + } + + // Reads the given datastore directory, building a table of the value size of each + // keyed element, and returning the summed total. + private int parseKeySizes(File packageDir, ArrayMap<String, Integer> datastore) { + int totalSize = 0; + final String[] elements = packageDir.list(); + if (elements != null) { + if (DEBUG) { + Log.v(TAG, "Existing datastore contents:"); + } + for (String file : elements) { + File element = new File(packageDir, file); + String key = file; // filename + int size = (int) element.length(); + totalSize += size; + if (DEBUG) { + Log.v(TAG, " key " + key + " size " + size); + } + datastore.put(key, size); + } + if (DEBUG) { + Log.v(TAG, " TOTAL: " + totalSize); + } + } else { + if (DEBUG) { + Log.v(TAG, "No existing data for this package"); + } + } + return totalSize; } // Deletes the contents but not the given directory diff --git a/core/jni/Android.bp b/core/jni/Android.bp index c5279e10d93f..51851690c08d 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -162,7 +162,6 @@ cc_library_shared { "android_hardware_camera2_DngCreator.cpp", "android_hardware_display_DisplayViewport.cpp", "android_hardware_HardwareBuffer.cpp", - "android_hardware_Radio.cpp", "android_hardware_SensorManager.cpp", "android_hardware_SerialPort.cpp", "android_hardware_SoundTrigger.cpp", @@ -258,12 +257,10 @@ cc_library_shared { "libpdfium", "libimg_utils", "libnetd_client", - "libradio", "libsoundtrigger", "libminikin", "libprocessgroup", "libnativebridge", - "libradio_metadata", "libnativeloader", "libmemunreachable", "libhidlbase", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 659f47debaf1..92bc16055931 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -88,7 +88,6 @@ extern int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv *e extern int register_android_hardware_camera2_legacy_PerfMeasurement(JNIEnv *env); extern int register_android_hardware_camera2_DngCreator(JNIEnv *env); extern int register_android_hardware_HardwareBuffer(JNIEnv *env); -extern int register_android_hardware_Radio(JNIEnv *env); extern int register_android_hardware_SensorManager(JNIEnv *env); extern int register_android_hardware_SerialPort(JNIEnv *env); extern int register_android_hardware_SoundTrigger(JNIEnv *env); @@ -1402,7 +1401,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_hardware_camera2_legacy_PerfMeasurement), REG_JNI(register_android_hardware_camera2_DngCreator), REG_JNI(register_android_hardware_HardwareBuffer), - REG_JNI(register_android_hardware_Radio), REG_JNI(register_android_hardware_SensorManager), REG_JNI(register_android_hardware_SerialPort), REG_JNI(register_android_hardware_SoundTrigger), diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp index 5553a3ed22c5..4b6578bdff7f 100644 --- a/core/jni/android/graphics/ColorFilter.cpp +++ b/core/jni/android/graphics/ColorFilter.cpp @@ -30,9 +30,12 @@ using namespace uirenderer; class SkColorFilterGlue { public: - static void SafeUnref(JNIEnv* env, jobject clazz, jlong skFilterHandle) { - SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(skFilterHandle); - SkSafeUnref(filter); + static void SafeUnref(SkShader* shader) { + SkSafeUnref(shader); + } + + static jlong GetNativeFinalizer(JNIEnv*, jobject) { + return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SafeUnref)); } static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) { @@ -57,7 +60,7 @@ public: }; static const JNINativeMethod colorfilter_methods[] = { - {"nSafeUnref", "(J)V", (void*) SkColorFilterGlue::SafeUnref} + {"nativeGetFinalizer", "()J", (void*) SkColorFilterGlue::GetNativeFinalizer } }; static const JNINativeMethod porterduff_methods[] = { diff --git a/core/jni/android_hardware_Radio.cpp b/core/jni/android_hardware_Radio.cpp deleted file mode 100644 index 8b9be68bf712..000000000000 --- a/core/jni/android_hardware_Radio.cpp +++ /dev/null @@ -1,969 +0,0 @@ -/* -** -** Copyright 2015, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_NDEBUG 1 -#define LOG_TAG "Radio-JNI" -#include <utils/Log.h> - -#include "jni.h" -#include "JNIHelp.h" -#include "core_jni_helpers.h" -#include <system/radio.h> -#include <system/RadioMetadataWrapper.h> -#include <radio/RadioCallback.h> -#include <radio/Radio.h> -#include <utils/RefBase.h> -#include <utils/Vector.h> -#include <binder/IMemory.h> -#include <binder/MemoryDealer.h> - -using namespace android; - -static jclass gArrayListClass; -static struct { - jmethodID add; -} gArrayListMethods; - -static const char* const kRadioManagerClassPathName = "android/hardware/radio/RadioManager"; -static jclass gRadioManagerClass; - -static const char* const kRadioModuleClassPathName = "android/hardware/radio/RadioModule"; -static jclass gRadioModuleClass; -static struct { - jfieldID mNativeContext; - jfieldID mId; -} gModuleFields; -static jmethodID gPostEventFromNative; - -static const char* const kModulePropertiesClassPathName = - "android/hardware/radio/RadioManager$ModuleProperties"; -static jclass gModulePropertiesClass; -static jmethodID gModulePropertiesCstor; - - -static const char* const kRadioBandDescriptorClassPathName = - "android/hardware/radio/RadioManager$BandDescriptor"; -static jclass gRadioBandDescriptorClass; -static struct { - jfieldID mRegion; - jfieldID mType; - jfieldID mLowerLimit; - jfieldID mUpperLimit; - jfieldID mSpacing; -} gRadioBandDescriptorFields; - -static const char* const kRadioFmBandDescriptorClassPathName = - "android/hardware/radio/RadioManager$FmBandDescriptor"; -static jclass gRadioFmBandDescriptorClass; -static jmethodID gRadioFmBandDescriptorCstor; - -static const char* const kRadioAmBandDescriptorClassPathName = - "android/hardware/radio/RadioManager$AmBandDescriptor"; -static jclass gRadioAmBandDescriptorClass; -static jmethodID gRadioAmBandDescriptorCstor; - -static const char* const kRadioBandConfigClassPathName = - "android/hardware/radio/RadioManager$BandConfig"; -static jclass gRadioBandConfigClass; -static struct { - jfieldID mDescriptor; -} gRadioBandConfigFields; - - -static const char* const kRadioFmBandConfigClassPathName = - "android/hardware/radio/RadioManager$FmBandConfig"; -static jclass gRadioFmBandConfigClass; -static jmethodID gRadioFmBandConfigCstor; -static struct { - jfieldID mStereo; - jfieldID mRds; - jfieldID mTa; - jfieldID mAf; - jfieldID mEa; -} gRadioFmBandConfigFields; - -static const char* const kRadioAmBandConfigClassPathName = - "android/hardware/radio/RadioManager$AmBandConfig"; -static jclass gRadioAmBandConfigClass; -static jmethodID gRadioAmBandConfigCstor; -static struct { - jfieldID mStereo; -} gRadioAmBandConfigFields; - - -static const char* const kRadioProgramInfoClassPathName = - "android/hardware/radio/RadioManager$ProgramInfo"; -static jclass gRadioProgramInfoClass; -static jmethodID gRadioProgramInfoCstor; - -static const char* const kRadioMetadataClassPathName = - "android/hardware/radio/RadioMetadata"; -static jclass gRadioMetadataClass; -static jmethodID gRadioMetadataCstor; -static struct { - jmethodID putIntFromNative; - jmethodID putStringFromNative; - jmethodID putBitmapFromNative; - jmethodID putClockFromNative; -} gRadioMetadataMethods; - -static Mutex gLock; - -enum { - RADIO_STATUS_OK = 0, - RADIO_STATUS_ERROR = INT_MIN, - RADIO_PERMISSION_DENIED = -1, - RADIO_STATUS_NO_INIT = -19, - RADIO_STATUS_BAD_VALUE = -22, - RADIO_STATUS_DEAD_OBJECT = -32, - RADIO_STATUS_INVALID_OPERATION = -38, - RADIO_STATUS_TIMED_OUT = -110, -}; - - -// ---------------------------------------------------------------------------- - -static sp<Radio> getRadio(JNIEnv* env, jobject thiz) -{ - Mutex::Autolock l(gLock); - Radio* const radio = (Radio*)env->GetLongField(thiz, gModuleFields.mNativeContext); - return sp<Radio>(radio); -} - -static sp<Radio> setRadio(JNIEnv* env, jobject thiz, const sp<Radio>& module) -{ - Mutex::Autolock l(gLock); - sp<Radio> old = (Radio*)env->GetLongField(thiz, gModuleFields.mNativeContext); - if (module.get()) { - module->incStrong((void*)setRadio); - } - if (old != 0) { - old->decStrong((void*)setRadio); - } - env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get()); - return old; -} - -static jint convertBandDescriptorFromNative(JNIEnv *env, - jobject *jBandDescriptor, - const radio_band_config_t *nBandconfig) -{ - ALOGV("%s type %d region %d", __FUNCTION__, nBandconfig->band.type, nBandconfig->region); - - if (nBandconfig->band.type == RADIO_BAND_FM || - nBandconfig->band.type == RADIO_BAND_FM_HD) { - *jBandDescriptor = env->NewObject(gRadioFmBandDescriptorClass, gRadioFmBandDescriptorCstor, - nBandconfig->region, nBandconfig->band.type, - nBandconfig->band.lower_limit, nBandconfig->band.upper_limit, - nBandconfig->band.spacings[0], - nBandconfig->band.fm.stereo, - nBandconfig->band.fm.rds != RADIO_RDS_NONE, - nBandconfig->band.fm.ta, - nBandconfig->band.fm.af, - nBandconfig->band.fm.ea); - } else if (nBandconfig->band.type == RADIO_BAND_AM) { - *jBandDescriptor = env->NewObject(gRadioAmBandDescriptorClass, gRadioAmBandDescriptorCstor, - nBandconfig->region, nBandconfig->band.type, - nBandconfig->band.lower_limit, nBandconfig->band.upper_limit, - nBandconfig->band.spacings[0], - nBandconfig->band.am.stereo); - } else { - ALOGE("%s unknown band type %d", __FUNCTION__, nBandconfig->band.type); - return (jint)RADIO_STATUS_BAD_VALUE; - } - - if (*jBandDescriptor == NULL) { - return (jint)RADIO_STATUS_NO_INIT; - } - - return (jint)RADIO_STATUS_OK; -} - -static jint convertBandConfigFromNative(JNIEnv *env, - jobject *jBandConfig, - const radio_band_config_t *nBandconfig) -{ - ALOGV("%s type %d region %d", __FUNCTION__, nBandconfig->band.type, nBandconfig->region); - - if (nBandconfig->band.type == RADIO_BAND_FM || - nBandconfig->band.type == RADIO_BAND_FM_HD) { - *jBandConfig = env->NewObject(gRadioFmBandConfigClass, gRadioFmBandConfigCstor, - nBandconfig->region, nBandconfig->band.type, - nBandconfig->band.lower_limit, nBandconfig->band.upper_limit, - nBandconfig->band.spacings[0], - nBandconfig->band.fm.stereo, - nBandconfig->band.fm.rds != RADIO_RDS_NONE, - nBandconfig->band.fm.ta, - nBandconfig->band.fm.af, - nBandconfig->band.fm.ea); - } else if (nBandconfig->band.type == RADIO_BAND_AM) { - *jBandConfig = env->NewObject(gRadioAmBandConfigClass, gRadioAmBandConfigCstor, - nBandconfig->region, nBandconfig->band.type, - nBandconfig->band.lower_limit, nBandconfig->band.upper_limit, - nBandconfig->band.spacings[0], - nBandconfig->band.am.stereo); - } else { - ALOGE("%s unknown band type %d", __FUNCTION__, nBandconfig->band.type); - return (jint)RADIO_STATUS_BAD_VALUE; - } - - if (*jBandConfig == NULL) { - return (jint)RADIO_STATUS_NO_INIT; - } - - return (jint)RADIO_STATUS_OK; -} - -static jint convertMetadataFromNative(JNIEnv *env, - jobject *jMetadata, - const radio_metadata_t *nMetadata) -{ - ALOGV("%s", __FUNCTION__); - int count = radio_metadata_get_count(nMetadata); - if (count <= 0) { - return (jint)count; - } - *jMetadata = env->NewObject(gRadioMetadataClass, gRadioMetadataCstor); - - jint jCount = 0; - jint jStatus = 0; - for (unsigned int i = 0; i < (unsigned int)count; i++) { - radio_metadata_key_t key; - radio_metadata_type_t type; - void *value; - size_t size; - if (radio_metadata_get_at_index(nMetadata, i , &key, &type, &value, &size) != 0) { - continue; - } - switch (type) { - case RADIO_METADATA_TYPE_INT: { - ALOGV("%s RADIO_METADATA_TYPE_INT %d", __FUNCTION__, key); - int32_t val = *(int32_t *)value; - jStatus = env->CallIntMethod(*jMetadata, - gRadioMetadataMethods.putIntFromNative, - key, (jint)val); - if (jStatus == 0) { - jCount++; - } - } break; - case RADIO_METADATA_TYPE_TEXT: { - ALOGV("%s RADIO_METADATA_TYPE_TEXT %d", __FUNCTION__, key); - jstring jText = env->NewStringUTF((char *)value); - jStatus = env->CallIntMethod(*jMetadata, - gRadioMetadataMethods.putStringFromNative, - key, jText); - if (jStatus == 0) { - jCount++; - } - env->DeleteLocalRef(jText); - } break; - case RADIO_METADATA_TYPE_RAW: { - ALOGV("%s RADIO_METADATA_TYPE_RAW %d size %zu", __FUNCTION__, key, size); - if (size == 0) { - break; - } - jbyteArray jData = env->NewByteArray(size); - if (jData == NULL) { - break; - } - env->SetByteArrayRegion(jData, 0, size, (jbyte *)value); - jStatus = env->CallIntMethod(*jMetadata, - gRadioMetadataMethods.putBitmapFromNative, - key, jData); - if (jStatus == 0) { - jCount++; - } - env->DeleteLocalRef(jData); - } break; - case RADIO_METADATA_TYPE_CLOCK: { - ALOGV("%s RADIO_METADATA_TYPE_CLOCK %d", __FUNCTION__, key); - radio_metadata_clock_t *clock = (radio_metadata_clock_t *) value; - jStatus = - env->CallIntMethod(*jMetadata, - gRadioMetadataMethods.putClockFromNative, - key, (jint) clock->utc_seconds_since_epoch, - (jint) clock->timezone_offset_in_minutes); - if (jStatus == 0) { - jCount++; - } - } break; - } - } - return jCount; -} - -static jint convertProgramInfoFromNative(JNIEnv *env, - jobject *jProgramInfo, - const radio_program_info_t *nProgramInfo) -{ - ALOGV("%s", __FUNCTION__); - int jStatus; - jobject jMetadata = NULL; - - if (nProgramInfo == nullptr || nProgramInfo->metadata == nullptr) { - return (jint)RADIO_STATUS_BAD_VALUE; - } - - jStatus = convertMetadataFromNative(env, &jMetadata, nProgramInfo->metadata); - if (jStatus < 0) { - return jStatus; - } - - ALOGV("%s channel %d tuned %d", __FUNCTION__, nProgramInfo->channel, nProgramInfo->tuned); - - int flags = 0; // TODO(b/32621193): pass from the HAL - jstring jVendorExension = env->NewStringUTF(""); // TODO(b/32621193): pass from the HAL - *jProgramInfo = env->NewObject(gRadioProgramInfoClass, gRadioProgramInfoCstor, - nProgramInfo->channel, nProgramInfo->sub_channel, - nProgramInfo->tuned, nProgramInfo->stereo, - nProgramInfo->digital, nProgramInfo->signal_strength, - jMetadata, flags, jVendorExension); - - env->DeleteLocalRef(jMetadata); - env->DeleteLocalRef(jVendorExension); - return (jint)RADIO_STATUS_OK; -} - - -static jint convertBandConfigToNative(JNIEnv *env, - radio_band_config_t *nBandconfig, - jobject jBandConfig) -{ - ALOGV("%s", __FUNCTION__); - - jobject jDescriptor = env->GetObjectField(jBandConfig, gRadioBandConfigFields.mDescriptor); - - if (jDescriptor == NULL) { - return (jint)RADIO_STATUS_NO_INIT; - } - - nBandconfig->region = - (radio_region_t)env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mRegion); - nBandconfig->band.type = - (radio_band_t)env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mType); - nBandconfig->band.lower_limit = - env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mLowerLimit); - nBandconfig->band.upper_limit = - env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mUpperLimit); - nBandconfig->band.num_spacings = 1; - nBandconfig->band.spacings[0] = - env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mSpacing); - - if (env->IsInstanceOf(jBandConfig, gRadioFmBandConfigClass)) { - nBandconfig->band.fm.deemphasis = radio_demephasis_for_region(nBandconfig->region); - nBandconfig->band.fm.stereo = - env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mStereo); - nBandconfig->band.fm.rds = - radio_rds_for_region(env->GetBooleanField(jBandConfig, - gRadioFmBandConfigFields.mRds), - nBandconfig->region); - nBandconfig->band.fm.ta = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mTa); - nBandconfig->band.fm.af = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mAf); - nBandconfig->band.fm.ea = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mEa); - } else if (env->IsInstanceOf(jBandConfig, gRadioAmBandConfigClass)) { - nBandconfig->band.am.stereo = - env->GetBooleanField(jBandConfig, gRadioAmBandConfigFields.mStereo); - } else { - return (jint)RADIO_STATUS_BAD_VALUE; - } - - return (jint)RADIO_STATUS_OK; -} - -static jint -android_hardware_Radio_listModules(JNIEnv *env, jobject clazz, - jobject jModules) -{ - ALOGV("%s", __FUNCTION__); - - if (jModules == NULL) { - ALOGE("listModules NULL ArrayList"); - return RADIO_STATUS_BAD_VALUE; - } - if (!env->IsInstanceOf(jModules, gArrayListClass)) { - ALOGE("listModules not an arraylist"); - return RADIO_STATUS_BAD_VALUE; - } - - unsigned int numModules = 0; - radio_properties_t *nModules = NULL; - - status_t status = Radio::listModules(nModules, &numModules); - if (status != NO_ERROR || numModules == 0) { - return (jint)status; - } - - nModules = (radio_properties_t *)calloc(numModules, sizeof(radio_properties_t)); - - status = Radio::listModules(nModules, &numModules); - ALOGV("%s Radio::listModules status %d numModules %d", __FUNCTION__, status, numModules); - - if (status != NO_ERROR) { - numModules = 0; - } - - for (size_t i = 0; i < numModules; i++) { - if (nModules[i].num_bands == 0) { - continue; - } - ALOGV("%s module %zu id %d implementor %s product %s", - __FUNCTION__, i, nModules[i].handle, nModules[i].implementor, - nModules[i].product); - - - jobjectArray jBands = env->NewObjectArray(nModules[i].num_bands, - gRadioBandDescriptorClass, NULL); - - for (size_t j = 0; j < nModules[i].num_bands; j++) { - jobject jBandDescriptor; - int jStatus = - convertBandDescriptorFromNative(env, &jBandDescriptor, &nModules[i].bands[j]); - if (jStatus != RADIO_STATUS_OK) { - continue; - } - env->SetObjectArrayElement(jBands, j, jBandDescriptor); - env->DeleteLocalRef(jBandDescriptor); - } - - if (env->GetArrayLength(jBands) == 0) { - continue; - } - jstring jImplementor = env->NewStringUTF(nModules[i].implementor); - jstring jProduct = env->NewStringUTF(nModules[i].product); - jstring jVersion = env->NewStringUTF(nModules[i].version); - jstring jSerial = env->NewStringUTF(nModules[i].serial); - bool isBgscanSupported = false; // TODO(b/32621193): pass from the HAL - jstring jVendorExension = env->NewStringUTF(""); // TODO(b/32621193): pass from the HAL - jobject jModule = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor, - nModules[i].handle, nullptr, nModules[i].class_id, - jImplementor, jProduct, jVersion, jSerial, - nModules[i].num_tuners, - nModules[i].num_audio_sources, - nModules[i].supports_capture, - jBands, isBgscanSupported, jVendorExension); - - env->DeleteLocalRef(jImplementor); - env->DeleteLocalRef(jProduct); - env->DeleteLocalRef(jVersion); - env->DeleteLocalRef(jSerial); - env->DeleteLocalRef(jBands); - env->DeleteLocalRef(jVendorExension); - if (jModule == NULL) { - continue; - } - env->CallBooleanMethod(jModules, gArrayListMethods.add, jModule); - } - - free(nModules); - return (jint) status; -} - -// ---------------------------------------------------------------------------- - -class JNIRadioCallback: public RadioCallback -{ -public: - JNIRadioCallback(JNIEnv* env, jobject thiz, jobject weak_thiz); - ~JNIRadioCallback(); - - virtual void onEvent(struct radio_event *event); - -private: - jclass mClass; // Reference to Radio class - jobject mObject; // Weak ref to Radio Java object to call on -}; - -JNIRadioCallback::JNIRadioCallback(JNIEnv* env, jobject thiz, jobject weak_thiz) -{ - - // Hold onto the RadioModule class for use in calling the static method - // that posts events to the application thread. - jclass clazz = env->GetObjectClass(thiz); - if (clazz == NULL) { - ALOGE("Can't find class %s", kRadioModuleClassPathName); - return; - } - mClass = (jclass)env->NewGlobalRef(clazz); - - // We use a weak reference so the RadioModule object can be garbage collected. - // The reference is only used as a proxy for callbacks. - mObject = env->NewGlobalRef(weak_thiz); -} - -JNIRadioCallback::~JNIRadioCallback() -{ - // remove global references - JNIEnv *env = AndroidRuntime::getJNIEnv(); - if (env == NULL) { - return; - } - env->DeleteGlobalRef(mObject); - env->DeleteGlobalRef(mClass); -} - -void JNIRadioCallback::onEvent(struct radio_event *event) -{ - JNIEnv *env = AndroidRuntime::getJNIEnv(); - if (env == NULL) { - return; - } - - ALOGV("%s", __FUNCTION__); - - jobject jObj = NULL; - jint jArg2 = 0; - jint jStatus = RADIO_STATUS_OK; - switch (event->type) { - case RADIO_EVENT_CONFIG: - jStatus = convertBandConfigFromNative(env, &jObj, &event->config); - break; - case RADIO_EVENT_TUNED: - case RADIO_EVENT_AF_SWITCH: - ALOGV("%s RADIO_EVENT_TUNED channel %d", __FUNCTION__, event->info.channel); - jStatus = convertProgramInfoFromNative(env, &jObj, &event->info); - break; - case RADIO_EVENT_METADATA: - jStatus = convertMetadataFromNative(env, &jObj, event->metadata); - if (jStatus >= 0) { - jStatus = RADIO_STATUS_OK; - } - break; - case RADIO_EVENT_ANTENNA: - case RADIO_EVENT_TA: - case RADIO_EVENT_EA: - case RADIO_EVENT_CONTROL: - jArg2 = event->on ? 1 : 0; - break; - } - - if (jStatus != RADIO_STATUS_OK) { - return; - } - env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject, - event->type, event->status, jArg2, jObj); - - env->DeleteLocalRef(jObj); - if (env->ExceptionCheck()) { - ALOGW("An exception occurred while notifying an event."); - env->ExceptionClear(); - } -} - -// ---------------------------------------------------------------------------- - -static void -android_hardware_Radio_setup(JNIEnv *env, jobject thiz, - jobject weak_this, jobject jConfig, jboolean withAudio) -{ - ALOGV("%s", __FUNCTION__); - - setRadio(env, thiz, 0); - - sp<JNIRadioCallback> callback = new JNIRadioCallback(env, thiz, weak_this); - - radio_handle_t handle = (radio_handle_t)env->GetIntField(thiz, gModuleFields.mId); - - struct radio_band_config nConfig; - struct radio_band_config *configPtr = NULL; - if (jConfig != NULL) { - jint jStatus = convertBandConfigToNative(env, &nConfig, jConfig); - if (jStatus != RADIO_STATUS_OK) { - return; - } - configPtr = &nConfig; - } - sp<Radio> module = Radio::attach(handle, configPtr, (bool)withAudio, callback); - if (module == 0) { - return; - } - - setRadio(env, thiz, module); -} - -static void -android_hardware_Radio_close(JNIEnv *env, jobject thiz) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = setRadio(env, thiz, 0); - ALOGV("detach module %p", module.get()); - if (module != 0) { - ALOGV("detach module->detach()"); - module->detach(); - } -} - -static void -android_hardware_Radio_finalize(JNIEnv *env, jobject thiz) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module != 0) { - ALOGW("Radio finalized without being detached"); - } - android_hardware_Radio_close(env, thiz); -} - -static jint -android_hardware_Radio_setConfiguration(JNIEnv *env, jobject thiz, jobject jConfig) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - - if (!env->IsInstanceOf(jConfig, gRadioFmBandConfigClass) && - !env->IsInstanceOf(jConfig, gRadioAmBandConfigClass)) { - return RADIO_STATUS_BAD_VALUE; - } - - struct radio_band_config nConfig; - jint jStatus = convertBandConfigToNative(env, &nConfig, jConfig); - if (jStatus != RADIO_STATUS_OK) { - return jStatus; - } - - status_t status = module->setConfiguration(&nConfig); - return (jint)status; -} - -static jint -android_hardware_Radio_getConfiguration(JNIEnv *env, jobject thiz, jobjectArray jConfigs) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - if (env->GetArrayLength(jConfigs) != 1) { - return (jint)RADIO_STATUS_BAD_VALUE; - } - - struct radio_band_config nConfig; - - status_t status = module->getConfiguration(&nConfig); - if (status != NO_ERROR) { - return (jint)status; - } - jobject jConfig; - int jStatus = convertBandConfigFromNative(env, &jConfig, &nConfig); - if (jStatus != RADIO_STATUS_OK) { - return jStatus; - } - env->SetObjectArrayElement(jConfigs, 0, jConfig); - env->DeleteLocalRef(jConfig); - return RADIO_STATUS_OK; -} - -static jint -android_hardware_Radio_setMute(JNIEnv *env, jobject thiz, jboolean mute) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - status_t status = module->setMute((bool)mute); - return (jint)status; -} - -static jboolean -android_hardware_Radio_getMute(JNIEnv *env, jobject thiz) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return true; - } - bool mute = true; - status_t status = module->getMute(&mute); - if (status != NO_ERROR) { - return true; - } - return (jboolean)mute; -} - -static jint -android_hardware_Radio_step(JNIEnv *env, jobject thiz, jint direction, jboolean skipSubChannel) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - status_t status = module->step((radio_direction_t)direction, (bool)skipSubChannel); - return (jint)status; -} - -static jint -android_hardware_Radio_scan(JNIEnv *env, jobject thiz, jint direction, jboolean skipSubChannel) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - status_t status = module->scan((radio_direction_t)direction, (bool)skipSubChannel); - return (jint)status; -} - -static jint -android_hardware_Radio_tune(JNIEnv *env, jobject thiz, jint channel, jint subChannel) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - status_t status = module->tune((uint32_t)channel, (uint32_t)subChannel); - return (jint)status; -} - -static jint -android_hardware_Radio_cancel(JNIEnv *env, jobject thiz) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - status_t status = module->cancel(); - return (jint)status; -} - -static jint -android_hardware_Radio_getProgramInformation(JNIEnv *env, jobject thiz, jobjectArray jInfos) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return RADIO_STATUS_NO_INIT; - } - if (env->GetArrayLength(jInfos) != 1) { - return (jint)RADIO_STATUS_BAD_VALUE; - } - - struct radio_program_info nInfo; - RadioMetadataWrapper metadataWrapper(&nInfo.metadata); - jobject jInfo = NULL; - int jStatus; - - jStatus = (int)module->getProgramInformation(&nInfo); - if (jStatus != RADIO_STATUS_OK) { - goto exit; - } - jStatus = convertProgramInfoFromNative(env, &jInfo, &nInfo); - if (jStatus != RADIO_STATUS_OK) { - goto exit; - } - env->SetObjectArrayElement(jInfos, 0, jInfo); - -exit: - if (jInfo != NULL) { - env->DeleteLocalRef(jInfo); - } - return jStatus; -} - -static jboolean -android_hardware_Radio_isAntennaConnected(JNIEnv *env, jobject thiz) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return false; - } - - struct radio_band_config nConfig; - - status_t status = module->getConfiguration(&nConfig); - if (status != NO_ERROR) { - return false; - } - - return (jboolean)nConfig.band.antenna_connected; -} - - -static jboolean -android_hardware_Radio_hasControl(JNIEnv *env, jobject thiz) -{ - ALOGV("%s", __FUNCTION__); - sp<Radio> module = getRadio(env, thiz); - if (module == NULL) { - return false; - } - - bool hasControl; - status_t status = module->hasControl(&hasControl); - if (status != NO_ERROR) { - return false; - } - - return (jboolean)hasControl; -} - - -static JNINativeMethod gMethods[] = { - {"nativeListModules", - "(Ljava/util/List;)I", - (void *)android_hardware_Radio_listModules}, -}; - -static JNINativeMethod gModuleMethods[] = { - {"native_setup", - "(Ljava/lang/Object;Landroid/hardware/radio/RadioManager$BandConfig;Z)V", - (void *)android_hardware_Radio_setup}, - {"native_finalize", - "()V", - (void *)android_hardware_Radio_finalize}, - {"close", - "()V", - (void *)android_hardware_Radio_close}, - {"setConfiguration", - "(Landroid/hardware/radio/RadioManager$BandConfig;)I", - (void *)android_hardware_Radio_setConfiguration}, - {"getConfiguration", - "([Landroid/hardware/radio/RadioManager$BandConfig;)I", - (void *)android_hardware_Radio_getConfiguration}, - {"setMute", - "(Z)I", - (void *)android_hardware_Radio_setMute}, - {"getMute", - "()Z", - (void *)android_hardware_Radio_getMute}, - {"step", - "(IZ)I", - (void *)android_hardware_Radio_step}, - {"scan", - "(IZ)I", - (void *)android_hardware_Radio_scan}, - {"tune", - "(II)I", - (void *)android_hardware_Radio_tune}, - {"cancel", - "()I", - (void *)android_hardware_Radio_cancel}, - {"getProgramInformation", - "([Landroid/hardware/radio/RadioManager$ProgramInfo;)I", - (void *)android_hardware_Radio_getProgramInformation}, - {"isAntennaConnected", - "()Z", - (void *)android_hardware_Radio_isAntennaConnected}, - {"hasControl", - "()Z", - (void *)android_hardware_Radio_hasControl}, -}; - -int register_android_hardware_Radio(JNIEnv *env) -{ - jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); - gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); - gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); - - jclass lClass = FindClassOrDie(env, kRadioManagerClassPathName); - gRadioManagerClass = MakeGlobalRefOrDie(env, lClass); - - jclass moduleClass = FindClassOrDie(env, kRadioModuleClassPathName); - gRadioModuleClass = MakeGlobalRefOrDie(env, moduleClass); - gPostEventFromNative = GetStaticMethodIDOrDie(env, moduleClass, "postEventFromNative", - "(Ljava/lang/Object;IIILjava/lang/Object;)V"); - gModuleFields.mNativeContext = GetFieldIDOrDie(env, moduleClass, "mNativeContext", "J"); - gModuleFields.mId = GetFieldIDOrDie(env, moduleClass, "mId", "I"); - - jclass modulePropertiesClass = FindClassOrDie(env, kModulePropertiesClassPathName); - gModulePropertiesClass = MakeGlobalRefOrDie(env, modulePropertiesClass); - gModulePropertiesCstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>", - "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;" - "Ljava/lang/String;IIZ[Landroid/hardware/radio/RadioManager$BandDescriptor;Z" - "Ljava/lang/String;)V"); - - jclass bandDescriptorClass = FindClassOrDie(env, kRadioBandDescriptorClassPathName); - gRadioBandDescriptorClass = MakeGlobalRefOrDie(env, bandDescriptorClass); - gRadioBandDescriptorFields.mRegion = GetFieldIDOrDie(env, bandDescriptorClass, "mRegion", "I"); - gRadioBandDescriptorFields.mType = GetFieldIDOrDie(env, bandDescriptorClass, "mType", "I"); - gRadioBandDescriptorFields.mLowerLimit = - GetFieldIDOrDie(env, bandDescriptorClass, "mLowerLimit", "I"); - gRadioBandDescriptorFields.mUpperLimit = - GetFieldIDOrDie(env, bandDescriptorClass, "mUpperLimit", "I"); - gRadioBandDescriptorFields.mSpacing = - GetFieldIDOrDie(env, bandDescriptorClass, "mSpacing", "I"); - - jclass fmBandDescriptorClass = FindClassOrDie(env, kRadioFmBandDescriptorClassPathName); - gRadioFmBandDescriptorClass = MakeGlobalRefOrDie(env, fmBandDescriptorClass); - gRadioFmBandDescriptorCstor = GetMethodIDOrDie(env, fmBandDescriptorClass, "<init>", - "(IIIIIZZZZZ)V"); - - jclass amBandDescriptorClass = FindClassOrDie(env, kRadioAmBandDescriptorClassPathName); - gRadioAmBandDescriptorClass = MakeGlobalRefOrDie(env, amBandDescriptorClass); - gRadioAmBandDescriptorCstor = GetMethodIDOrDie(env, amBandDescriptorClass, "<init>", - "(IIIIIZ)V"); - - jclass bandConfigClass = FindClassOrDie(env, kRadioBandConfigClassPathName); - gRadioBandConfigClass = MakeGlobalRefOrDie(env, bandConfigClass); - gRadioBandConfigFields.mDescriptor = - GetFieldIDOrDie(env, bandConfigClass, "mDescriptor", - "Landroid/hardware/radio/RadioManager$BandDescriptor;"); - - jclass fmBandConfigClass = FindClassOrDie(env, kRadioFmBandConfigClassPathName); - gRadioFmBandConfigClass = MakeGlobalRefOrDie(env, fmBandConfigClass); - gRadioFmBandConfigCstor = GetMethodIDOrDie(env, fmBandConfigClass, "<init>", - "(IIIIIZZZZZ)V"); - gRadioFmBandConfigFields.mStereo = GetFieldIDOrDie(env, fmBandConfigClass, "mStereo", "Z"); - gRadioFmBandConfigFields.mRds = GetFieldIDOrDie(env, fmBandConfigClass, "mRds", "Z"); - gRadioFmBandConfigFields.mTa = GetFieldIDOrDie(env, fmBandConfigClass, "mTa", "Z"); - gRadioFmBandConfigFields.mAf = GetFieldIDOrDie(env, fmBandConfigClass, "mAf", "Z"); - gRadioFmBandConfigFields.mEa = - GetFieldIDOrDie(env, fmBandConfigClass, "mEa", "Z"); - - - jclass amBandConfigClass = FindClassOrDie(env, kRadioAmBandConfigClassPathName); - gRadioAmBandConfigClass = MakeGlobalRefOrDie(env, amBandConfigClass); - gRadioAmBandConfigCstor = GetMethodIDOrDie(env, amBandConfigClass, "<init>", - "(IIIIIZ)V"); - gRadioAmBandConfigFields.mStereo = GetFieldIDOrDie(env, amBandConfigClass, "mStereo", "Z"); - - jclass programInfoClass = FindClassOrDie(env, kRadioProgramInfoClassPathName); - gRadioProgramInfoClass = MakeGlobalRefOrDie(env, programInfoClass); - gRadioProgramInfoCstor = GetMethodIDOrDie(env, programInfoClass, "<init>", - "(IIZZZILandroid/hardware/radio/RadioMetadata;ILjava/lang/String;)V"); - - jclass metadataClass = FindClassOrDie(env, kRadioMetadataClassPathName); - gRadioMetadataClass = MakeGlobalRefOrDie(env, metadataClass); - gRadioMetadataCstor = GetMethodIDOrDie(env, metadataClass, "<init>", "()V"); - gRadioMetadataMethods.putIntFromNative = GetMethodIDOrDie(env, metadataClass, - "putIntFromNative", - "(II)I"); - gRadioMetadataMethods.putStringFromNative = GetMethodIDOrDie(env, metadataClass, - "putStringFromNative", - "(ILjava/lang/String;)I"); - gRadioMetadataMethods.putBitmapFromNative = GetMethodIDOrDie(env, metadataClass, - "putBitmapFromNative", - "(I[B)I"); - gRadioMetadataMethods.putClockFromNative = GetMethodIDOrDie(env, metadataClass, - "putClockFromNative", - "(IJI)I"); - - - RegisterMethodsOrDie(env, kRadioManagerClassPathName, gMethods, NELEM(gMethods)); - - int ret = RegisterMethodsOrDie(env, kRadioModuleClassPathName, gModuleMethods, NELEM(gModuleMethods)); - - ALOGV("%s DONE", __FUNCTION__); - - return ret; -} diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml index 863efef5c661..d83ccb23f64f 100644 --- a/core/res/res/layout-land/time_picker_material.xml +++ b/core/res/res/layout-land/time_picker_material.xml @@ -17,6 +17,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layoutDirection="ltr" android:layout_width="match_parent" android:layout_height="wrap_content"> @@ -30,6 +31,7 @@ <LinearLayout android:id="@+id/time_layout" + android:layoutDirection="ltr" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="@dimen/timepicker_radial_picker_top_margin" diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java index 0ca3729dcc0e..b24b9885d1b0 100644 --- a/graphics/java/android/graphics/ColorFilter.java +++ b/graphics/java/android/graphics/ColorFilter.java @@ -14,19 +14,22 @@ * limitations under the License. */ -// This file was generated from the C++ include file: SkColorFilter.h -// Any changes made to this file will be discarded by the build. -// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, -// or one of the auxilary file specifications in device/tools/gluemaker. - package android.graphics; +import libcore.util.NativeAllocationRegistry; + /** * A color filter can be used with a {@link Paint} to modify the color of * each pixel drawn with that paint. This is an abstract class that should * never be used directly. */ public class ColorFilter { + + private static class NoImagePreloadHolder { + public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( + ColorFilter.class.getClassLoader(), nativeGetFinalizer(), 50); + } + /** * @deprecated Use subclass constructors directly instead. */ @@ -34,9 +37,11 @@ public class ColorFilter { public ColorFilter() {} /** - * Holds the pointer to the native SkColorFilter instance. + * Current native SkColorFilter instance. */ private long mNativeInstance; + // Runnable to do immediate destruction + private Runnable mCleaner; long createNativeInstance() { return 0; @@ -44,35 +49,28 @@ public class ColorFilter { void discardNativeInstance() { if (mNativeInstance != 0) { - nSafeUnref(mNativeInstance); + mCleaner.run(); + mCleaner = null; mNativeInstance = 0; } } - @Override - protected void finalize() throws Throwable { - try { - if (mNativeInstance != 0) { - nSafeUnref(mNativeInstance); - } - mNativeInstance = -1; - } finally { - super.finalize(); - } - } - /** @hide */ public long getNativeInstance() { - if (mNativeInstance == -1) { - throw new IllegalStateException("attempting to use a finalized ColorFilter"); - } - if (mNativeInstance == 0) { mNativeInstance = createNativeInstance(); + + if (mNativeInstance != 0) { + // Note: we must check for null here, since it's possible for createNativeInstance() + // to return nullptr if the native SkColorFilter would be a no-op at draw time. + // See native implementations of subclass create methods for more info. + mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation( + this, mNativeInstance); + } } return mNativeInstance; } - static native void nSafeUnref(long native_instance); + private static native long nativeGetFinalizer(); } diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index bab8883ef64f..0782269d7de1 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -3313,13 +3313,14 @@ struct ResTable::PackageGroup clearBagCache(); const size_t numTypes = types.size(); for (size_t i = 0; i < numTypes; i++) { - const TypeList& typeList = types[i]; + TypeList& typeList = types.editItemAt(i); const size_t numInnerTypes = typeList.size(); for (size_t j = 0; j < numInnerTypes; j++) { if (typeList[j]->package->owner == owner) { delete typeList[j]; } } + typeList.clear(); } const size_t N = packages.size(); diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp index a3d5079c6ce9..85b12ba79a8c 100644 --- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp +++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp @@ -51,8 +51,6 @@ TEST(SkiaBehavior, CreateBitmapShader1x1) { SkShader::TileMode xy[2]; ASSERT_TRUE(s->isABitmap(&bitmap, nullptr, xy)) << "1x1 bitmap shader must query as bitmap shader"; - EXPECT_EQ(SkShader::kClamp_TileMode, xy[0]); - EXPECT_EQ(SkShader::kRepeat_TileMode, xy[1]); EXPECT_EQ(origBitmap.pixelRef(), bitmap.pixelRef()); } diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp index 3d988773ff04..ba3b482935dd 100644 --- a/media/jni/soundpool/SoundPoolThread.cpp +++ b/media/jni/soundpool/SoundPoolThread.cpp @@ -20,8 +20,6 @@ #include "SoundPoolThread.h" -static const int kMaxWorkers = 3; - namespace android { void SoundPoolThread::write(SoundPoolMsg msg) { @@ -33,21 +31,14 @@ void SoundPoolThread::write(SoundPoolMsg msg) { // if thread is quitting, don't add to queue if (mRunning) { mMsgQueue.push(msg); - if (mNumWorkers < kMaxWorkers) { - if (createThreadEtc(beginThread, this, "SoundPoolThread")) { - mNumWorkers++; - ALOGV("created worker thread"); - } - } + mCondition.signal(); } } const SoundPoolMsg SoundPoolThread::read() { Mutex::Autolock lock(&mLock); - if (mMsgQueue.size() == 0) { - mNumWorkers--; - mCondition.signal(); - return SoundPoolMsg(SoundPoolMsg::KILL, 0); + while (mMsgQueue.size() == 0) { + mCondition.wait(mLock); } SoundPoolMsg msg = mMsgQueue[0]; mMsgQueue.removeAt(0); @@ -60,20 +51,20 @@ void SoundPoolThread::quit() { if (mRunning) { mRunning = false; mMsgQueue.clear(); - mCondition.broadcast(); // wake up any blocked writers - while (mNumWorkers > 0) { - mCondition.wait(mLock); - } + mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0)); + mCondition.signal(); + mCondition.wait(mLock); } ALOGV("return from quit"); } SoundPoolThread::SoundPoolThread(SoundPool* soundPool) : - mSoundPool(soundPool), - mNumWorkers(0), - mRunning(true) + mSoundPool(soundPool) { mMsgQueue.setCapacity(maxMessages); + if (createThreadEtc(beginThread, this, "SoundPoolThread")) { + mRunning = true; + } } SoundPoolThread::~SoundPoolThread() diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h index 5d7bf0c07803..7b3e1dda0a23 100644 --- a/media/jni/soundpool/SoundPoolThread.h +++ b/media/jni/soundpool/SoundPoolThread.h @@ -58,7 +58,6 @@ private: Condition mCondition; Vector<SoundPoolMsg> mMsgQueue; SoundPool* mSoundPool; - int32_t mNumWorkers; bool mRunning; }; diff --git a/packages/MtpDocumentsProvider/res/values-af/strings.xml b/packages/MtpDocumentsProvider/res/values-af/strings.xml new file mode 100644 index 000000000000..c2c8761146f3 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-gasheer"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Aflaaie"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Toegang tot lêers word tans van <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> af verkry"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Die ander toestel is besig. Jy kan nie lêers oordra voordat dit beskikbaar is nie."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Geen lêers is gevind nie. Die ander toestel is dalk gesluit. Indien wel, ontsluit dit en probeer weer."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-am/strings.xml b/packages/MtpDocumentsProvider/res/values-am/strings.xml new file mode 100644 index 000000000000..7b721c86cec0 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"የMTP አስተናጋጅ"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"የወረዱ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"ፋይሎችን ከ<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> በመድረስ ላይ"</string> + <string name="error_busy_device" msgid="3997316850357386589">"ሌላኛው መሣሪያ ሥራ በዝቶበታል። እስከሚገኝ ድረስ ፋይሎችን ማስተላለፍ አይችሉም።"</string> + <string name="error_locked_device" msgid="7557872102188356147">"ምንም ፋይሎች አልተገኙም። ሌላኛው መሣሪያ ተቆልፎ ሊሆን ይችላል። ተቆልፎ ከሆነ ይክፈቱት እና እንደገና ይሞክሩ።"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ar/strings.xml b/packages/MtpDocumentsProvider/res/values-ar/strings.xml new file mode 100644 index 000000000000..284a8602ce6a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"مضيف بروتوكول نقل الوسائط (MTP)"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"التنزيلات"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"جارٍ الوصول إلى الملفات من <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"الجهاز الآخر مشغول، ولا يمكنك نقل الملفات إلا بعد أن يصبح متاحًا."</string> + <string name="error_locked_device" msgid="7557872102188356147">"لم يتم العثور على ملفات، وربما يكون الجهاز الآخر في وضع القفل. إذا كان الأمر كذلك، فعليك إلغاء قفله وإعادة المحاولة."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-az/strings.xml b/packages/MtpDocumentsProvider/res/values-az/strings.xml new file mode 100644 index 000000000000..e8ed1242f13c --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Endirmələr"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Fayllara <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> cihazından daxil olunur"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Digər cihaz məşğuldur. Əlçatan olmayana kimi fayl köçürə bilməzsiniz."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Fayl tapılmadı. Digər cihaz kilidlənmiş ola bilər. Elədirsə, kiliddən çıxarın və yenidən cəhd edin."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-b+sr+Latn/strings.xml b/packages/MtpDocumentsProvider/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..bc9009969a16 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Preuzimanja"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Pristup datotekama sa uređaja <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Drugi uređaj je zauzet. Datoteke možete da prenesete tek kad on postane dostupan."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nije pronađena nijedna datoteka. Drugi uređaj je možda zaključan. Ako jeste, otključajte ga i pokušajte ponovo."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-be/strings.xml b/packages/MtpDocumentsProvider/res/values-be/strings.xml new file mode 100644 index 000000000000..f6263acb0150 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Вузел MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Спампоўкі"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Доступ да файлаў з <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Іншая прылада занята. Вы не можаце перадаць файлы, пакуль яна не стане даступнай."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Файлы не знойдзены. Іншая прылада можа быць заблакіравана. Калі гэта так, разблакіруйце яе і паўтарыце спробу."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-bg/strings.xml b/packages/MtpDocumentsProvider/res/values-bg/strings.xml new file mode 100644 index 000000000000..52d311971fc1 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP хост"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Изтегляния"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> на <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"От <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> се осъществява достъп до файловете"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Другото устройство е заето. Не можете да прехвърляте файлове, докато то не се освободи."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Няма намерени файлове. Другото устройство може да е заключено. Ако е така, отключете го и опитайте отново."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-bn/strings.xml b/packages/MtpDocumentsProvider/res/values-bn/strings.xml new file mode 100644 index 000000000000..7fad89e89d60 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP হোস্ট"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ডাউনলোডগুলি"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> থেকে ফাইলগুলিকে অ্যাক্সেস করা হচ্ছে"</string> + <string name="error_busy_device" msgid="3997316850357386589">"অন্য ডিভাইসটি ব্যস্ত আছে৷ এটি উপলব্ধ না হওয়া পর্যন্ত আপনি ফাইলগুলিকে স্থানান্তর করতে পারবেন না৷"</string> + <string name="error_locked_device" msgid="7557872102188356147">"কোনো ফাইল পাওয়া যায়নি৷ অন্য ডিভাইসটি লক থাকতে পারে৷ যদি তাই হয়, তাহলে এটিকে আনলক করে আবার চেষ্টা করুন৷"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-bs/strings.xml b/packages/MtpDocumentsProvider/res/values-bs/strings.xml new file mode 100644 index 000000000000..33323f81f81a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Preuzimanja"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Pristupanje datotekama iz uređaja <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Drugi uređaj je zauzet. Nećete moći prenositi fajlove dok ne bude dostupan."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Fajlovi nisu pronađeni. Moguće je da je drugi uređaj zaključan. Ako jeste, otključajte ga i pokušajte ponovo."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ca/strings.xml b/packages/MtpDocumentsProvider/res/values-ca/strings.xml new file mode 100644 index 000000000000..b2aa59966ac4 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Amfitrió MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Baixades"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"S\'està accedint als fitxers del dispositiu <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"L\'altre dispositiu està ocupat. No pots transferir fitxers fins que estigui disponible."</string> + <string name="error_locked_device" msgid="7557872102188356147">"No s\'han trobat fitxers. És possible que l\'altre dispositiu estigui bloquejat. Si és així, desbloqueja\'l i torna-ho a provar."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-cs/strings.xml b/packages/MtpDocumentsProvider/res/values-cs/strings.xml new file mode 100644 index 000000000000..2156e8c52f7e --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Hostitel MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Stahování"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> – <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Používání souborů ze zařízení <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Druhé zařízení je zaneprázdněné. Dokud nebude dostupné, soubory nelze přenést."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nebyly nalezeny žádné soubory. Druhé zařízení je možná uzamčené. Pokud ano, odemkněte jej a zkuste to znovu."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-da/strings.xml b/packages/MtpDocumentsProvider/res/values-da/strings.xml new file mode 100644 index 000000000000..b82c5e8b0af8 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Adgang til filer fra <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Den anden enhed er optaget. Du kan ikke overføre filer, før den er tilgængelig."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Der blev ikke fundet nogen filer. Den anden enhed er muligvis låst. Hvis dette er tilfældet, skal du låse den op og prøve igen."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-de/strings.xml b/packages/MtpDocumentsProvider/res/values-de/strings.xml new file mode 100644 index 000000000000..9a71c769aaed --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> von <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Zugriff auf Dateien von <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Das andere Gerät ist nicht verfügbar. Du kannst die Dateien übertragen, sobald das Gerät wieder verfügbar ist."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Keine Dateien gefunden. Das andere Gerät ist möglicherweise gesperrt. Entsperre es in diesem Fall und versuche es noch einmal."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-el/strings.xml b/packages/MtpDocumentsProvider/res/values-el/strings.xml new file mode 100644 index 000000000000..562d2952988a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Κεντρικός υπολογιστής MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Λήψεις"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Πρόσβαση στα αρχεία από τη συσκευή <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Η άλλη συσκευή είναι απασχολημένη. Δεν μπορείτε να μεταφέρετε αρχεία μέχρι να γίνει διαθέσιμη."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Δεν βρέθηκαν αρχεία. Η άλλη συσκευή ενδέχεται να είναι κλειδωμένη. Εάν ισχύει αυτό, ξεκλειδώστε την και δοκιμάστε ξανά."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-en-rAU/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rAU/strings.xml new file mode 100644 index 000000000000..5f2167e8273a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string> + <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-en-rGB/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rGB/strings.xml new file mode 100644 index 000000000000..5f2167e8273a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string> + <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-en-rIN/strings.xml b/packages/MtpDocumentsProvider/res/values-en-rIN/strings.xml new file mode 100644 index 000000000000..5f2167e8273a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accessing files from <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"The other device is busy. You can\'t transfer files until it\'s available."</string> + <string name="error_locked_device" msgid="7557872102188356147">"No files found. The other device may be locked. If so, unlock it and try again."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-es-rUS/strings.xml b/packages/MtpDocumentsProvider/res/values-es-rUS/strings.xml new file mode 100644 index 000000000000..740d224d7136 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Descargas"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accediendo a los archivos de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"El otro dispositivo está ocupado. No podrás transferir archivos hasta que esté disponible."</string> + <string name="error_locked_device" msgid="7557872102188356147">"No se encontraron archivos. Es posible que el otro dispositivo esté bloqueado. Si es así, desbloquéalo y vuelve a intentarlo."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-es/strings.xml b/packages/MtpDocumentsProvider/res/values-es/strings.xml new file mode 100644 index 000000000000..d80a75ac07f7 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host de MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Descargas"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accediendo a los archivos desde <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"El otro dispositivo está ocupado. No se pueden transferir archivos hasta que esté disponible."</string> + <string name="error_locked_device" msgid="7557872102188356147">"No se ha encontrado ningún archivo. Es posible que el otro dispositivo esté bloqueado. Si es así, desbloquéalo y vuelve a intentarlo."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-et/strings.xml b/packages/MtpDocumentsProvider/res/values-et/strings.xml new file mode 100644 index 000000000000..7568777e15f7 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Allalaadimised"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>, <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Juurdepääsemine failidele seadmest <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Teine seade on hõivatud. Te ei saa faile üle viia enne, kui see seade on saadaval."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Faile ei leitud. Teine seade võib olla lukustatud. Kui see on nii, avage see ja proovige uuesti."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-eu/strings.xml b/packages/MtpDocumentsProvider/res/values-eu/strings.xml new file mode 100644 index 000000000000..dc9d463b98eb --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ostalaria"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Deskargak"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> gailuko fitxategiak atzitzen"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Beste gailua lanpetuta dago. Erabilgarri egon arte ezingo duzu transferitu fitxategirik."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Ez da aurkitu fitxategirik. Baliteke beste gailua blokeatuta egotea. Hala bada, desblokea ezazu eta saiatu berriro."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-fa/strings.xml b/packages/MtpDocumentsProvider/res/values-fa/strings.xml new file mode 100644 index 000000000000..9ac58c7ad3f1 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"میزبان MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"بارگیریها"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"دسترسی به فایلها از <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"دستگاه دیگر مشغول است. تا زمانی که این دستگاه دردسترس قرار نگیرد نمیتوانید فایلها را منتقل کنید."</string> + <string name="error_locked_device" msgid="7557872102188356147">"فایلی پیدا نشد. دستگاه دیگر ممکن است قفل باشد. اگر اینطور است، قفل آن را باز کنید و دوباره تلاش کنید."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-fi/strings.xml b/packages/MtpDocumentsProvider/res/values-fi/strings.xml new file mode 100644 index 000000000000..0a61d08a566e --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-isäntä"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Lataukset"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Käytetään laitteen <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> tiedostoja"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Toinen laite on varattu. Et voi siirtää tiedostoja, ennen kuin se on käytettävissä."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Tiedostoja ei löytynyt. Toinen laite voi olla lukittu. Jos näin on, avaa se ja yritä uudelleen."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-fr-rCA/strings.xml b/packages/MtpDocumentsProvider/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000000..281760ecb620 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Hôte MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Téléchargements"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accès aux fichiers à partir de l\'appareil <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"L\'autre appareil est occupé. Vous devez attendre qu\'il soit disponible pour transférer des fichiers."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Aucun fichier trouvé. L\'autre appareil est peut-être verrouillé. Si c\'est le cas, déverrouillez-le, puis réessayez."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-fr/strings.xml b/packages/MtpDocumentsProvider/res/values-fr/strings.xml new file mode 100644 index 000000000000..96c713b61af4 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Hôte MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Téléchargements"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> – <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accès aux fichiers depuis le <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>…"</string> + <string name="error_busy_device" msgid="3997316850357386589">"L\'autre appareil est occupé. Vous devez attendre qu\'il soit disponible pour transférer des fichiers."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Aucun fichier trouvé. L\'autre appareil est peut-être verrouillé. Si tel est le cas, déverrouillez-le, puis réessayez."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-gl/strings.xml b/packages/MtpDocumentsProvider/res/values-gl/strings.xml new file mode 100644 index 000000000000..7e61c7cedff9 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Descargas"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> de <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accedendo aos ficheiros do dispositivo <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Non podes transferir ficheiros ata que estea dispoñible."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Non se atopou ningún ficheiro. Se o outro dispositivo está bloqueado, desbloquéao e téntao de novo."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-gu/strings.xml b/packages/MtpDocumentsProvider/res/values-gu/strings.xml new file mode 100644 index 000000000000..40ec38ddcda9 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP હોસ્ટ"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ડાઉનલોડ્સ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ની ફાઇલોને ઍક્સેસ કરી રહ્યાં છે"</string> + <string name="error_busy_device" msgid="3997316850357386589">"અન્ય ઉપકરણ વ્યસ્ત છે. તે ઉપલબ્ધ ન થાય ત્યાં સુધી તમે ફાઇલોને સ્થાનાંતરિત કરી શકતાં નથી."</string> + <string name="error_locked_device" msgid="7557872102188356147">"કોઈ ફાઇલો મળી નહીં. અન્ય ઉપકરણ લૉક કરેલ હોઈ શકે છે. જો આમ હોય, તો તેને અનલૉક કરો અને ફરી પ્રયાસ કરો."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-hi/strings.xml b/packages/MtpDocumentsProvider/res/values-hi/strings.xml new file mode 100644 index 000000000000..1cf1c03780e8 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP होस्ट"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> से फ़ाइलें एक्सेस कर रहा है"</string> + <string name="error_busy_device" msgid="3997316850357386589">"दूसरा डिवाइस व्यस्त है. आप उसके उपलब्ध हो जाने तक फ़ाइलें स्थानांतरित नहीं कर सकते हैं."</string> + <string name="error_locked_device" msgid="7557872102188356147">"कोई फ़ाइल नहीं मिली. हो सकता है कि दूसरा डिवाइस लॉक हो. यदि ऐसा है, तो उसे अनलॉक करें और पुन: प्रयास करें."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-hr/strings.xml b/packages/MtpDocumentsProvider/res/values-hr/strings.xml new file mode 100644 index 000000000000..63fc5c768113 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Preuzimanja"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g><xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Pristupanje datotekama s uređaja <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Drugi je uređaj zauzet. Datoteke ćete moći prenijeti kada postane dostupan."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Datoteke nisu pronađene. Drugi je uređaj možda zaključan. U tom ga slučaju otključajte i pokušajte ponovo."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-hu/strings.xml b/packages/MtpDocumentsProvider/res/values-hu/strings.xml new file mode 100644 index 000000000000..e5b822c14271 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Letöltések"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Hozzáférés a fájlokhoz a következő eszközről: <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"A másik eszköz elfoglalt. Nem vihetők át fájlok addig, amíg rendelkezésre nem áll."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nem található fájl. Lehet, hogy a másik eszköz zárolva van. Ha igen, oldja fel, és próbálkozzon újra."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-hy/strings.xml b/packages/MtpDocumentsProvider/res/values-hy/strings.xml new file mode 100644 index 000000000000..3a6bfb50de44 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP խնամորդ"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Ներբեռնումներ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Մուտք է գործում ֆայլեր <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> սարքից"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Մյուս սարքը զբաղված է: Ֆայլերը կարող եք փոխանցել միայն երբ այն հասանելի է:"</string> + <string name="error_locked_device" msgid="7557872102188356147">"Ֆայլեր չեն գտնվել: Հնարավոր է, որ մյուս սարքը կողպված է: Եթե դա այդպես է, ապակողպեք այն և փորձեք նորից:"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-in/strings.xml b/packages/MtpDocumentsProvider/res/values-in/strings.xml new file mode 100644 index 000000000000..6f65337a1d61 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Download"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Mengakses file dari <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Perangkat lainnya sedang sibuk. Anda dapat mentransfer file jika telah tersedia."</string> + <string name="error_locked_device" msgid="7557872102188356147">"File tidak ditemukan. Perangkat lainnya mungkin terkunci. Jika begitu, buka kuncinya dan coba lagi."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-is/strings.xml b/packages/MtpDocumentsProvider/res/values-is/strings.xml new file mode 100644 index 000000000000..9388f7e76efa --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-hýsill"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Niðurhal"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Fær aðgang að skrám frá <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Hitt tækið er upptekið. Þú getur ekki fært skrár fyrr en það er tiltækt."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Engar skrár fundust. Hitt tækið gæti verið læst. Ef svo er skaltu opna það og reyna aftur."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-it/strings.xml b/packages/MtpDocumentsProvider/res/values-it/strings.xml new file mode 100644 index 000000000000..a41699f55282 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Download"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> di <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Accesso ai file da <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"L\'altro dispositivo è occupato. I file non possono essere trasferiti fino a quando non sarà disponibile."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nessun file trovato. L\'altro dispositivo potrebbe essere bloccato. In questo caso, sbloccalo e riprova."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-iw/strings.xml b/packages/MtpDocumentsProvider/res/values-iw/strings.xml new file mode 100644 index 000000000000..62dfe7dd4ebb --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"מארח פרוטוקול העברת מדיה (MTP)"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"הורדות"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"גישה לקבצים מ-<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"המכשיר השני לא פנוי. ניתן יהיה להעביר קבצים רק לאחר שהוא יהיה זמין."</string> + <string name="error_locked_device" msgid="7557872102188356147">"לא נמצאו קבצים. ייתכן שהמכשיר השני נעול. אם כן, פתח אותו ונסה שוב."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ja/strings.xml b/packages/MtpDocumentsProvider/res/values-ja/strings.xml new file mode 100644 index 000000000000..4ae59f5d9037 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ホスト"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ダウンロード"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> からファイルにアクセスしています"</string> + <string name="error_busy_device" msgid="3997316850357386589">"接続先の端末は使用中のため、利用できるようになるまでファイルを転送できません。"</string> + <string name="error_locked_device" msgid="7557872102188356147">"ファイルが見つかりません。接続先の端末がロックされている可能性があります。その場合は、ロックを解除してからもう一度お試しください。"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ka/strings.xml b/packages/MtpDocumentsProvider/res/values-ka/strings.xml new file mode 100644 index 000000000000..33812dfbf3df --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ჰოსტი"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ჩამოტვირთვები"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"მიმდინარეობს <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>-ზე არსებულ ფაილებზე წვდომა"</string> + <string name="error_busy_device" msgid="3997316850357386589">"სხვა მოწყობილობა დაკავებულია. ფაილების გადატანა ვერ მოხერხდება, სანამ ის ხელმისაწვდომი არ გახდება."</string> + <string name="error_locked_device" msgid="7557872102188356147">"ფაილები ვერ მოიძებნა. მეორე მოწყობილობა შეიძლება დაბლოკილი იყოს. ამ შემთხვევაში, განბლოკეთ ის და ცადეთ ხელახლა."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-kk/strings.xml b/packages/MtpDocumentsProvider/res/values-kk/strings.xml new file mode 100644 index 000000000000..a6dea5b97b03 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP хосты"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Жүктеп алынғандар"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Файлдарға <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> құрылғысынан кіру"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Екінші құрылғы бос емес. Ол босамайынша, файлдар тасымалданбайды."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Ешқандай файл табылмады. Екінші құрылғы құлыптаулы болуы мүмкін. Құлыптаулы болса, құлпын ашып, қайталап көріңіз."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-km/strings.xml b/packages/MtpDocumentsProvider/res/values-km/strings.xml new file mode 100644 index 000000000000..baffa95c426b --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"ម៉ាស៊ីន MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ដោយឡូត"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"កំពុងចូលដំណើរការពី <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"ឧបករណ៍ផ្សេងទៀតកំពុងជាប់រវល់។ អ្នកមិនផ្ទេរឯកសារបានទេ រហូតទាល់តែវាអាចប្រើបាន។"</string> + <string name="error_locked_device" msgid="7557872102188356147">"រកមិនឃើញឯកសារទេ។ ឧបករណ៍ផ្សេងទៀតប្រហែលជាត្រូវបានចាក់សោ។ ប្រសិនបើវាត្រូវបានចាក់សោមែន សូមដោះសោ ហើយព្យាយាមម្តងទៀត។"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-kn/strings.xml b/packages/MtpDocumentsProvider/res/values-kn/strings.xml new file mode 100644 index 000000000000..3f16c142aba1 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ಹೋಸ್ಟ್"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ಡೌನ್ಲೋಡ್ಗಳು"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ನಿಂದ ಫೈಲ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಲಾಗುತ್ತಿದೆ"</string> + <string name="error_busy_device" msgid="3997316850357386589">"ಬೇರೆಯ ಸಾಧನವು ಕಾರ್ಯನಿರತವಾಗಿದೆ. ಇದು ಲಭ್ಯವಾಗುವವರೆಗೆ ಫೈಲ್ಗಳನ್ನು ನಿಮಗೆ ವರ್ಗಾಯಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string> + <string name="error_locked_device" msgid="7557872102188356147">"ಯಾವುದೇ ಫೈಲ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ. ಬೇರೆಯ ಸಾಧನವು ಲಾಕ್ ಆಗಿರಬಹುದು. ಹಾಗಾದಲ್ಲಿ, ಇದನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ko/strings.xml b/packages/MtpDocumentsProvider/res/values-ko/strings.xml new file mode 100644 index 000000000000..bbe2fe6d78a4 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP 호스트"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"다운로드"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>에서 파일에 액세스 중"</string> + <string name="error_busy_device" msgid="3997316850357386589">"다른 기기가 사용 중입니다. 다른 기기를 사용할 수 있을 때까지 파일을 전송할 수 없습니다."</string> + <string name="error_locked_device" msgid="7557872102188356147">"파일이 없습니다. 다른 기기가 잠겨 있을 수 있습니다. 기기의 잠금을 해제하고 다시 시도하세요."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ky/strings.xml b/packages/MtpDocumentsProvider/res/values-ky/strings.xml new file mode 100644 index 000000000000..e60a494a9919 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP хосту"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Жүктөлүп алынган нерселер"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> түзмөгүндөгү файлдар колдонулууда"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Берки түзмөк бош эмес. Ал бошомоюнча файлдарды өткөрө албайсыз."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Бир дагы файл табылган жок. Берки түзмөк кулпуланып турат окшойт. Кулпусун ачып, кайра аракет кылып көрүңүз."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-lo/strings.xml b/packages/MtpDocumentsProvider/res/values-lo/strings.xml new file mode 100644 index 000000000000..bcc0ee6b7ff3 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"ໂຮສ MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ການດາວໂຫລດ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"ກຳລັງເຂົ້າເຖິງໄຟລ໌ຈາກ <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"ອຸປະກອນອື່ນບໍ່ຫວ່າງເທື່ອ. ທ່ານບໍ່ສາມາດໂອນຍ້າຍໄຟລ໌ໄດ້ຈົນກວ່າມັນຈະຫວ່າງ."</string> + <string name="error_locked_device" msgid="7557872102188356147">"ບໍ່ພົບໄຟລ໌. ອຸປະກອນອີກເຄື່ອງອາດຖືກລັອກໄວ້ຢູ່. ຫາກມັນຖືກລັອກໄວ້, ໃຫ້ປົດລັອກມັນກ່ອນແລ້ວລອງໃໝ່ອີກຄັ້ງ."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-lt/strings.xml b/packages/MtpDocumentsProvider/res/values-lt/strings.xml new file mode 100644 index 000000000000..8bff3a8fe78a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MPP priegloba"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Atsisiuntimai"</string> + <string name="root_name" msgid="5819495383921089536">"„<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>“ <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Pasiekiami failai iš „<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>“"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Kitas įrenginys yra užsiėmęs. Failus galėsite perkelti tik tada, kai jis bus pasiekiamas."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nerasta failų. Gali būti, kad kitas įrenginys yra užrakintas. Jei taip yra, atrakinkite jį ir bandykite dar kartą."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-lv/strings.xml b/packages/MtpDocumentsProvider/res/values-lv/strings.xml new file mode 100644 index 000000000000..5e96338afaa0 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP saimniekdators"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Lejupielādes"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Piekļuve failiem no: <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Otra ierīce ir aizņemta. Varēsiet pārsūtīt failus tikai tad, kad tā būs pieejama."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Neviens fails netika atrasts. Iespējams, otra ierīce ir bloķēta. Ja tā ir, atbloķējiet ierīci un mēģiniet vēlreiz."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-mk/strings.xml b/packages/MtpDocumentsProvider/res/values-mk/strings.xml new file mode 100644 index 000000000000..6028b716ec9e --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-хост"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Преземања"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Се пристапува до датотеки од <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Другиот уред е зафатен. Не може да се пренесуваат датотеки сѐ додека не стане достапен."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Не се најдени датотеки. Другиот уред можеби е заклучен. Ако е така, отклучете го и обидете се повторно."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ml/strings.xml b/packages/MtpDocumentsProvider/res/values-ml/strings.xml new file mode 100644 index 000000000000..49eb847b1173 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ഹോസ്റ്റ്"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ഡൗണ്ലോഡുകൾ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ഉപകരണത്തിൽ നിന്ന് ഫയലുകൾ ആക്സസ്സ് ചെയ്യുന്നു"</string> + <string name="error_busy_device" msgid="3997316850357386589">"രണ്ടാമത്തെ ഉപകരണം തിരക്കിലാണ്. അത് ലഭ്യമാകുന്നത് വരെ നിങ്ങൾക്ക് ഫയലുകൾ കൈമാറാൻ കഴിയില്ല."</string> + <string name="error_locked_device" msgid="7557872102188356147">"ഫയലുകളൊന്നും കണ്ടെത്തിയില്ല. രണ്ടാമത്തെ ഉപകരണം ലോക്കുചെയ്ത നിലയിലായിരിക്കാം. ആണെങ്കിൽ, അൺലോക്കുചെയ്ത് വീണ്ടും ശ്രമിക്കുക."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-mn/strings.xml b/packages/MtpDocumentsProvider/res/values-mn/strings.xml new file mode 100644 index 000000000000..43b8204e7599 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Хост"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Таталт"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>-с файлд хандаж байна"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Нөгөө төхөөрөмж завгүй байна. Үүнийг боломжтой болох хүртэл файл шилжүүлэх боломжгүй."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Файл олдсонгүй. Нөгөө төхөөрөмж түгжигдсэн байж болзошгүй. Ингэсэн тохиолдолд түгжээг нь тайлаад, дахин оролдоно уу."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-mr/strings.xml b/packages/MtpDocumentsProvider/res/values-mr/strings.xml new file mode 100644 index 000000000000..5b856dc4ec19 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP होस्ट"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> मधून फायलींंमध्ये प्रवेश करीत आहे"</string> + <string name="error_busy_device" msgid="3997316850357386589">"अन्य डिव्हाइस व्यस्त आहे. ते उपलब्ध होईपर्यंत आपण फायली हस्तांतरित करू शकत नाही."</string> + <string name="error_locked_device" msgid="7557872102188356147">"कोणत्याही फायली आढळल्या नाहीत. अन्य डिव्हाइस कदाचित बंद असू शकते. तसे असल्यास, ते अनलॉक करा आणि पुन्हा प्रयत्न करा."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ms/strings.xml b/packages/MtpDocumentsProvider/res/values-ms/strings.xml new file mode 100644 index 000000000000..febec1d349af --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Hos MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Muat turun"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Mengakses fail daripada <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Peranti lain sedang sibuk. Anda tidak boleh memindahkan fail sehingga peranti itu tersedia."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Tiada fail ditemui. Peranti lain itu mungkin dikunci. Jika benar, sila buka kuncinya dan cuba lagi."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-my/strings.xml b/packages/MtpDocumentsProvider/res/values-my/strings.xml new file mode 100644 index 000000000000..8b509fbf0167 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP လက်ခံစက်"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ဒေါင်းလုဒ်များ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> မှ ဖိုင်များကို အသုံးပြုနေသည်"</string> + <string name="error_busy_device" msgid="3997316850357386589">"တခြားစက်ပစ္စည်းသည် မအားသေးပါ။ ၎င်းအဆင်သင့် မဖြစ်သေးသ၍ ဖိုင်များကို လွှဲပြောင်း၍ရမည် မဟုတ်ပါ။"</string> + <string name="error_locked_device" msgid="7557872102188356147">"မည်သည့်ဖိုင်မျှ မတွေ့ပါ။ ၎င်းစက်ပစ္စည်းကို လော့ခ်ချထားပုံရပါသည်။ သို့ဖြစ်လျှင် ၎င်းကိုလော့ခ်ဖြုတ်ပြီး ထပ်လုပ်ကြည့်ပါ။"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-nb/strings.xml b/packages/MtpDocumentsProvider/res/values-nb/strings.xml new file mode 100644 index 000000000000..40fabed73f40 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-vert"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Nedlastinger"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> på <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Bruker filer på <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Den andre enheten er opptatt. Du kan ikke overføre filer før den er tilgjengelig."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Ingen filer ble funnet. Den andre enheten kan være låst. I så fall må du låse den opp og prøve igjen."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ne/strings.xml b/packages/MtpDocumentsProvider/res/values-ne/strings.xml new file mode 100644 index 000000000000..53c0954d296e --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP होस्ट"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोडहरू"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> बाट फाइलहरूमाथि पहुँच राख्दै"</string> + <string name="error_busy_device" msgid="3997316850357386589">"अर्को यन्त्र व्यस्त छ। त्यो यन्त्र उपलब्ध नभएसम्म तपाईं फाइल स्थानान्तरण गर्न सक्नुहुन्न।"</string> + <string name="error_locked_device" msgid="7557872102188356147">"कुनै फाइल भेट्टिएन। अर्को यन्त्र लक गरिएको हुन सक्छ। यदि त्यसो हो भने त्यसलाई अनलक गरेर फेरि प्रयास गर्नुहोस्।"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-nl/strings.xml b/packages/MtpDocumentsProvider/res/values-nl/strings.xml new file mode 100644 index 000000000000..b1a01b2cd8a9 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Bestanden openen op <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Het andere apparaat wordt gebruikt. Je moet wachten tot het beschikbaar is om bestanden te kunnen overzetten."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Geen bestanden gevonden. Het kan zijn dat het andere apparaat is vergrendeld. Als dat het geval is, ontgrendel je het en probeer je het opnieuw."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-pa/strings.xml b/packages/MtpDocumentsProvider/res/values-pa/strings.xml new file mode 100644 index 000000000000..ab8ba1592ba7 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ਹੋਸਟ"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ਡਾਊਨਲੋਡ"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ਦੀਆਂ ਫ਼ਾਈਲਾਂ \'ਤੇ ਪਹੁੰਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string> + <string name="error_busy_device" msgid="3997316850357386589">"ਦੂਜੀ ਡੀਵਾਈਸ ਰੁਝੇਵੇਂ ਵਿੱਚ ਹੈ। ਉਸਦੇ ਉਪਲਬਧ ਹੋਣ ਤੱਕ ਤੁਸੀਂ ਫ਼ਾਈਲਾਂ ਦਾ ਤਬਾਦਲਾ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string> + <string name="error_locked_device" msgid="7557872102188356147">"ਕੋਈ ਫ਼ਾਈਲਾਂ ਨਹੀਂ ਮਿਲੀਆਂ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਦੂਜੀ ਡੀਵਾਈਸ ਲੌਕ ਹੋਵੇ। ਜੇਕਰ ਇੰਝ ਹੈ, ਤਾਂ ਉਸਨੂੰ ਅਨਲੌਕ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-pl/strings.xml b/packages/MtpDocumentsProvider/res/values-pl/strings.xml new file mode 100644 index 000000000000..69fa0f4473ca --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Pobrane"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> – <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Uzyskuję dostęp do plików na urządzeniu <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Drugie urządzenie jest zajęte. Dopóki nie będzie dostępne, nie możesz przesłać plików."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nie znaleziono plików. Drugie urządzenie może być zablokowane. Jeśli tak jest, odblokuj je i spróbuj ponownie."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-pt-rBR/strings.xml b/packages/MtpDocumentsProvider/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000000..03a14263f9c3 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host do MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Acessando arquivos do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Não é possível transferir arquivos até que ele esteja disponível."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nenhum arquivo encontrado. É possível que o outro dispositivo esteja bloqueado. Se for o caso, desbloqueie-o e tente novamente."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-pt-rPT/strings.xml b/packages/MtpDocumentsProvider/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000000..05d32d40fa27 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Anfitrião MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Transferências"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Aceder a ficheiros do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Não pode transferir os ficheiros enquanto não estiver disponível."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nenhum ficheiro encontrado. O outro dispositivo pode estar bloqueado. Se assim for, desbloqueie e tente novamente."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-pt/strings.xml b/packages/MtpDocumentsProvider/res/values-pt/strings.xml new file mode 100644 index 000000000000..03a14263f9c3 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host do MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Downloads"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Acessando arquivos do <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"O outro dispositivo está ocupado. Não é possível transferir arquivos até que ele esteja disponível."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nenhum arquivo encontrado. É possível que o outro dispositivo esteja bloqueado. Se for o caso, desbloqueie-o e tente novamente."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ro/strings.xml b/packages/MtpDocumentsProvider/res/values-ro/strings.xml new file mode 100644 index 000000000000..21ebc57836b4 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Gazdă MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Descărcări"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Se accesează fișierele de pe <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Celălalt dispozitiv este ocupat. Nu puteți să transferați fișiere înainte să fie disponibil."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nu s-au găsit fișiere. Este posibil ca celălalt dispozitiv să fie blocat. În acest caz, deblocați-l și încercați din nou."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ru/strings.xml b/packages/MtpDocumentsProvider/res/values-ru/strings.xml new file mode 100644 index 000000000000..717f12f5403f --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-хост"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Загрузки"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="STORAGE_NAME">%2$s</xliff:g> <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Доступ к файлам на устройстве <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>…"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Другое устройство занято. Вы сможете передать файлы, когда оно будет доступно."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Файлы не найдены. Если другое устройство заблокировано, разблокируйте его и повторите попытку."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-si/strings.xml b/packages/MtpDocumentsProvider/res/values-si/strings.xml new file mode 100644 index 000000000000..7a096b0a356a --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP සංග්රාහක"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"බාගැනීම්"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> වෙතින් ගොනු වෙත පිවිසීම"</string> + <string name="error_busy_device" msgid="3997316850357386589">"අනෙක් උපාංගය කාර්ය බහුලය. එය ලබා ගත හැකි වන තෙක් ඔබට ගොනු මාරු කළ නොහැකිය."</string> + <string name="error_locked_device" msgid="7557872102188356147">"ගොනු හමු නොවීය. අනෙක් උපාංගය අගුලු දමා තිබිය හැකිය. එසේ නම්, එය අගුලු හැර නැවත උත්සාහ කරන්න."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-sk/strings.xml b/packages/MtpDocumentsProvider/res/values-sk/strings.xml new file mode 100644 index 000000000000..365e1b7ba0ae --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Hostiteľ MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Stiahnuté súbory"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Prístup k súborom zo zariadenia <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Druhé zariadenie je zaneprázdnené. Súbory bude možné preniesť, keď bude k dispozícii."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nenašli sa žiadne súbory. Druhé zariadenie môže byť uzamknuté. Ak je to tak, odomknite ho a skúste to znova."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-sl/strings.xml b/packages/MtpDocumentsProvider/res/values-sl/strings.xml new file mode 100644 index 000000000000..60945d64fe8f --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Gostitelj MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Prenosi"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Dostopanje do datotek iz naprave <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Druga naprava ni na voljo. Dokler ne bo na voljo, ne bo mogoče prenašati datotek."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Ni datotek. Druga naprava je morda zaklenjena. Če je zaklenjena, jo odklenite in poskusite znova."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-sq/strings.xml b/packages/MtpDocumentsProvider/res/values-sq/strings.xml new file mode 100644 index 000000000000..d92f29f6db60 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Pritësi i protokollit MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Shkarkimet"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Po qaset te skedarët nga <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Pajisja tjetër është e zënë. Nuk mund të transferosh skedarë deri sa të jetë në dispozicion."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Nuk u gjet asnjë skedar. Pajisja tjetër mund të jetë e kyçur. Nëse po, shkyçe dhe provo përsëri."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-sr/strings.xml b/packages/MtpDocumentsProvider/res/values-sr/strings.xml new file mode 100644 index 000000000000..d91c5c4354ce --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP хост"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Преузимања"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Приступ датотекама са уређаја <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Други уређај је заузет. Датотеке можете да пренесете тек кад он постане доступан."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Није пронађена ниједна датотека. Други уређај је можда закључан. Ако јесте, откључајте га и покушајте поново."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-sv/strings.xml b/packages/MtpDocumentsProvider/res/values-sv/strings.xml new file mode 100644 index 000000000000..26818eb220ce --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP-värd"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Nedladdningar"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Åtkomst till filer från <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Den andra enheten är upptagen. Du kan inte överföra filer förrän den är tillgänglig."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Inga filer hittades. Den andra enheten kan vara låst. Om den är det låser du upp den och försöker igen."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-sw/strings.xml b/packages/MtpDocumentsProvider/res/values-sw/strings.xml new file mode 100644 index 000000000000..de3ed54b367f --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-sw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Seva pangishi ya MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Vipakuliwa"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Inafikia faili kwenye <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Kifaa hicho kingine kinatumika. Huwezi kuhamisha faili hadi kipatikane."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Hakuna faili zilizopatikana. Huenda kifaa hicho kingine kimefungwa. Ikiwa kimefungwa, kifungue na ujaribu tena."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ta/strings.xml b/packages/MtpDocumentsProvider/res/values-ta/strings.xml new file mode 100644 index 000000000000..c6e6e6204e2f --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP ஹோஸ்ட்"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"இறக்கங்கள்"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> இலிருந்து கோப்புகளை அணுகுகிறது"</string> + <string name="error_busy_device" msgid="3997316850357386589">"பிற சாதனம் பணிமிகுதியில் உள்ளதால், அந்தப் பணி முடியும் வரை கோப்புகளை இடமாற்ற முடியாது."</string> + <string name="error_locked_device" msgid="7557872102188356147">"கோப்புகள் இல்லை. பிற சாதனம் பூட்டப்பட்டிருக்கக்கூடும் என்பதால் முதலில் அதைத் திறந்து, மீண்டும் முயலவும்."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-te/strings.xml b/packages/MtpDocumentsProvider/res/values-te/strings.xml new file mode 100644 index 000000000000..7add85835da7 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP హోస్ట్"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"డౌన్లోడ్లు"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> నుండి ఫైల్లను ప్రాప్యత చేస్తోంది"</string> + <string name="error_busy_device" msgid="3997316850357386589">"ఇతర పరికరం బిజీగా ఉంది. అది అందుబాటులోకి వచ్చే వరకు మీరు ఫైల్లను బదిలీ చేయలేరు."</string> + <string name="error_locked_device" msgid="7557872102188356147">"ఫైల్లు ఏవీ కనుగొనబడలేదు. ఇతర పరికరం లాక్ చేయబడి ఉండవచ్చు. అలా జరిగి ఉంటే, దాన్ని అన్లాక్ చేసి, ఆపై మళ్లీ ప్రయత్నించండి."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-th/strings.xml b/packages/MtpDocumentsProvider/res/values-th/strings.xml new file mode 100644 index 000000000000..d2b62fe516e1 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"โฮสต์ MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ดาวน์โหลด"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"กำลังเข้าถึงไฟล์จาก <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"อุปกรณ์อีกเครื่องหนึ่งไม่ว่าง คุณไม่สามารถโอนไฟล์จนกว่าอุปกรณ์จะสามารถใช้ได้"</string> + <string name="error_locked_device" msgid="7557872102188356147">"ไม่พบไฟล์ อุปกรณ์อีกเครื่องหนึ่งอาจล็อกอยู่ หากเป็นเช่นนั้น ให้ปลดล็อกและลองอีกครั้ง"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-tl/strings.xml b/packages/MtpDocumentsProvider/res/values-tl/strings.xml new file mode 100644 index 000000000000..68b2eba38ea3 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Host ng MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Mga Download"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Nag-a-access ng mga file mula sa <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Abala ang kabilang device. Hindi ka makakapaglipat ng mga file hanggang sa maging available ito."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Walang natagpuang mga file. Maaaring naka-lock ang kabilang device. Kung gayon, i-unlock ito at subukang muli."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-tr/strings.xml b/packages/MtpDocumentsProvider/res/values-tr/strings.xml new file mode 100644 index 000000000000..14250ef527c7 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Ana Makinesi"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"İndirilenler"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> cihazdaki dosyalara erişiliyor"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Diğer cihaz meşgul. Cihaz kullanılabilir duruma gelene kadar dosyaları aktaramazsınız."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Hiçbir dosya bulunamadı. Diğer cihaz kilitli olabilir. Kilitliyse, kilidini açıp tekrar deneyin."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-uk/strings.xml b/packages/MtpDocumentsProvider/res/values-uk/strings.xml new file mode 100644 index 000000000000..8589f8c594b6 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Хост MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Завантаження"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Відкриваються файли з пристрою <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Інший пристрій зайнятий. Щоб передавати файли, він має бути доступним."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Не вдалося знайти файли. Можливо, інший пристрій заблоковано. У такому разі розблокуйте його та повторіть спробу."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-ur/strings.xml b/packages/MtpDocumentsProvider/res/values-ur/strings.xml new file mode 100644 index 000000000000..17578ae51b9f --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP میزبان"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"ڈاؤن لوڈز"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> سے فائلوں کی رسائی ہو رہی ہے"</string> + <string name="error_busy_device" msgid="3997316850357386589">"دوسرا آلہ مصروف ہے۔ اس کے دستیاب ہونے تک آپ فائلیں منتقل نہیں کر سکتے۔"</string> + <string name="error_locked_device" msgid="7557872102188356147">"کوئی فائلیں نہیں ملیں۔ ہو سکتا ہے دوسرا آلہ مقفل ہو۔ اگر ایسا ہے تو اسے غیر مقفل کریں اور دوبارہ کوشش کریں۔"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-uz/strings.xml b/packages/MtpDocumentsProvider/res/values-uz/strings.xml new file mode 100644 index 000000000000..c511172076c0 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP Host"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Yuklanmalar"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g><xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> qurilmasidan fayllar o‘qilmoqda"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Ulangan qurilma band. U bo‘shamaguncha fayllarni o‘tkazib bo‘lmaydi."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Hech qanday fayl topilmadi. Ulangan qurilma qulflangan bo‘lishi mumkin. Agar shunday bo‘lsa, uni qulfdan chiqaring va qayta urinib ko‘ring."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-vi/strings.xml b/packages/MtpDocumentsProvider/res/values-vi/strings.xml new file mode 100644 index 000000000000..0eb63106d85e --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Máy chủ MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Tải xuống"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Đang truy cập tệp từ <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Thiết bị khác đang bận. Bạn không thể chuyển tệp cho đến khi thiết bị rảnh."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Không tìm thấy tệp. Thiết bị khác có thể đã bị khóa. Nếu như vậy, hãy mở khóa thiết bị rồi thử lại."</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-zh-rCN/strings.xml b/packages/MtpDocumentsProvider/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000000..7f1f3942c911 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"MTP 主机"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"下载"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"正在访问 <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 的文件"</string> + <string name="error_busy_device" msgid="3997316850357386589">"另一台设备正忙。您必须等到该设备可用时才能传输文件。"</string> + <string name="error_locked_device" msgid="7557872102188356147">"未找到任何文件。另一台设备可能处于锁定状态;如果是这样,请解锁该设备并重试。"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-zh-rHK/strings.xml b/packages/MtpDocumentsProvider/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000000..be8c5482c13c --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"媒體傳輸協定主機"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"下載"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 的「<xliff:g id="STORAGE_NAME">%2$s</xliff:g>」"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"正在從 <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 存取檔案"</string> + <string name="error_busy_device" msgid="3997316850357386589">"另一部裝置目前處於忙碌狀態,要等到該裝置可用時才能轉移檔案。"</string> + <string name="error_locked_device" msgid="7557872102188356147">"找不到檔案。如果另一部裝置處於鎖定狀態,請解鎖該裝置,然後再試一次。"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-zh-rTW/strings.xml b/packages/MtpDocumentsProvider/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000000..2fe3c06898e0 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"媒體傳輸通訊協定主機"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"下載"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"正在從 <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> 存取檔案"</string> + <string name="error_busy_device" msgid="3997316850357386589">"另一個裝置忙碌中。必須等到該裝置可用時才能轉移檔案。"</string> + <string name="error_locked_device" msgid="7557872102188356147">"找不到任何檔案。如果另一個裝置處於鎖定狀態,請將該裝置解鎖後再試一次。"</string> +</resources> diff --git a/packages/MtpDocumentsProvider/res/values-zu/strings.xml b/packages/MtpDocumentsProvider/res/values-zu/strings.xml new file mode 100644 index 000000000000..f3f720676b22 --- /dev/null +++ b/packages/MtpDocumentsProvider/res/values-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<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="6271216747302322594">"Ukusingatha kwe-MTP"</string> + <string name="downloads_app_label" msgid="7120690641874849726">"Okulandiwe"</string> + <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"Ifinyelela kumafayela kusukela ku-<xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string> + <string name="error_busy_device" msgid="3997316850357386589">"Enye idivayisi imatasatasa. Awukwazi ukudlulisela amafayela ize itholakale."</string> + <string name="error_locked_device" msgid="7557872102188356147">"Awekho amafayela atholiwe. Enye idivayisi kungenzeka ikhiyiwe. Uma kunjalo, yivule uphinde uzame futhi."</string> +</resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java index fc1a3a902c73..38fe8790e4d0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java +++ b/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java @@ -4,7 +4,6 @@ import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceScreen; -import java.util.List; /** * A controller that manages event for preference. @@ -40,17 +39,6 @@ public abstract class AbstractPreferenceController { } /** - * Updates non-indexable keys for search provider. - * - * Called by SearchIndexProvider#getNonIndexableKeys - */ - public void updateNonIndexableKeys(List<String> keys) { - if (!isAvailable()) { - keys.add(getPreferenceKey()); - } - } - - /** * Returns true if preference is available (should be displayed) */ public abstract boolean isAvailable(); diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java index 1bb141706736..924a82f0b1f4 100755 --- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java +++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java @@ -28,6 +28,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.Path.Direction; import android.graphics.Path.FillType; +import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -82,6 +83,7 @@ public class BatteryMeterDrawableBase extends Drawable { private final float[] mPlusPoints; private final Path mPlusPath = new Path(); + private final Rect mPadding = new Rect(); private final RectF mFrame = new RectF(); private final RectF mButtonFrame = new RectF(); private final RectF mBoltFrame = new RectF(); @@ -219,12 +221,40 @@ public class BatteryMeterDrawableBase extends Drawable { @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); - mHeight = bottom - top; - mWidth = right - left; + updateSize(); + } + + private void updateSize() { + final Rect bounds = getBounds(); + + mHeight = (bounds.bottom - mPadding.bottom) - (bounds.top + mPadding.top); + mWidth = (bounds.right - mPadding.right) - (bounds.left + mPadding.left); mWarningTextPaint.setTextSize(mHeight * 0.75f); mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; } + @Override + public boolean getPadding(Rect padding) { + if (mPadding.left == 0 + && mPadding.top == 0 + && mPadding.right == 0 + && mPadding.bottom == 0) { + return super.getPadding(padding); + } + + padding.set(mPadding); + return true; + } + + public void setPadding(int left, int top, int right, int bottom) { + mPadding.left = left; + mPadding.top = top; + mPadding.right = right; + mPadding.bottom = bottom; + + updateSize(); + } + private int getColorForLevel(int percent) { // If we are in power save mode, always use the normal color. if (mPowerSaveEnabled) { @@ -255,6 +285,10 @@ public class BatteryMeterDrawableBase extends Drawable { invalidateSelf(); } + protected int batteryColorForLevel(int level) { + return mCharging ? mChargeColor : getColorForLevel(level); + } + @Override public void draw(Canvas c) { final int level = mLevel; @@ -264,11 +298,10 @@ public class BatteryMeterDrawableBase extends Drawable { float drawFrac = (float) level / 100f; final int height = mHeight; final int width = (int) (ASPECT_RATIO * mHeight); - int px = (mWidth - width) / 2; - + final int px = (mWidth - width) / 2; final int buttonHeight = Math.round(height * mButtonHeightFraction); - mFrame.set(0, 0, width, height); + mFrame.set(mPadding.left, mPadding.top, width + mPadding.left, height + mPadding.top); mFrame.offset(px, 0); // button-frame: area above the battery body @@ -282,7 +315,7 @@ public class BatteryMeterDrawableBase extends Drawable { mFrame.top += buttonHeight; // set the battery charging color - mBatteryPaint.setColor(mCharging ? mChargeColor : getColorForLevel(level)); + mBatteryPaint.setColor(batteryColorForLevel(level)); if (level >= FULL) { drawFrac = 1f; diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java index 83667ea00629..aa92fa40a91b 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java @@ -3,6 +3,7 @@ package com.android.settingslib.graph; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; +import android.graphics.Rect; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -68,4 +69,36 @@ public class BatteryMeterDrawableBaseTest { } } } + + @Test + public void testPadding_returnsCorrectValues() { + // different pads on each side to differentiate + final int left = 1; + final int top = 2; + final int right = 3; + final int bottom = 4; + + final Rect expected = new Rect(left, top, right, bottom); + final Rect padding = new Rect(); + + mBatteryDrawable.setPadding(left, top, right, bottom); + + assertThat(mBatteryDrawable.getPadding(padding)).isEqualTo(true); + assertThat(padding).isEqualTo(expected); + } + + @Test + public void testPadding_falseIfUnsetOrZero() { + final Rect padding = new Rect(); + assertThat(mBatteryDrawable.getPadding(padding)).isEqualTo(false); + assertThat(isRectZero(padding)).isEqualTo(true); + + mBatteryDrawable.setPadding(0, 0, 0, 0); + assertThat(mBatteryDrawable.getPadding(padding)).isEqualTo(false); + assertThat(isRectZero(padding)).isEqualTo(true); + } + + private boolean isRectZero(Rect r) { + return r.left == 0 && r.top == 0 && r.right == 0 && r.bottom == 0; + } } diff --git a/packages/Shell/res/layout/dialog_bugreport_info.xml b/packages/Shell/res/layout/dialog_bugreport_info.xml index bb3084f5c10a..4bd871103193 100644 --- a/packages/Shell/res/layout/dialog_bugreport_info.xml +++ b/packages/Shell/res/layout/dialog_bugreport_info.xml @@ -19,39 +19,51 @@ android:paddingTop="15dp" android:paddingStart="24dp" android:paddingEnd="24dp" - android:focusableInTouchMode="true" + android:focusableInTouchMode="false" + android:focusable="false" + android:importantForAutofill="noExcludeDescendants" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView + android:focusableInTouchMode="false" + android:focusable="false" android:inputType="textNoSuggestions" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/bugreport_info_name"/> <EditText android:id="@+id/name" + android:nextFocusDown="@+id/title" android:maxLength="30" android:singleLine="true" android:inputType="textNoSuggestions" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView + android:focusableInTouchMode="false" + android:focusable="false" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/bugreport_info_title"/> <EditText android:id="@+id/title" + android:nextFocusUp="@+id/name" + android:nextFocusDown="@+id/description" android:maxLength="80" android:singleLine="true" android:inputType="textAutoCorrect|textCapSentences" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView + android:focusableInTouchMode="false" + android:focusable="false" android:layout_width="match_parent" android:layout_height="wrap_content" android:editable="false" android:text="@string/bugreport_info_description"/> <EditText android:id="@+id/description" + android:nextFocusUp="@+id/title" android:singleLine="false" android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:layout_width="match_parent" diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java index d9719f356f14..f59c4a56bf3b 100644 --- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java +++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java @@ -29,6 +29,7 @@ import android.util.Range; import com.google.android.colorextraction.ColorExtractor.GradientColors; +import java.util.Arrays; import java.util.List; /** @@ -311,6 +312,12 @@ public class Tonal implements ExtractionType { final float maxHue; TonalPalette(float[] h, float[] s, float[] l) { + if (h.length != s.length || s.length != l.length) { + throw new IllegalArgumentException("All arrays should have the same size. h: " + + Arrays.toString(h) + " s: " + Arrays.toString(s) + " l: " + + Arrays.toString(l)); + } + this.h = h; this.s = s; this.l = l; @@ -388,7 +395,7 @@ public class Tonal implements ExtractionType { new float[] {0.70f, 0.72f, 0.69f, 0.6703296703296703f, 0.728813559322034f, 0.5657142857142856f, 0.5076923076923077f, 0.3944223107569721f, 0.6206896551724138f, 0.8931297709923666f, 1f, 1f, 1f}, - new float[] {0.05f, 0.08f, 0.1784313725490196f, 0.23137254901960785f, + new float[] {0.05f, 0.08f, 0.14f, 0.1784313725490196f, 0.23137254901960785f, 0.3431372549019608f, 0.38235294117647056f, 0.49215686274509807f, 0.6588235294117647f, 0.7431372549019608f, 0.8176470588235294f, 0.8784313725490196f, 0.9294117647058824f} @@ -442,7 +449,7 @@ public class Tonal implements ExtractionType { 0.8285256410256411f, 0.821522309711286f, 0.8083333333333333f, 0.8046594982078853f, 0.8005822416302766f, 0.7842377260981912f, 0.7771084337349398f, 0.7747747747747749f}, - new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, + new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.737142857142857f, 0.6434108527131781f, 0.46835443037974644f}, new float[] {0.05f, 0.08f, 0.12745098039215685f, 0.15490196078431373f, 0.20392156862745098f, 0.24901960784313726f, 0.3137254901960784f, diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java index d8bebabf0c5e..12f75bb2d56c 100644 --- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java +++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java @@ -29,10 +29,8 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.PowerManager; import android.os.SystemClock; -import android.os.UserHandle; import android.provider.Settings; import android.text.InputType; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -252,9 +250,9 @@ public class PasswordTextView extends View { mText = mText.substring(0, length - 1); CharState charState = mTextChars.get(length - 1); charState.startRemoveAnimation(0, 0); + sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0); } userActivity(); - sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0); } public String getText() { diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java index 14e15ec5716d..5ea18f22fbc9 100644 --- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java +++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java @@ -98,9 +98,13 @@ public class RoundedCorners extends SystemUI implements Tunable { TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING, padding, FLAG_END); - FragmentHostManager.get(sb.getNavigationBarWindow()).addTagListener( + View navigationBarWindow = sb.getNavigationBarWindow(); + // Not all devices have on screen navigation bars. + if (navigationBarWindow != null) { + FragmentHostManager.get(navigationBarWindow).addTagListener( NavigationBarFragment.TAG, new TunablePaddingTagListener(padding, 0)); + } FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar); fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG, diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 4a459974fcb6..9034c3fd926e 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -26,8 +26,10 @@ import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.os.Process; import android.os.SystemProperties; +import android.os.Trace; import android.os.UserHandle; import android.util.ArraySet; +import android.util.BootTimingsTraceLog; import android.util.Log; import com.android.systemui.fragments.FragmentService; @@ -190,11 +192,17 @@ public class SystemUIApplication extends Application implements SysUiServiceProv Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); + BootTimingsTraceLog log = new BootTimingsTraceLog("SystemUIBootTiming", + Trace.TRACE_TAG_APP); + log.traceBegin("StartServices"); final int N = services.length; for (int i = 0; i < N; i++) { Class<?> cl = services[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); + log.traceBegin("StartServices" + cl.getSimpleName()); + long ti = System.currentTimeMillis(); try { + Object newService = SystemUIFactory.getInstance().createInstance(cl); mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService); } catch (IllegalAccessException ex) { @@ -207,11 +215,18 @@ public class SystemUIApplication extends Application implements SysUiServiceProv mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); mServices[i].start(); + log.traceEnd(); + // Warn if initialization of component takes too long + ti = System.currentTimeMillis() - ti; + if (ti > 1000) { + Log.w(TAG, "Initialization of " + cl.getName() + " took " + ti + " ms"); + } if (mBootCompleted) { mServices[i].onBootCompleted(); } } + log.traceEnd(); Dependency.get(PluginManager.class).addPluginListener( new PluginListener<OverlayPlugin>() { private ArraySet<OverlayPlugin> mOverlays; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index 6b507645e4d0..8f1880039857 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -161,7 +161,8 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha QSTileLayout tileLayout = mQsPanel.getTileLayout(); mAllViews.add((View) tileLayout); - int heightDiff = mQsPanel.getBottom() - mQs.getHeader().getBottom() + int height = mQs.getView() != null ? mQs.getView().getMeasuredHeight() : 0; + int heightDiff = height - mQs.getHeader().getBottom() + mQs.getHeader().getPaddingBottom(); firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 90275c50b54a..bb3672511c48 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -253,7 +253,8 @@ public class QSFragment extends Fragment implements QS { } mHeader.setExpansion(mKeyguardShowing ? 1 : expansion); mFooter.setExpansion(mKeyguardShowing ? 1 : expansion); - int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom(); + int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom() + + mFooter.getHeight(); mQSPanel.setTranslationY(translationScaleY * heightDiff); mQSDetail.setFullyExpanded(expansion == 1); @@ -262,7 +263,7 @@ public class QSFragment extends Fragment implements QS { } // Set bounds on the QS panel so it doesn't run over the header. - mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion)); + mQsBounds.top = (int) -mQSPanel.getTranslationY(); mQsBounds.right = mQSPanel.getWidth(); mQsBounds.bottom = mQSPanel.getHeight(); mQSPanel.setClipBounds(mQsBounds); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index 918c00c2337f..089d07a567dd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -15,10 +15,13 @@ */ package com.android.systemui.qs.tiles; +import android.content.Context; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.settingslib.graph.BatteryMeterDrawableBase; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.qs.QSTile.BooleanState; @@ -79,7 +82,9 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements protected void handleUpdateState(BooleanState state, Object arg) { state.state = mCharging ? Tile.STATE_UNAVAILABLE : mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver); + BatterySaverIcon bsi = new BatterySaverIcon(); + bsi.mState = state.state; + state.icon = bsi; state.label = mContext.getString(R.string.battery_detail_switch_title); state.contentDescription = state.label; state.value = mPowerSave; @@ -99,4 +104,41 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements mPowerSave = isPowerSave; refreshState(null); } -}
\ No newline at end of file + + public static class BatterySaverIcon extends Icon { + private int mState; + + @Override + public Drawable getDrawable(Context context) { + BatterySaverDrawable b = new BatterySaverDrawable(context, 0); + b.mState = mState; + final int pad = context.getResources() + .getDimensionPixelSize(R.dimen.qs_tile_divider_height); + b.setPadding(pad, pad, pad, pad); + return b; + } + } + + private static class BatterySaverDrawable extends BatteryMeterDrawableBase { + private int mState; + private static final int MAX_BATTERY = 100; + + BatterySaverDrawable(Context context, int frameColor) { + super(context, frameColor); + // Show as full so it's always uniform color + super.setBatteryLevel(MAX_BATTERY); + setPowerSave(true); + setCharging(false); + } + + @Override + protected int batteryColorForLevel(int level) { + return QSTileImpl.getColorForState(mContext, mState); + } + + @Override + public void setBatteryLevel(int val) { + // Don't change the actual level, otherwise this won't draw correctly + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index d77796144282..2d3e0b6829ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -226,6 +226,9 @@ public class KeyButtonView extends ImageView implements ButtonInterface { case MotionEvent.ACTION_UP: final boolean doIt = isPressed() && !mLongClicked; setPressed(false); + // Always send a release ourselves because it doesn't seem to be sent elsewhere + // and it feels weird to sometimes get a release haptic and other times not. + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE); if (mCode != 0) { if (doIt) { sendEvent(KeyEvent.ACTION_UP, 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index bd7fee0f7f52..b6c76551c48b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -341,6 +341,10 @@ public class MobileSignalController extends SignalController< } private boolean isRoaming() { + // During a carrier change, roaming indications need to be supressed. + if (isCarrierNetworkChangeActive()) { + return false; + } if (isCdma()) { final int iconMode = mServiceState.getCdmaEriIconMode(); return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index be3802bd68ed..cba9f77df2ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -494,6 +494,79 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { DEFAULT_ICON /* typeIcon */); } + @Test + public void testCarrierNetworkChange_roamingBeforeNetworkChange() { + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + + setupDefaultSignal(); + setLevel(strength); + setGsmRoaming(true); + + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); + + // API call is made + setCarrierNetworkChange(true /* enabled */); + + // Carrier network change is true, show special indicator, no roaming. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + 0 /* typeIcon */, + false /* roaming */); + + // Revert back + setCarrierNetworkChange(false /* enabled */); + + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); + } + + @Test + public void testCarrierNetworkChange_roamingAfterNetworkChange() { + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + + setupDefaultSignal(); + setLevel(strength); + + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + false /* roaming */); + + // API call is made + setCarrierNetworkChange(true /* enabled */); + + // Carrier network change is true, show special indicator, no roaming. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + 0 /* typeIcon */, + false /* roaming */); + + setGsmRoaming(true); + + // Roaming should not show. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + 0 /* typeIcon */, + false /* roaming */); + + // Revert back + setCarrierNetworkChange(false /* enabled */); + + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); + } + private void verifyEmergencyOnly(boolean isEmergencyOnly) { ArgumentCaptor<Boolean> emergencyOnly = ArgumentCaptor.forClass(Boolean.class); Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setEmergencyCallsOnly( diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 2edcd71721ca..39ee6cf4a234 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3546,7 +3546,7 @@ message MetricsEvent { STORAGE_FILES = 841; // FIELD - Rank of the clicked Settings search result - FIELD_SETTINGS_SERACH_RESULT_RANK = 842; + FIELD_SETTINGS_SEARCH_RESULT_RANK = 842; // OPEN: Settings > Apps > Default Apps > Assist > Default assist DEFAULT_ASSIST_PICKER = 843; @@ -4039,10 +4039,10 @@ message MetricsEvent { ACTION_SETTINGS_UPDATE_DEFAULT_APP = 1000; // FIELD - Query length when Settings search result is clicked - FIELD_SETTINGS_SERACH_QUERY_LENGTH = 1001; + FIELD_SETTINGS_SEARCH_QUERY_LENGTH = 1001; // FIELD - Number of results when Settings search result is clicked - FIELD_SETTINGS_SERACH_RESULT_COUNT = 1002; + FIELD_SETTINGS_SEARCH_RESULT_COUNT = 1002; // OPEN: Settings > Display > Ambient Display // CATEGORY: SETTINGS diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 902353e8a3f1..a31c33e4ab91 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -17,6 +17,7 @@ package com.android.server.am; import static android.app.Activity.RESULT_CANCELED; +import static android.app.ActivityManager.START_ABORTED; import static android.app.ActivityManager.START_CANCELED; import static android.app.ActivityManager.START_CLASS_NOT_FOUND; import static android.app.ActivityManager.START_DELIVERED_TO_TOP; @@ -117,7 +118,6 @@ import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; import android.util.EventLog; -import android.util.Printer; import android.util.Slog; import com.android.internal.app.HeavyWeightSwitcherActivity; @@ -130,7 +130,6 @@ import java.io.PrintWriter; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.List; /** * Controller for interpreting how and then launching activities. @@ -248,34 +247,6 @@ class ActivityStarter { mUsingVr2dDisplay = false; } - // TODO(b/38121026): Remove once issue has been resolved. - private class ActivityInfoAssignment { - final ActivityInfo info; - final String description; - final long timestamp; - - public ActivityInfoAssignment(ActivityInfo info, String description) { - timestamp = System.currentTimeMillis(); - this.info = info; - this.description = description; - } - - void dump(PrintWriter pw, String prefix) { - pw.println(prefix + " " + timestamp + ":" + description + ":" + describeInfo()); - } - - private String describeInfo() { - return "ActivityInfo[obj:" + info + " userId:" - + (info != null ? UserHandle.getUserId(info.applicationInfo.uid) : 0) + "]"; - } - } - - private List<ActivityInfoAssignment> mLastStartActivityInfoAssignments = new ArrayList<>(); - - private void addActivityInfoAssignment(ActivityInfo info, String description) { - mLastStartActivityInfoAssignments.add(new ActivityInfoAssignment(info, description)); - } - ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) { mService = service; mSupervisor = supervisor; @@ -283,8 +254,6 @@ class ActivityStarter { mUsingVr2dDisplay = false; } - - int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, @@ -293,8 +262,6 @@ class ActivityStarter { ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask, String reason) { - mLastStartActivityInfoAssignments.clear(); - addActivityInfoAssignment(aInfo, "startActivityLocked::initial"); if (TextUtils.isEmpty(reason)) { throw new IllegalArgumentException("Need to specify a reason."); @@ -313,7 +280,9 @@ class ActivityStarter { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } - return mLastStartActivityResult; + + // Aborted results are treated as successes externally, but we must track them internally. + return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS; } /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */ @@ -486,7 +455,6 @@ class ActivityStarter { intent = mInterceptor.mIntent; rInfo = mInterceptor.mRInfo; aInfo = mInterceptor.mAInfo; - addActivityInfoAssignment(aInfo, "startActivity::mInterceptor.mAInfo"); resolvedType = mInterceptor.mResolvedType; inTask = mInterceptor.mInTask; callingPid = mInterceptor.mCallingPid; @@ -500,7 +468,7 @@ class ActivityStarter { // We pretend to the caller that it was really started, but // they will just get a cancel result. ActivityOptions.abort(options); - return START_SUCCESS; + return START_ABORTED; } // If permissions need a review before any of the app components can run, we @@ -533,7 +501,6 @@ class ActivityStarter { rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); - addActivityInfoAssignment(aInfo, "startActivity::isPermissionReviewRequired"); if (DEBUG_PERMISSIONS_REVIEW) { Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, @@ -558,14 +525,12 @@ class ActivityStarter { callingPid = realCallingPid; aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); - addActivityInfoAssignment(aInfo, "startActivity::auxiliaryInfo != null"); } ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, container, options, sourceRecord); - addActivityInfoAssignment(aInfo, "startActivity:: value used to create new activity"); if (outActivity != null) { outActivity[0] = r; } @@ -2366,16 +2331,6 @@ class ActivityStarter { pw.println(prefix + "mStartActivity:"); mStartActivity.dump(pw, prefix + " "); } - - if (!mLastStartActivityInfoAssignments.isEmpty()) { - pw.println(prefix + "mLastStartActivityInfoAssignments:"); - for (ActivityInfoAssignment assignment : mLastStartActivityInfoAssignments) { - assignment.dump(pw, prefix); - /*pw.println(prefix + prefix + assignment.description + "@" + p - + ":" + assignment.info);*/ - } - } - if (mIntent != null) { pw.println(prefix + "mIntent=" + mIntent); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 13054a643e52..468cb2990b67 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -60,6 +60,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; @@ -166,6 +167,8 @@ public final class ContentService extends IContentService.Stub { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw_)) return; final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, " "); + final boolean dumpAll = ArrayUtils.contains(args, "-a"); + // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. final long identityToken = clearCallingIdentity(); @@ -173,7 +176,7 @@ public final class ContentService extends IContentService.Stub { if (mSyncManager == null) { pw.println("No SyncManager created! (Disk full?)"); } else { - mSyncManager.dump(fd, pw); + mSyncManager.dump(fd, pw, dumpAll); } pw.println(); pw.println("Observer tree:"); @@ -603,7 +606,7 @@ public final class ContentService extends IContentService.Stub { SyncStorageEngine.EndPoint info; info = new SyncStorageEngine.EndPoint(account, authority, userId); syncManager.clearScheduledSyncOperations(info); - syncManager.cancelActiveSync(info, null /* all syncs for this adapter */); + syncManager.cancelActiveSync(info, null /* all syncs for this adapter */, "API"); } } finally { restoreCallingIdentity(identityToken); @@ -631,7 +634,7 @@ public final class ContentService extends IContentService.Stub { } // Cancel active syncs and clear pending syncs from the queue. syncManager.cancelScheduledSyncOperation(info, extras); - syncManager.cancelActiveSync(info, extras); + syncManager.cancelActiveSync(info, extras, "API"); } finally { restoreCallingIdentity(identityToken); } diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java index a621d7376b7f..1f02ebfc4972 100644 --- a/services/core/java/com/android/server/content/SyncJobService.java +++ b/services/core/java/com/android/server/content/SyncJobService.java @@ -34,6 +34,8 @@ public class SyncJobService extends JobService { private Messenger mMessenger; private SparseArray<JobParameters> jobParamsMap = new SparseArray<JobParameters>(); + private final SyncLogger mLogger = SyncLogger.getInstance(); + /** * This service is started by the SyncManager which passes a messenger object to * communicate back with it. It never stops while the device is running. @@ -63,6 +65,9 @@ public class SyncJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { + + mLogger.purgeOldLogs(); + boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); synchronized (jobParamsMap) { jobParamsMap.put(params.getJobId(), params); @@ -70,6 +75,9 @@ public class SyncJobService extends JobService { Message m = Message.obtain(); m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC; SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras()); + + mLogger.log("onStopJob() jobid=", params.getJobId(), " op=", op); + if (op == null) { Slog.e(TAG, "Got invalid job " + params.getJobId()); return false; @@ -88,7 +96,7 @@ public class SyncJobService extends JobService { Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: " + params.getStopReason()); } - + mLogger.log("onStopJob() ", mLogger.jobParametersToString(params)); synchronized (jobParamsMap) { jobParamsMap.remove(params.getJobId()); } @@ -108,9 +116,13 @@ public class SyncJobService extends JobService { return false; } - public void callJobFinished(int jobId, boolean needsReschedule) { + public void callJobFinished(int jobId, boolean needsReschedule, String why) { synchronized (jobParamsMap) { JobParameters params = jobParamsMap.get(jobId); + mLogger.log("callJobFinished()", + " needsReschedule=", needsReschedule, + " ", mLogger.jobParametersToString(params), + " why=", why); if (params != null) { jobFinished(params, needsReschedule); jobParamsMap.remove(jobId); diff --git a/services/core/java/com/android/server/content/SyncLogger.java b/services/core/java/com/android/server/content/SyncLogger.java new file mode 100644 index 000000000000..db794643b4df --- /dev/null +++ b/services/core/java/com/android/server/content/SyncLogger.java @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.content; + +import android.app.job.JobParameters; +import android.os.Build; +import android.os.Environment; +import android.os.FileUtils; +import android.os.SystemProperties; +import android.text.format.DateUtils; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; + +import libcore.io.IoUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * Implements a rotating file logger for the sync manager, which is enabled only on userdebug/eng + * builds (unless debug.synclog is set to 1). + * + * Note this class could be used for other purposes too, but in general we don't want various + * system components to log to files, so it's put in a local package here. + */ +public class SyncLogger { + private static final String TAG = "SyncLogger"; + + private static SyncLogger sInstance; + + SyncLogger() { + } + + /** + * @return the singleton instance. + */ + public static synchronized SyncLogger getInstance() { + if (sInstance == null) { + final boolean enable = "1".equals(SystemProperties.get("debug.synclog", + Build.IS_DEBUGGABLE ? "1" : "0")); + if (enable) { + sInstance = new RotatingFileLogger(); + } else { + sInstance = new SyncLogger(); + } + } + return sInstance; + } + + /** + * Write strings to the log file. + */ + public void log(Object... message) { + } + + /** + * Remove old log files. + */ + public void purgeOldLogs() { + // The default implementation is no-op. + } + + public String jobParametersToString(JobParameters params) { + // The default implementation is no-op. + return ""; + } + + /** + * Dump all existing log files into a given writer. + */ + public void dumpAll(PrintWriter pw) { + } + + /** + * Actual implementation which is only used on userdebug/eng builds (by default). + */ + private static class RotatingFileLogger extends SyncLogger { + private final Object mLock = new Object(); + + private final long mKeepAgeMs = TimeUnit.DAYS.toMillis(7); + + private static final SimpleDateFormat sTimestampFormat + = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + + private static final SimpleDateFormat sFilenameDateFormat + = new SimpleDateFormat("yyyy-MM-dd"); + + @GuardedBy("mLock") + private final Date mCachedDate = new Date(); + + @GuardedBy("mLock") + private final StringBuilder mStringBuilder = new StringBuilder(); + + private final File mLogPath; + + @GuardedBy("mLock") + private long mCurrentLogFileDayTimestamp; + + @GuardedBy("mLock") + private Writer mLogWriter; + + @GuardedBy("mLock") + private boolean mErrorShown; + + RotatingFileLogger() { + mLogPath = new File(Environment.getDataSystemDirectory(), "syncmanager-log"); + } + + private void handleException(String message, Exception e) { + if (!mErrorShown) { + Slog.e(TAG, message, e); + mErrorShown = true; + } + } + + @Override + public void log(Object... message) { + if (message == null) { + return; + } + synchronized (mLock) { + final long now = System.currentTimeMillis(); + openLogLocked(now); + if (mLogWriter == null) { + return; // Couldn't open log file? + } + + mStringBuilder.setLength(0); + mCachedDate.setTime(now); + mStringBuilder.append(sTimestampFormat.format(mCachedDate)); + mStringBuilder.append(' '); + + mStringBuilder.append(android.os.Process.myTid()); + mStringBuilder.append(' '); + + for (Object o : message) { + mStringBuilder.append(o); + } + mStringBuilder.append('\n'); + + try { + mLogWriter.append(mStringBuilder); + mLogWriter.flush(); + } catch (IOException e) { + handleException("Failed to write log", e); + } + } + } + + private void openLogLocked(long now) { + // If we already have a log file opened and the date has't changed, just use it. + final long day = now % DateUtils.DAY_IN_MILLIS; + if ((mLogWriter != null) && (day == mCurrentLogFileDayTimestamp)) { + return; + } + + // Otherwise create a new log file. + closeCurrentLogLocked(); + + mCurrentLogFileDayTimestamp = day; + + mCachedDate.setTime(now); + final String filename = "synclog-" + sFilenameDateFormat.format(mCachedDate) + ".log"; + final File file = new File(mLogPath, filename); + + file.getParentFile().mkdirs(); + + try { + mLogWriter = new FileWriter(file, /* append= */ true); + } catch (IOException e) { + handleException("Failed to open log file: " + file, e); + } + } + + private void closeCurrentLogLocked() { + IoUtils.closeQuietly(mLogWriter); + mLogWriter = null; + } + + @Override + public void purgeOldLogs() { + synchronized (mLock) { + FileUtils.deleteOlderFiles(mLogPath, /* keepCount= */ 1, mKeepAgeMs); + } + } + + @Override + public String jobParametersToString(JobParameters params) { + if (params == null) { + return "job:null"; + } else { + return "job:#" + params.getJobId() + ":" + + SyncOperation.maybeCreateFromJobExtras(params.getExtras()); + } + } + + @Override + public void dumpAll(PrintWriter pw) { + synchronized (mLock) { + final String[] files = mLogPath.list(); + if (files == null || (files.length == 0)) { + return; + } + Arrays.sort(files); + + for (String file : files) { + dumpFile(pw, new File(mLogPath, file)); + } + } + } + + private void dumpFile(PrintWriter pw, File file) { + Slog.w(TAG, "Dumping " + file); + final char[] buffer = new char[32 * 1024]; + + try (Reader in = new BufferedReader(new FileReader(file))) { + int read; + while ((read = in.read(buffer)) >= 0) { + if (read > 0) { + pw.write(buffer, 0, read); + } + } + } catch (IOException e) { + } + } + } +} diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index e3e26583b686..35591420af50 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -241,6 +241,8 @@ public class SyncManager { private final Random mRand; + private final SyncLogger mLogger; + private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) { for (JobInfo job: pendingJobs) { if (job.getId() == jobId) { @@ -289,13 +291,15 @@ public class SyncManager { mStorageIsLow = true; cancelActiveSync( SyncStorageEngine.EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL, - null /* any sync */); + null /* any sync */, + "storage low"); } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.v(TAG, "Internal storage is ok."); } mStorageIsLow = false; - rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL); + rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL, + "storage ok"); } } }; @@ -378,15 +382,16 @@ public class SyncManager { if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.v(TAG, "Reconnection detected: clearing all backoffs"); } + // Note the location of this code was wrong from nyc to oc; fixed in DR. + clearAllBackoffs("network reconnect"); } - clearAllBackoffs(); } } }; - private void clearAllBackoffs() { + private void clearAllBackoffs(String why) { mSyncStorageEngine.clearAllBackoffsLocked(); - rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL); + rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL, why); } private boolean readDataConnectionState() { @@ -502,6 +507,8 @@ public class SyncManager { // and creating threads and so on; it may fail if the disk is full. mContext = context; + mLogger = SyncLogger.getInstance(); + SyncStorageEngine.init(context); mSyncStorageEngine = SyncStorageEngine.getSingleton(); mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() { @@ -1145,8 +1152,12 @@ public class SyncManager { mSyncHandler.sendMessage(msg); } - private void sendCancelSyncsMessage(final SyncStorageEngine.EndPoint info, Bundle extras) { + private void sendCancelSyncsMessage(final SyncStorageEngine.EndPoint info, Bundle extras, + String why) { if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_CANCEL"); + + mLogger.log("sendCancelSyncsMessage() ep=", info, " why=", why); + Message msg = mSyncHandler.obtainMessage(); msg.what = SyncHandler.MESSAGE_CANCEL; msg.setData(extras); @@ -1227,7 +1238,7 @@ public class SyncManager { } } - private void clearBackoffSetting(EndPoint target) { + private void clearBackoffSetting(EndPoint target, String why) { Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target); if (backoff != null && backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE && backoff.second == SyncStorageEngine.NOT_IN_BACKOFF_MODE) { @@ -1240,7 +1251,7 @@ public class SyncManager { SyncStorageEngine.NOT_IN_BACKOFF_MODE, SyncStorageEngine.NOT_IN_BACKOFF_MODE); - rescheduleSyncs(target); + rescheduleSyncs(target, why); } private void increaseBackoffSetting(EndPoint target) { @@ -1281,14 +1292,16 @@ public class SyncManager { Slog.v(TAG, "Backoff until: " + backoff + ", delayTime: " + newDelayInMs); } mSyncStorageEngine.setBackoff(target, backoff, newDelayInMs); - rescheduleSyncs(target); + rescheduleSyncs(target, "increaseBackoffSetting"); } /** * Reschedule all scheduled syncs for this EndPoint. The syncs will be scheduled according * to current backoff and delayUntil values of this EndPoint. */ - private void rescheduleSyncs(EndPoint target) { + private void rescheduleSyncs(EndPoint target, String why) { + mLogger.log("rescheduleSyncs() ep=", target, " why=", why); + List<SyncOperation> ops = getAllPendingSyncs(); int count = 0; for (SyncOperation op: ops) { @@ -1316,7 +1329,7 @@ public class SyncManager { if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.v(TAG, "Delay Until time set to " + newDelayUntilTime + " for " + target); } - rescheduleSyncs(target); + rescheduleSyncs(target, "delayUntil newDelayUntilTime: " + newDelayUntilTime); } private boolean isAdapterDelayed(EndPoint target) { @@ -1338,8 +1351,8 @@ public class SyncManager { * have null account/provider info to specify all accounts/providers. * @param extras if non-null, specifies the exact sync to remove. */ - public void cancelActiveSync(SyncStorageEngine.EndPoint info, Bundle extras) { - sendCancelSyncsMessage(info, extras); + public void cancelActiveSync(SyncStorageEngine.EndPoint info, Bundle extras, String why) { + sendCancelSyncsMessage(info, extras, why); } /** @@ -1599,7 +1612,8 @@ public class SyncManager { null /* any account */, null /* any authority */, userId), - null /* any sync. */ + null /* any sync. */, + "onUserStopped" ); } @@ -1759,10 +1773,15 @@ public class SyncManager { } } - protected void dump(FileDescriptor fd, PrintWriter pw) { + protected void dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); dumpSyncState(ipw); dumpSyncAdapters(ipw); + + if (dumpAll) { + ipw.println("Detailed Sync History"); + mLogger.dumpAll(pw); + } } static String formatTime(long time) { @@ -2644,7 +2663,7 @@ public class SyncManager { Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_CANCEL: " + endpoint + " bundle: " + extras); } - cancelActiveSyncH(endpoint, extras); + cancelActiveSyncH(endpoint, extras, "MESSAGE_CANCEL"); break; case SyncHandler.MESSAGE_SYNC_FINISHED: @@ -2660,7 +2679,8 @@ public class SyncManager { Slog.v(TAG, "syncFinished" + payload.activeSyncContext.mSyncOperation); } mSyncJobService.callJobFinished( - payload.activeSyncContext.mSyncOperation.jobId, false); + payload.activeSyncContext.mSyncOperation.jobId, false, + "sync finished"); runSyncFinishedOrCanceledH(payload.syncResult, payload.activeSyncContext); break; @@ -2704,7 +2724,8 @@ public class SyncManager { SyncResult syncResult = new SyncResult(); syncResult.stats.numIoExceptions++; mSyncJobService.callJobFinished( - currentSyncContext.mSyncOperation.jobId, false); + currentSyncContext.mSyncOperation.jobId, false, + "service disconnected"); runSyncFinishedOrCanceledH(syncResult, currentSyncContext); } break; @@ -2722,7 +2743,8 @@ public class SyncManager { "Detected sync making no progress for %s. cancelling.", monitoredSyncContext)); mSyncJobService.callJobFinished( - monitoredSyncContext.mSyncOperation.jobId, false); + monitoredSyncContext.mSyncOperation.jobId, false, + "no network activity"); runSyncFinishedOrCanceledH( null /* cancel => no result */, monitoredSyncContext); } else { @@ -2754,8 +2776,10 @@ public class SyncManager { * delay. This is equivalent to a failure. If this is a periodic sync, a delayed one-off * sync will be scheduled. */ - private void deferSyncH(SyncOperation op, long delay) { - mSyncJobService.callJobFinished(op.jobId, false); + private void deferSyncH(SyncOperation op, long delay, String why) { + mLogger.log("deferSyncH() ", (op.isPeriodic ? "periodic " : ""), + "sync. op=", op, " delay=", delay, " why=", why); + mSyncJobService.callJobFinished(op.jobId, false, why); if (op.isPeriodic) { scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay); } else { @@ -2779,10 +2803,10 @@ public class SyncManager { /** * Cancel an active sync and reschedule it on the JobScheduler with some delay. */ - private void deferActiveSyncH(ActiveSyncContext asc) { + private void deferActiveSyncH(ActiveSyncContext asc, String why) { SyncOperation op = asc.mSyncOperation; runSyncFinishedOrCanceledH(null, asc); - deferSyncH(op, SYNC_DELAY_ON_CONFLICT); + deferSyncH(op, SYNC_DELAY_ON_CONFLICT, why); } private void startSyncH(SyncOperation op) { @@ -2790,7 +2814,7 @@ public class SyncManager { if (isLoggable) Slog.v(TAG, op.toString()); if (mStorageIsLow) { - deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE); + deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE, "storage low"); return; } @@ -2800,7 +2824,8 @@ public class SyncManager { List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation syncOperation: ops) { if (syncOperation.sourcePeriodicId == op.jobId) { - mSyncJobService.callJobFinished(op.jobId, false); + mSyncJobService.callJobFinished(op.jobId, false, + "periodic sync, pending"); return; } } @@ -2808,13 +2833,14 @@ public class SyncManager { // executing according to some backoff criteria. for (ActiveSyncContext asc: mActiveSyncContexts) { if (asc.mSyncOperation.sourcePeriodicId == op.jobId) { - mSyncJobService.callJobFinished(op.jobId, false); + mSyncJobService.callJobFinished(op.jobId, false, + "periodic sync, already running"); return; } } // Check for adapter delays. if (isAdapterDelayed(op.target)) { - deferSyncH(op, 0 /* No minimum delay */); + deferSyncH(op, 0 /* No minimum delay */, "backing off"); return; } } @@ -2828,13 +2854,13 @@ public class SyncManager { if (isLoggable) { Slog.v(TAG, "Rescheduling sync due to conflict " + op.toString()); } - deferSyncH(op, SYNC_DELAY_ON_CONFLICT); + deferSyncH(op, SYNC_DELAY_ON_CONFLICT, "delay on conflict"); return; } else { if (isLoggable) { Slog.v(TAG, "Pushing back running sync due to a higher priority sync"); } - deferActiveSyncH(asc); + deferActiveSyncH(asc, "preempted"); break; } } @@ -2844,12 +2870,13 @@ public class SyncManager { switch (syncOpState) { case SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS: case SYNC_OP_STATE_INVALID: { - mSyncJobService.callJobFinished(op.jobId, false); + mSyncJobService.callJobFinished(op.jobId, false, + "invalid op state: " + syncOpState); } return; } if (!dispatchSyncOperation(op)) { - mSyncJobService.callJobFinished(op.jobId, false); + mSyncJobService.callJobFinished(op.jobId, false, "dispatchSyncOperation() failed"); } setAuthorityPendingState(op.target); @@ -3019,7 +3046,8 @@ public class SyncManager { if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) { ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId); if (asc != null) { - mSyncJobService.callJobFinished(syncOperation.jobId, false); + mSyncJobService.callJobFinished(syncOperation.jobId, false, + "removePeriodicSyncInternalH"); runSyncFinishedOrCanceledH(null, asc); } getJobScheduler().cancel(op.jobId); @@ -3131,6 +3159,8 @@ public class SyncManager { final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo; syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, info.userId); if (syncAdapterInfo == null) { + mLogger.log("dispatchSyncOperation() failed: no sync adapter info for ", + syncAdapterType); Log.d(TAG, "can't find a sync adapter for " + syncAdapterType + ", removing settings for it"); mSyncStorageEngine.removeAuthority(info); @@ -3151,6 +3181,8 @@ public class SyncManager { postMonitorSyncProgressMessage(activeSyncContext); if (!activeSyncContext.bindToSyncAdapter(targetComponent, info.userId)) { + mLogger.log("dispatchSyncOperation() failed: bind failed. target: ", + targetComponent); Slog.e(TAG, "Bind attempt failed - target: " + targetComponent); closeActiveSyncContext(activeSyncContext); return false; @@ -3166,16 +3198,25 @@ public class SyncManager { activeSyncContext.mIsLinkedToDeath = true; syncAdapter.linkToDeath(activeSyncContext, 0); + mLogger.log("Sync start: account=" + syncOperation.target.account, + " authority=", syncOperation.target.provider, + " reason=", SyncOperation.reasonToString(null, syncOperation.reason), + " extras=", SyncOperation.extrasToString(syncOperation.extras)); + activeSyncContext.mSyncAdapter = ISyncAdapter.Stub.asInterface(syncAdapter); activeSyncContext.mSyncAdapter .startSync(activeSyncContext, syncOperation.target.provider, syncOperation.target.account, syncOperation.extras); + + mLogger.log("Sync finish"); } catch (RemoteException remoteExc) { + mLogger.log("Sync failed with RemoteException: ", remoteExc.toString()); Log.d(TAG, "maybeStartNextSync: caught a RemoteException, rescheduling", remoteExc); closeActiveSyncContext(activeSyncContext); increaseBackoffSetting(syncOperation.target); scheduleSyncOperationH(syncOperation); } catch (RuntimeException exc) { + mLogger.log("Sync failed with RuntimeException: ", exc.toString()); closeActiveSyncContext(activeSyncContext); Slog.e(TAG, "Caught RuntimeException while starting the sync " + syncOperation, exc); } @@ -3186,7 +3227,8 @@ public class SyncManager { * @param info Can have null fields to indicate all the active syncs for that field. * @param extras Can be null to indicate <strong>all</strong> syncs for the given endpoint. */ - private void cancelActiveSyncH(SyncStorageEngine.EndPoint info, Bundle extras) { + private void cancelActiveSyncH(SyncStorageEngine.EndPoint info, Bundle extras, + String why) { ArrayList<ActiveSyncContext> activeSyncs = new ArrayList<ActiveSyncContext>(mActiveSyncContexts); for (ActiveSyncContext activeSyncContext : activeSyncs) { @@ -3202,7 +3244,8 @@ public class SyncManager { false /* no config settings */)) { continue; } - mSyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false); + mSyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false, + why); runSyncFinishedOrCanceledH(null /* cancel => no result */, activeSyncContext); } } @@ -3250,6 +3293,7 @@ public class SyncManager { // potentially rescheduling all pending jobs to respect new backoff values. getJobScheduler().cancel(syncOperation.jobId); } + mLogger.log("runSyncFinishedOrCanceledH() op=", syncOperation, " result=", syncResult); if (syncResult != null) { if (isLoggable) { @@ -3262,7 +3306,7 @@ public class SyncManager { // TODO: set these correctly when the SyncResult is extended to include it downstreamActivity = 0; upstreamActivity = 0; - clearBackoffSetting(syncOperation.target); + clearBackoffSetting(syncOperation.target, "sync success"); // If the operation completes successfully and it was scheduled due to // a periodic operation failing, we reschedule the periodic operation to diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java index b46426cc4a05..7d2cc0035847 100644 --- a/services/core/java/com/android/server/content/SyncOperation.java +++ b/services/core/java/com/android/server/content/SyncOperation.java @@ -237,6 +237,9 @@ public class SyncOperation { * contain a valid sync operation. */ static SyncOperation maybeCreateFromJobExtras(PersistableBundle jobExtras) { + if (jobExtras == null) { + return null; + } String accountName, accountType; String provider; int userId, owningUid; @@ -445,6 +448,10 @@ public class SyncOperation { } static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) { + if (bundle == null) { + sb.append("null"); + return; + } sb.append("["); for (String key : bundle.keySet()) { sb.append(key).append("=").append(bundle.get(key)).append(" "); @@ -452,6 +459,12 @@ public class SyncOperation { sb.append("]"); } + static String extrasToString(Bundle bundle) { + final StringBuilder sb = new StringBuilder(); + extrasToStringBuilder(bundle, sb); + return sb.toString(); + } + String wakeLockName() { if (wakeLockName != null) { return wakeLockName; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index fe2c5bd87df4..c1e820c9b787 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -142,6 +142,7 @@ public class LockSettingsService extends ILockSettings.Stub { private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1; // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this + // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); private final DeviceProvisionedObserver mDeviceProvisionedObserver = @@ -1434,16 +1435,14 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); return VerifyCredentialResponse.ERROR; } - synchronized (mSpManager) { - if (isSyntheticPasswordBasedCredentialLocked(userId)) { - VerifyCredentialResponse response = spBasedDoVerifyCredentialLocked(credential, - credentialType, hasChallenge, challenge, userId, progressCallback); - if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { - mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); - } - return response; - } + VerifyCredentialResponse response = null; + response = spBasedDoVerifyCredential(credential, credentialType, hasChallenge, challenge, + userId, progressCallback); + // The user employs synthetic password based credential. + if (response != null) { + return response; } + final CredentialHash storedHash; if (userId == USER_FRP) { PersistentData data = mStorage.readPersistentDataBlock(); @@ -1472,7 +1471,7 @@ public class LockSettingsService extends ILockSettings.Stub { credentialToVerify = credential; } - VerifyCredentialResponse response = verifyCredential(userId, storedHash, credentialToVerify, + response = verifyCredential(userId, storedHash, credentialToVerify, hasChallenge, challenge, progressCallback); if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { @@ -1995,33 +1994,46 @@ public class LockSettingsService extends ILockSettings.Stub { setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM); } - private VerifyCredentialResponse spBasedDoVerifyCredentialLocked(String userCredential, int + private VerifyCredentialResponse spBasedDoVerifyCredential(String userCredential, int credentialType, boolean hasChallenge, long challenge, int userId, ICheckCredentialProgressCallback progressCallback) throws RemoteException { - if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredentialLocked: user=" + userId); + if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId); if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { userCredential = null; } - if (userId == USER_FRP) { - return mSpManager.verifyFrpCredential(getGateKeeperService(), - userCredential, credentialType, progressCallback); - } - long handle = getSyntheticPasswordHandleLocked(userId); - AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( - getGateKeeperService(), handle, userCredential, userId); + final AuthenticationResult authResult; + VerifyCredentialResponse response; + synchronized (mSpManager) { + if (!isSyntheticPasswordBasedCredentialLocked(userId)) { + return null; + } + if (userId == USER_FRP) { + return mSpManager.verifyFrpCredential(getGateKeeperService(), + userCredential, credentialType, progressCallback); + } - VerifyCredentialResponse response = authResult.gkResponse; - if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { + long handle = getSyntheticPasswordHandleLocked(userId); + authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( + getGateKeeperService(), handle, userCredential, userId); + + response = authResult.gkResponse; // credential has matched - // perform verifyChallenge with synthetic password which generates the real auth - // token for the current user - response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, - challenge, userId); - if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { - Slog.wtf(TAG, "verifyChallenge with SP failed."); - return VerifyCredentialResponse.ERROR; + if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { + // perform verifyChallenge with synthetic password which generates the real GK auth + // token and response for the current user + response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, + challenge, userId); + if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { + // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't + // match the recorded GK password handle. + Slog.wtf(TAG, "verifyChallenge with SP failed."); + return VerifyCredentialResponse.ERROR; + } } + } + + if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { if (progressCallback != null) { progressCallback.onCredentialVerified(); } @@ -2032,12 +2044,14 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length); unlockUser(userId, null, secret); + activateEscrowTokens(authResult.authToken, userId); + if (isManagedProfileWithSeparatedLock(userId)) { TrustManager trustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); trustManager.setDeviceLockedForUser(userId, false); } - activateEscrowTokens(authResult.authToken, userId); + mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { if (response.getTimeout() > 0) { requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId); @@ -2184,8 +2198,8 @@ public class LockSettingsService extends ILockSettings.Stub { private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException { if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId); - disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); synchronized (mSpManager) { + disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); for (long handle : mSpManager.getPendingTokensForUser(userId)) { Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId)); mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index d730c56ae2ca..67ead6f45d7a 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -36,6 +36,7 @@ class LockSettingsShellCommand extends ShellCommand { private static final String COMMAND_CLEAR = "clear"; private static final String COMMAND_SP = "sp"; private static final String COMMAND_SET_DISABLED = "set-disabled"; + private static final String COMMAND_VERIFY = "verify"; private int mCurrentUserId; private final LockPatternUtils mLockPatternUtils; @@ -76,6 +77,9 @@ class LockSettingsShellCommand extends ShellCommand { case COMMAND_SET_DISABLED: runSetDisabled(); break; + case COMMAND_VERIFY: + runVerify(); + break; default: getErrPrintWriter().println("Unknown command: " + cmd); break; @@ -88,6 +92,11 @@ class LockSettingsShellCommand extends ShellCommand { } } + private void runVerify() { + // The command is only run if the credential is correct. + getOutPrintWriter().println("Lock credential verified successfully"); + } + @Override public void onHelp() { } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index fbe6d302dd64..48b4c5724b5f 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1136,7 +1136,7 @@ public class NotificationManagerService extends SystemService { NotificationAssistants notificationAssistants, ConditionProviders conditionProviders, ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper, NotificationUsageStats usageStats, AtomicFile policyFile, - ActivityManager activityManager) { + ActivityManager activityManager, GroupHelper groupHelper) { Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, @@ -1193,35 +1193,7 @@ public class NotificationManagerService extends SystemService { } }); mSnoozeHelper = snoozeHelper; - mGroupHelper = new GroupHelper(new GroupHelper.Callback() { - @Override - public void addAutoGroup(String key) { - synchronized (mNotificationLock) { - addAutogroupKeyLocked(key); - } - mRankingHandler.requestSort(false); - } - - @Override - public void removeAutoGroup(String key) { - synchronized (mNotificationLock) { - removeAutogroupKeyLocked(key); - } - mRankingHandler.requestSort(false); - } - - @Override - public void addAutoGroupSummary(int userId, String pkg, String triggeringKey) { - createAutoGroupSummary(userId, pkg, triggeringKey); - } - - @Override - public void removeAutoGroupSummary(int userId, String pkg) { - synchronized (mNotificationLock) { - clearAutogroupSummaryLocked(userId, pkg); - } - } - }); + mGroupHelper = groupHelper; // This is a ManagedServices object that keeps track of the listeners. mListeners = notificationListeners; @@ -1337,11 +1309,44 @@ public class NotificationManagerService extends SystemService { new ConditionProviders(getContext(), mUserProfiles, AppGlobals.getPackageManager()), null, snoozeHelper, new NotificationUsageStats(getContext()), new AtomicFile(new File(systemDir, "notification_policy.xml")), - (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE)); + (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE), + getGroupHelper()); publishBinderService(Context.NOTIFICATION_SERVICE, mService); publishLocalService(NotificationManagerInternal.class, mInternalService); } + private GroupHelper getGroupHelper() { + return new GroupHelper(new GroupHelper.Callback() { + @Override + public void addAutoGroup(String key) { + synchronized (mNotificationLock) { + addAutogroupKeyLocked(key); + } + mRankingHandler.requestSort(false); + } + + @Override + public void removeAutoGroup(String key) { + synchronized (mNotificationLock) { + removeAutogroupKeyLocked(key); + } + mRankingHandler.requestSort(false); + } + + @Override + public void addAutoGroupSummary(int userId, String pkg, String triggeringKey) { + createAutoGroupSummary(userId, pkg, triggeringKey); + } + + @Override + public void removeAutoGroupSummary(int userId, String pkg) { + synchronized (mNotificationLock) { + clearAutogroupSummaryLocked(userId, pkg); + } + } + }); + } + private void sendRegisteredOnlyBroadcast(String action) { getContext().sendBroadcastAsUser(new Intent(action) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL, null); @@ -3323,7 +3328,6 @@ public class NotificationManagerService extends SystemService { (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE); mRankingHelper.sort(mNotificationList); mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */); - mGroupHelper.onNotificationPosted(sbn); } }; @@ -3740,12 +3744,14 @@ public class NotificationManagerService extends SystemService { if (notification.getSmallIcon() != null) { StatusBarNotification oldSbn = (old != null) ? old.sbn : null; mListeners.notifyPostedLocked(n, oldSbn); - mHandler.post(new Runnable() { - @Override - public void run() { - mGroupHelper.onNotificationPosted(n); - } - }); + if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) { + mHandler.post(new Runnable() { + @Override + public void run() { + mGroupHelper.onNotificationPosted(n); + } + }); + } } else { Slog.e(TAG, "Not posting notification without small icon: " + notification); if (old != null && !old.isCanceled) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0af3fffb2e3f..e59b9e383d13 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7209,12 +7209,15 @@ public class PackageManagerService extends IPackageManager.Stub // load resources from the correct package installerInfo.resolvePackageName = info.getComponentInfo().packageName; resolveInfos.set(i, installerInfo); + continue; } - continue; } // caller is a full app, don't need to apply any other filtering if (ephemeralPkgName == null) { continue; + } else if (ephemeralPkgName.equals(info.activityInfo.packageName)) { + // caller is same app; don't need to apply any other filtering + continue; } // allow activities that have been explicitly exposed to ephemeral apps if (!isEphemeralApp diff --git a/services/core/java/com/android/server/timezone/FileDescriptorHelper.java b/services/core/java/com/android/server/timezone/FileDescriptorHelper.java deleted file mode 100644 index c3b1101000b5..000000000000 --- a/services/core/java/com/android/server/timezone/FileDescriptorHelper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.timezone; - -import android.os.ParcelFileDescriptor; - -import java.io.IOException; - -/** - * An easy-to-mock interface around use of {@link ParcelFileDescriptor} for use by - * {@link RulesManagerService}. - */ -interface FileDescriptorHelper { - - byte[] readFully(ParcelFileDescriptor parcelFileDescriptor) throws IOException; -} diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index 58bdeb9d11ec..804a8b79310e 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -20,8 +20,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemService; import com.android.timezone.distro.DistroException; import com.android.timezone.distro.DistroVersion; -import com.android.timezone.distro.TimeZoneDistro; import com.android.timezone.distro.StagedDistroOperation; +import com.android.timezone.distro.TimeZoneDistro; import android.app.timezone.Callback; import android.app.timezone.DistroFormatVersion; @@ -36,7 +36,9 @@ import android.os.RemoteException; import android.util.Slog; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.Arrays; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; @@ -83,26 +85,22 @@ public final class RulesManagerService extends IRulesManager.Stub { private final PackageTracker mPackageTracker; private final Executor mExecutor; private final TimeZoneDistroInstaller mInstaller; - private final FileDescriptorHelper mFileDescriptorHelper; private static RulesManagerService create(Context context) { RulesManagerServiceHelperImpl helper = new RulesManagerServiceHelperImpl(context); return new RulesManagerService( helper /* permissionHelper */, helper /* executor */, - helper /* fileDescriptorHelper */, PackageTracker.create(context), new TimeZoneDistroInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR)); } // A constructor that can be used by tests to supply mocked / faked dependencies. RulesManagerService(PermissionHelper permissionHelper, - Executor executor, - FileDescriptorHelper fileDescriptorHelper, PackageTracker packageTracker, + Executor executor, PackageTracker packageTracker, TimeZoneDistroInstaller timeZoneDistroInstaller) { mPermissionHelper = permissionHelper; mExecutor = executor; - mFileDescriptorHelper = fileDescriptorHelper; mPackageTracker = packageTracker; mInstaller = timeZoneDistroInstaller; } @@ -177,55 +175,78 @@ public final class RulesManagerService extends IRulesManager.Stub { } @Override - public int requestInstall( - ParcelFileDescriptor timeZoneDistro, byte[] checkTokenBytes, ICallback callback) { - mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION); + public int requestInstall(ParcelFileDescriptor distroParcelFileDescriptor, + byte[] checkTokenBytes, ICallback callback) { - CheckToken checkToken = null; - if (checkTokenBytes != null) { - checkToken = createCheckTokenOrThrow(checkTokenBytes); - } - synchronized (this) { - if (timeZoneDistro == null) { - throw new NullPointerException("timeZoneDistro == null"); - } - if (callback == null) { - throw new NullPointerException("observer == null"); - } - if (mOperationInProgress.get()) { - return RulesManager.ERROR_OPERATION_IN_PROGRESS; + boolean closeParcelFileDescriptorOnExit = true; + try { + mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION); + + CheckToken checkToken = null; + if (checkTokenBytes != null) { + checkToken = createCheckTokenOrThrow(checkTokenBytes); } - mOperationInProgress.set(true); - // Execute the install asynchronously. - mExecutor.execute(new InstallRunnable(timeZoneDistro, checkToken, callback)); + synchronized (this) { + if (distroParcelFileDescriptor == null) { + throw new NullPointerException("distroParcelFileDescriptor == null"); + } + if (callback == null) { + throw new NullPointerException("observer == null"); + } + if (mOperationInProgress.get()) { + return RulesManager.ERROR_OPERATION_IN_PROGRESS; + } + mOperationInProgress.set(true); - return RulesManager.SUCCESS; + // Execute the install asynchronously. + mExecutor.execute( + new InstallRunnable(distroParcelFileDescriptor, checkToken, callback)); + + // The InstallRunnable now owns the ParcelFileDescriptor, so it will close it after + // it executes (and we do not have to). + closeParcelFileDescriptorOnExit = false; + + return RulesManager.SUCCESS; + } + } finally { + // We should close() the local ParcelFileDescriptor we were passed if it hasn't been + // passed to another thread to handle. + if (distroParcelFileDescriptor != null && closeParcelFileDescriptorOnExit) { + try { + distroParcelFileDescriptor.close(); + } catch (IOException e) { + Slog.w(TAG, "Failed to close distroParcelFileDescriptor", e); + } + } } } private class InstallRunnable implements Runnable { - private final ParcelFileDescriptor mTimeZoneDistro; + private final ParcelFileDescriptor mDistroParcelFileDescriptor; private final CheckToken mCheckToken; private final ICallback mCallback; - InstallRunnable( - ParcelFileDescriptor timeZoneDistro, CheckToken checkToken, ICallback callback) { - mTimeZoneDistro = timeZoneDistro; + InstallRunnable(ParcelFileDescriptor distroParcelFileDescriptor, CheckToken checkToken, + ICallback callback) { + mDistroParcelFileDescriptor = distroParcelFileDescriptor; mCheckToken = checkToken; mCallback = callback; } @Override public void run() { + boolean success = false; // Adopt the ParcelFileDescriptor into this try-with-resources so it is closed // when we are done. - boolean success = false; - try { - byte[] distroBytes = - RulesManagerService.this.mFileDescriptorHelper.readFully(mTimeZoneDistro); - TimeZoneDistro distro = new TimeZoneDistro(distroBytes); + try (ParcelFileDescriptor pfd = mDistroParcelFileDescriptor) { + // The ParcelFileDescriptor owns the underlying FileDescriptor and we'll close + // it at the end of the try-with-resources. + final boolean isFdOwner = false; + InputStream is = new FileInputStream(pfd.getFileDescriptor(), isFdOwner); + + TimeZoneDistro distro = new TimeZoneDistro(is); int installerResult = mInstaller.stageInstallWithErrorCode(distro); int resultCode = mapInstallerResultToApiCode(installerResult); sendFinishedStatus(mCallback, resultCode); diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java index 15a571d6750c..482d8e2c8014 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java +++ b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java @@ -27,8 +27,7 @@ import libcore.io.Streams; /** * A single class that implements multiple helper interfaces for use by {@link RulesManagerService}. */ -final class RulesManagerServiceHelperImpl - implements PermissionHelper, Executor, FileDescriptorHelper { +final class RulesManagerServiceHelperImpl implements PermissionHelper, Executor { private final Context mContext; @@ -47,13 +46,4 @@ final class RulesManagerServiceHelperImpl // TODO Is there a better way? new Thread(runnable).start(); } - - @Override - public byte[] readFully(ParcelFileDescriptor parcelFileDescriptor) throws IOException { - try (ParcelFileDescriptor pfd = parcelFileDescriptor) { - // Read bytes - FileInputStream in = new FileInputStream(pfd.getFileDescriptor(), false /* isOwner */); - return Streams.readFully(in); - } - } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java index 70c7e586d3fe..608635491849 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java @@ -25,8 +25,8 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; -import android.util.Log; import android.util.LongSparseArray; +import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -60,16 +60,21 @@ final class NetworkLoggingHandler extends Handler { /** Delay after which older batches get discarded after a retrieval. */ private static final long RETRIEVED_BATCH_DISCARD_DELAY_MS = 5 * 60 * 1000; // 5m + /** Do not call into mDpm with locks held */ private final DevicePolicyManagerService mDpm; private final AlarmManager mAlarmManager; private final OnAlarmListener mBatchTimeoutAlarmListener = new OnAlarmListener() { @Override public void onAlarm() { - Log.d(TAG, "Received a batch finalization timeout alarm, finalizing " + Slog.d(TAG, "Received a batch finalization timeout alarm, finalizing " + mNetworkEvents.size() + " pending events."); + Bundle notificationExtras = null; synchronized (NetworkLoggingHandler.this) { - finalizeBatchAndNotifyDeviceOwnerLocked(); + notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked(); + } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); } } }; @@ -110,17 +115,21 @@ final class NetworkLoggingHandler extends Handler { case LOG_NETWORK_EVENT_MSG: { final NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY); if (networkEvent != null) { + Bundle notificationExtras = null; synchronized (NetworkLoggingHandler.this) { mNetworkEvents.add(networkEvent); if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) { - finalizeBatchAndNotifyDeviceOwnerLocked(); + notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked(); } } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); + } } break; } default: { - Log.d(TAG, "NetworkLoggingHandler received an unknown of message."); + Slog.d(TAG, "NetworkLoggingHandler received an unknown of message."); break; } } @@ -133,40 +142,48 @@ final class NetworkLoggingHandler extends Handler { mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS, NETWORK_LOGGING_TIMEOUT_ALARM_TAG, mBatchTimeoutAlarmListener, this); - Log.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS + Slog.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS + "ms from now."); } synchronized void pause() { - Log.d(TAG, "Paused network logging"); + Slog.d(TAG, "Paused network logging"); mPaused = true; } - synchronized void resume() { - if (!mPaused) { - Log.d(TAG, "Attempted to resume network logging, but logging is not paused."); - return; - } + void resume() { + Bundle notificationExtras = null; + synchronized (this) { + if (!mPaused) { + Slog.d(TAG, "Attempted to resume network logging, but logging is not paused."); + return; + } - Log.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken - + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); - mPaused = false; + Slog.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken + + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); + mPaused = false; - // If there is a batch ready that the device owner hasn't been notified about, do it now. - if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { - scheduleBatchFinalization(); - notifyDeviceOwnerLocked(); + // If there is a batch ready that the device owner hasn't been notified about, do it now. + if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { + scheduleBatchFinalization(); + notificationExtras = buildDeviceOwnerMessageLocked(); + } + } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); } } synchronized void discardLogs() { mBatches.clear(); mNetworkEvents = new ArrayList<>(); - Log.d(TAG, "Discarded all network logs"); + Slog.d(TAG, "Discarded all network logs"); } @GuardedBy("this") - private void finalizeBatchAndNotifyDeviceOwnerLocked() { + /** @returns extras if a message should be sent to the device owner */ + private Bundle finalizeBatchAndBuildDeviceOwnerMessageLocked() { + Bundle notificationExtras = null; if (mNetworkEvents.size() > 0) { // Finalize the batch and start a new one from scratch. if (mBatches.size() >= MAX_BATCHES) { @@ -177,27 +194,39 @@ final class NetworkLoggingHandler extends Handler { mBatches.append(mCurrentBatchToken, mNetworkEvents); mNetworkEvents = new ArrayList<>(); if (!mPaused) { - notifyDeviceOwnerLocked(); + notificationExtras = buildDeviceOwnerMessageLocked(); } } else { // Don't notify the DO, since there are no events; DPC can still retrieve // the last full batch if not paused. - Log.d(TAG, "Was about to finalize the batch, but there were no events to send to" + Slog.d(TAG, "Was about to finalize the batch, but there were no events to send to" + " the DPC, the batchToken of last available batch: " + mCurrentBatchToken); } // Regardless of whether the batch was non-empty schedule a new finalization after timeout. scheduleBatchFinalization(); + return notificationExtras; } - /** Sends a notification to the DO. Should only be called when there is a batch available. */ @GuardedBy("this") - private void notifyDeviceOwnerLocked() { + /** Build extras notification to the DO. Should only be called when there + is a batch available. */ + private Bundle buildDeviceOwnerMessageLocked() { final Bundle extras = new Bundle(); final int lastBatchSize = mBatches.valueAt(mBatches.size() - 1).size(); extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentBatchToken); extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, lastBatchSize); - Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " - + mCurrentBatchToken); + return extras; + } + + /** Sends a notification to the DO. Should not hold locks as DevicePolicyManagerService may + call into NetworkLoggingHandler. */ + private void notifyDeviceOwner(Bundle extras) { + Slog.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " + + extras.getLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, -1)); + if (Thread.holdsLock(this)) { + Slog.wtfStack(TAG, "Shouldn't be called with NetworkLoggingHandler lock held"); + return; + } mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras); } diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java index d475d6459c72..8ff46394db14 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -118,6 +118,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { private ManagedServices.ManagedServiceInfo mListener; @Mock private ICompanionDeviceManager mCompanionMgr; @Mock SnoozeHelper mSnoozeHelper; + @Mock GroupHelper mGroupHelper; // Use a Testable subclass so we can simulate calls from the system without failing. private static class TestableNotificationManagerService extends NotificationManagerService { @@ -175,7 +176,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager, mPackageManagerClient, mockLightsManager, mNotificationListeners, mNotificationAssistants, mConditionProviders, mCompanionMgr, - mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager); + mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper); } catch (SecurityException e) { if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { throw e; @@ -1086,4 +1087,47 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mNotificationAssistants, never()).setPackageOrComponentEnabled( any(), anyInt(), anyBoolean(), anyBoolean()); } + + @Test + public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); + mNotificationManagerService.addEnqueuedNotification(r); + NotificationManagerService.PostNotificationRunnable runnable = + mNotificationManagerService.new PostNotificationRunnable(r.getKey()); + runnable.run(); + waitForIdle(); + + verify(mGroupHelper, times(1)).onNotificationPosted(any()); + } + + @Test + public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups() + throws Exception { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", false); + mNotificationManagerService.addNotification(r); + + r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); + mNotificationManagerService.addEnqueuedNotification(r); + NotificationManagerService.PostNotificationRunnable runnable = + mNotificationManagerService.new PostNotificationRunnable(r.getKey()); + runnable.run(); + waitForIdle(); + + verify(mGroupHelper, times(1)).onNotificationPosted(any()); + } + + @Test + public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups() + throws Exception { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", false); + mNotificationManagerService.addNotification(r); + mNotificationManagerService.addEnqueuedNotification(r); + + NotificationManagerService.PostNotificationRunnable runnable = + mNotificationManagerService.new PostNotificationRunnable(r.getKey()); + runnable.run(); + waitForIdle(); + + verify(mGroupHelper, never()).onNotificationPosted(any()); + } } diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java index c3a6f07548c8..3b76d5e05e0e 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java @@ -30,6 +30,8 @@ import android.app.timezone.RulesManager; import android.app.timezone.RulesState; import android.os.ParcelFileDescriptor; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.util.concurrent.Executor; import javax.annotation.Nullable; @@ -61,7 +63,6 @@ public class RulesManagerServiceTest { private FakeExecutor mFakeExecutor; private PermissionHelper mMockPermissionHelper; - private FileDescriptorHelper mMockFileDescriptorHelper; private PackageTracker mMockPackageTracker; private TimeZoneDistroInstaller mMockTimeZoneDistroInstaller; @@ -69,7 +70,6 @@ public class RulesManagerServiceTest { public void setUp() { mFakeExecutor = new FakeExecutor(); - mMockFileDescriptorHelper = mock(FileDescriptorHelper.class); mMockPackageTracker = mock(PackageTracker.class); mMockPermissionHelper = mock(PermissionHelper.class); mMockTimeZoneDistroInstaller = mock(TimeZoneDistroInstaller.class); @@ -77,7 +77,6 @@ public class RulesManagerServiceTest { mRulesManagerService = new RulesManagerService( mMockPermissionHelper, mFakeExecutor, - mMockFileDescriptorHelper, mMockPackageTracker, mMockTimeZoneDistroInstaller); } @@ -273,9 +272,8 @@ public class RulesManagerServiceTest { revision); configureInstalledDistroVersion(installedDistroVersion); - byte[] expectedContent = createArbitraryBytes(1000); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - configureParcelFileDescriptorReadSuccess(parcelFileDescriptor, expectedContent); + ParcelFileDescriptor parcelFileDescriptor = + createParcelFileDescriptor(createArbitraryBytes(1000)); // Start an async operation so there is one in progress. The mFakeExecutor won't actually // execute it. @@ -298,24 +296,27 @@ public class RulesManagerServiceTest { public void requestInstall_operationInProgress() throws Exception { configureCallerHasPermission(); - byte[] expectedContent = createArbitraryBytes(1000); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - configureParcelFileDescriptorReadSuccess(parcelFileDescriptor, expectedContent); + ParcelFileDescriptor parcelFileDescriptor1 = + createParcelFileDescriptor(createArbitraryBytes(1000)); byte[] tokenBytes = createArbitraryTokenBytes(); ICallback callback = new StubbedCallback(); // First request should succeed. assertEquals(RulesManager.SUCCESS, - mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback)); + mRulesManagerService.requestInstall(parcelFileDescriptor1, tokenBytes, callback)); // Something async should be enqueued. Clear it but do not execute it so we can detect the // second request does nothing. mFakeExecutor.getAndResetLastCommand(); // Second request should fail. + ParcelFileDescriptor parcelFileDescriptor2 = + createParcelFileDescriptor(createArbitraryBytes(1000)); assertEquals(RulesManager.ERROR_OPERATION_IN_PROGRESS, - mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback)); + mRulesManagerService.requestInstall(parcelFileDescriptor2, tokenBytes, callback)); + + assertClosed(parcelFileDescriptor2); // Assert nothing async was enqueued. mFakeExecutor.assertNothingQueued(); @@ -327,9 +328,8 @@ public class RulesManagerServiceTest { public void requestInstall_badToken() throws Exception { configureCallerHasPermission(); - byte[] expectedContent = createArbitraryBytes(1000); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - configureParcelFileDescriptorReadSuccess(parcelFileDescriptor, expectedContent); + ParcelFileDescriptor parcelFileDescriptor = + createParcelFileDescriptor(createArbitraryBytes(1000)); byte[] badTokenBytes = new byte[2]; ICallback callback = new StubbedCallback(); @@ -340,6 +340,8 @@ public class RulesManagerServiceTest { } catch (IllegalArgumentException expected) { } + assertClosed(parcelFileDescriptor); + // Assert nothing async was enqueued. mFakeExecutor.assertNothingQueued(); verifyNoInstallerCallsMade(); @@ -369,7 +371,8 @@ public class RulesManagerServiceTest { public void requestInstall_nullCallback() throws Exception { configureCallerHasPermission(); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); + ParcelFileDescriptor parcelFileDescriptor = + createParcelFileDescriptor(createArbitraryBytes(1000)); byte[] tokenBytes = createArbitraryTokenBytes(); ICallback callback = null; @@ -378,6 +381,8 @@ public class RulesManagerServiceTest { fail(); } catch (NullPointerException expected) {} + assertClosed(parcelFileDescriptor); + // Assert nothing async was enqueued. mFakeExecutor.assertNothingQueued(); verifyNoInstallerCallsMade(); @@ -388,9 +393,8 @@ public class RulesManagerServiceTest { public void requestInstall_asyncSuccess() throws Exception { configureCallerHasPermission(); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - byte[] expectedContent = createArbitraryBytes(1000); - configureParcelFileDescriptorReadSuccess(parcelFileDescriptor, expectedContent); + ParcelFileDescriptor parcelFileDescriptor = + createParcelFileDescriptor(createArbitraryBytes(1000)); CheckToken token = createArbitraryToken(); byte[] tokenBytes = token.toByteArray(); @@ -406,14 +410,14 @@ public class RulesManagerServiceTest { verifyNoInstallerCallsMade(); verifyNoPackageTrackerCallsMade(); - TimeZoneDistro expectedDistro = new TimeZoneDistro(expectedContent); - // Set up the installer. configureStageInstallExpectation(TimeZoneDistroInstaller.INSTALL_SUCCESS); // Simulate the async execution. mFakeExecutor.simulateAsyncExecutionOfLastCommand(); + assertClosed(parcelFileDescriptor); + // Verify the expected calls were made to other components. verifyStageInstallCalled(); verifyPackageTrackerCalled(token, true /* success */); @@ -426,9 +430,8 @@ public class RulesManagerServiceTest { public void requestInstall_nullTokenBytes() throws Exception { configureCallerHasPermission(); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - byte[] expectedContent = createArbitraryBytes(1000); - configureParcelFileDescriptorReadSuccess(parcelFileDescriptor, expectedContent); + ParcelFileDescriptor parcelFileDescriptor = + createParcelFileDescriptor(createArbitraryBytes(1000)); TestCallback callback = new TestCallback(); @@ -447,6 +450,8 @@ public class RulesManagerServiceTest { // Simulate the async execution. mFakeExecutor.simulateAsyncExecutionOfLastCommand(); + assertClosed(parcelFileDescriptor); + // Verify the expected calls were made to other components. verifyStageInstallCalled(); verifyPackageTrackerCalled(null /* expectedToken */, true /* success */); @@ -459,9 +464,8 @@ public class RulesManagerServiceTest { public void requestInstall_asyncInstallFail() throws Exception { configureCallerHasPermission(); - byte[] expectedContent = createArbitraryBytes(1000); - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - configureParcelFileDescriptorReadSuccess(parcelFileDescriptor, expectedContent); + ParcelFileDescriptor parcelFileDescriptor = + createParcelFileDescriptor(createArbitraryBytes(1000)); CheckToken token = createArbitraryToken(); byte[] tokenBytes = token.toByteArray(); @@ -482,6 +486,8 @@ public class RulesManagerServiceTest { // Simulate the async execution. mFakeExecutor.simulateAsyncExecutionOfLastCommand(); + assertClosed(parcelFileDescriptor); + // Verify the expected calls were made to other components. verifyStageInstallCalled(); @@ -494,38 +500,6 @@ public class RulesManagerServiceTest { } @Test - public void requestInstall_asyncParcelFileDescriptorReadFail() throws Exception { - configureCallerHasPermission(); - - ParcelFileDescriptor parcelFileDescriptor = createFakeParcelFileDescriptor(); - configureParcelFileDescriptorReadFailure(parcelFileDescriptor); - - CheckToken token = createArbitraryToken(); - byte[] tokenBytes = token.toByteArray(); - - TestCallback callback = new TestCallback(); - - // Request the install. - assertEquals(RulesManager.SUCCESS, - mRulesManagerService.requestInstall(parcelFileDescriptor, tokenBytes, callback)); - - // Simulate the async execution. - mFakeExecutor.simulateAsyncExecutionOfLastCommand(); - - // Verify nothing else happened. - verifyNoInstallerCallsMade(); - - // A failure to read the ParcelFileDescriptor is treated as a failure. It might be the - // result of a file system error. This is a fairly arbitrary choice. - verifyPackageTrackerCalled(token, false /* success */); - - verifyNoPackageTrackerCallsMade(); - - // Check the callback was received. - callback.assertResultReceived(Callback.ERROR_UNKNOWN_FAILURE); - } - - @Test public void requestUninstall_operationInProgress() throws Exception { configureCallerHasPermission(); @@ -773,17 +747,6 @@ public class RulesManagerServiceTest { .enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION); } - private void configureParcelFileDescriptorReadSuccess(ParcelFileDescriptor parcelFileDescriptor, - byte[] content) throws Exception { - when(mMockFileDescriptorHelper.readFully(parcelFileDescriptor)).thenReturn(content); - } - - private void configureParcelFileDescriptorReadFailure(ParcelFileDescriptor parcelFileDescriptor) - throws Exception { - when(mMockFileDescriptorHelper.readFully(parcelFileDescriptor)) - .thenThrow(new IOException("Simulated failure")); - } - private void configureStageInstallExpectation(int resultCode) throws Exception { when(mMockTimeZoneDistroInstaller.stageInstallWithErrorCode(any(TimeZoneDistro.class))) @@ -827,10 +790,6 @@ public class RulesManagerServiceTest { return new CheckToken(1, new PackageVersions(1, 1)); } - private ParcelFileDescriptor createFakeParcelFileDescriptor() { - return new ParcelFileDescriptor((ParcelFileDescriptor) null); - } - private void configureDeviceSystemRulesVersion(String systemRulesVersion) throws Exception { when(mMockTimeZoneDistroInstaller.getSystemRulesVersion()).thenReturn(systemRulesVersion); } @@ -870,6 +829,10 @@ public class RulesManagerServiceTest { .thenThrow(new IOException("Simulated failure")); } + private static void assertClosed(ParcelFileDescriptor parcelFileDescriptor) { + assertFalse(parcelFileDescriptor.getFileDescriptor().valid()); + } + private static class FakeExecutor implements Executor { private Runnable mLastCommand; @@ -926,4 +889,17 @@ public class RulesManagerServiceTest { fail("Unexpected call"); } } + + private static ParcelFileDescriptor createParcelFileDescriptor(byte[] bytes) + throws IOException { + File file = File.createTempFile("pfd", null); + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(bytes); + } + ParcelFileDescriptor pfd = + ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); + // This should now be safe to delete. The ParcelFileDescriptor has an open fd. + file.delete(); + return pfd; + } } diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java index f6d9e9a1a4e4..703f1a1ca656 100644 --- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java +++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java @@ -43,12 +43,10 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.server.FgThread; import java.io.File; -import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.PrintWriter; import java.security.MessageDigest; import java.util.Arrays; @@ -56,10 +54,10 @@ public class UsbDebuggingManager { private static final String TAG = "UsbDebuggingManager"; private static final boolean DEBUG = false; - private final String ADBD_SOCKET = "adbd"; - private final String ADB_DIRECTORY = "misc/adb"; - private final String ADB_KEYS_FILE = "adb_keys"; - private final int BUFFER_SIZE = 4096; + private static final String ADBD_SOCKET = "adbd"; + private static final String ADB_DIRECTORY = "misc/adb"; + private static final String ADB_KEYS_FILE = "adb_keys"; + private static final int BUFFER_SIZE = 4096; private final Context mContext; private final Handler mHandler; @@ -346,7 +344,7 @@ public class UsbDebuggingManager { } /** - * @returns true if the componentName led to an Activity that was started. + * @return true if the componentName led to an Activity that was started. */ private boolean startConfirmationActivity(ComponentName componentName, UserHandle userHandle, String key, String fingerprints) { @@ -365,7 +363,7 @@ public class UsbDebuggingManager { } /** - * @returns true if the componentName led to a Service that was started. + * @return true if the componentName led to a Service that was started. */ private boolean startConfirmationService(ComponentName componentName, UserHandle userHandle, String key, String fingerprints) { diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 42272fddb95b..1a24d9571e72 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -92,14 +92,6 @@ public class UsbDeviceManager { private static final String USB_CONFIG_PROPERTY = "sys.usb.config"; /** - * The property which stores the current build type (user/userdebug/eng). - */ - private static final String BUILD_TYPE_PROPERTY = "ro.build.type"; - - private static final String BUILD_TYPE_USERDEBUG = "userdebug"; - private static final String BUILD_TYPE_ENG = "eng"; - - /** * The non-persistent property which stores the current USB actual state. */ private static final String USB_STATE_PROPERTY = "sys.usb.state"; @@ -179,7 +171,7 @@ public class UsbDeviceManager { private static Set<Integer> sBlackListedInterfaces; static { - sBlackListedInterfaces = new HashSet<Integer>(); + sBlackListedInterfaces = new HashSet<>(); sBlackListedInterfaces.add(UsbConstants.USB_CLASS_AUDIO); sBlackListedInterfaces.add(UsbConstants.USB_CLASS_COMM); sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HID); @@ -191,7 +183,7 @@ public class UsbDeviceManager { sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC); sBlackListedInterfaces.add(UsbConstants.USB_CLASS_VIDEO); sBlackListedInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER); - }; + } private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { @@ -225,44 +217,6 @@ public class UsbDeviceManager { } }; - private final BroadcastReceiver mPortReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT); - UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS); - mHandler.updateHostState(port, status); - } - }; - - private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); - boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; - mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging); - } - }; - - private final BroadcastReceiver mHostReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE)) - .getDeviceList().entrySet().iterator(); - if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { - mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true); - } else { - mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false); - } - } - }; - - private final BroadcastReceiver mLanguageChangedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED); - } - }; - public UsbDeviceManager(Context context, UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) { mContext = context; @@ -287,17 +241,56 @@ public class UsbDeviceManager { if (secureAdbEnabled && !dataEncrypted) { mDebuggingManager = new UsbDebuggingManager(context); } - mContext.registerReceiver(mPortReceiver, + + BroadcastReceiver portReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT); + UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS); + mHandler.updateHostState(port, status); + } + }; + + BroadcastReceiver chargingReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; + mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging); + } + }; + + BroadcastReceiver hostReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE)) + .getDeviceList().entrySet().iterator(); + if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { + mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true); + } else { + mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false); + } + } + }; + + BroadcastReceiver languageChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED); + } + }; + + mContext.registerReceiver(portReceiver, new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED)); - mContext.registerReceiver(mChargingReceiver, + mContext.registerReceiver(chargingReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); - mContext.registerReceiver(mHostReceiver, filter); + mContext.registerReceiver(hostReceiver, filter); - mContext.registerReceiver(mLanguageChangedReceiver, + mContext.registerReceiver(languageChangedReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); } @@ -326,7 +319,7 @@ public class UsbDeviceManager { // We do not show the USB notification if the primary volume supports mass storage. // The legacy mass storage UI will be used instead. - boolean massStorageSupported = false; + boolean massStorageSupported; final StorageManager storageManager = StorageManager.from(mContext); final StorageVolume primary = storageManager.getPrimaryVolume(); massStorageSupported = primary != null && primary.allowMassStorage(); @@ -454,7 +447,7 @@ public class UsbDeviceManager { SystemProperties.get(USB_STATE_PROPERTY)); } - /** + /* * Use the normal bootmode persistent prop to maintain state of adb across * all boot modes. */ @@ -462,7 +455,7 @@ public class UsbDeviceManager { SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB); - /** + /* * Previous versions can set persist config to mtp/ptp but it does not * get reset on OTA. Reset the property here instead. */ @@ -652,10 +645,7 @@ public class UsbDeviceManager { private boolean isNormalBoot() { String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown"); - if (bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown")) { - return true; - } - return false; + return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"); } private boolean trySetEnabledFunctions(String functions, boolean forceRestart) { @@ -1311,25 +1301,21 @@ public class UsbDeviceManager { String[] items = config.split(":"); if (items.length == 3 || items.length == 4) { if (mOemModeMap == null) { - mOemModeMap = new HashMap<String, HashMap<String, - Pair<String, String>>>(); + mOemModeMap = new HashMap<>(); } HashMap<String, Pair<String, String>> overrideMap = mOemModeMap.get(items[0]); if (overrideMap == null) { - overrideMap = new HashMap<String, - Pair<String, String>>(); + overrideMap = new HashMap<>(); mOemModeMap.put(items[0], overrideMap); } // Favoring the first combination if duplicate exists if (!overrideMap.containsKey(items[1])) { if (items.length == 3) { - overrideMap.put(items[1], - new Pair<String, String>(items[2], "")); + overrideMap.put(items[1], new Pair<>(items[2], "")); } else { - overrideMap.put(items[1], - new Pair<String, String>(items[2], items[3])); + overrideMap.put(items[1], new Pair<>(items[2], items[3])); } } } @@ -1390,7 +1376,7 @@ public class UsbDeviceManager { String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown"); String persistProp = USB_PERSISTENT_CONFIG_PROPERTY; if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) { - if (functions == true) { + if (functions) { persistProp = "persist.sys.usb." + bootMode + ".func"; } else { persistProp = "persist.sys.usb." + bootMode + ".config"; diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index af78c05ae399..737b572d9f29 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -16,7 +16,6 @@ package com.android.server.usb; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; @@ -44,13 +43,11 @@ public class UsbHostManager { private static final boolean DEBUG = false; // contains all connected USB devices - private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>(); - + private final HashMap<String, UsbDevice> mDevices = new HashMap<>(); // USB busses to exclude from USB host support private final String[] mHostBlacklist; - private final Context mContext; private final Object mLock = new Object(); private UsbDevice mNewDevice; @@ -71,7 +68,6 @@ public class UsbHostManager { public UsbHostManager(Context context, UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) { - mContext = context; mHostBlacklist = context.getResources().getStringArray( com.android.internal.R.array.config_usbHostBlacklist); mUsbAlsaManager = alsaManager; @@ -119,17 +115,14 @@ public class UsbHostManager { } /* returns true if the USB device should not be accessible by applications */ - private boolean isBlackListed(int clazz, int subClass, int protocol) { + private boolean isBlackListed(int clazz, int subClass) { // blacklist hubs if (clazz == UsbConstants.USB_CLASS_HUB) return true; // blacklist HID boot devices (mouse and keyboard) - if (clazz == UsbConstants.USB_CLASS_HID && - subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT) { - return true; - } + return clazz == UsbConstants.USB_CLASS_HID + && subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT; - return false; } /* Called from JNI in monitorUsbHostBus() to report new USB devices @@ -137,6 +130,7 @@ public class UsbHostManager { interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors have been processed */ + @SuppressWarnings("unused") private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, String manufacturerName, String productName, int version, String serialNumber) { @@ -161,7 +155,7 @@ public class UsbHostManager { // such test until endUsbDeviceAdded() when we have that info. if (isBlackListed(deviceName) || - isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) { + isBlackListed(deviceClass, deviceSubclass)) { return false; } @@ -183,9 +177,9 @@ public class UsbHostManager { deviceClass, deviceSubclass, deviceProtocol, manufacturerName, productName, versionString, serialNumber); - mNewConfigurations = new ArrayList<UsbConfiguration>(); - mNewInterfaces = new ArrayList<UsbInterface>(); - mNewEndpoints = new ArrayList<UsbEndpoint>(); + mNewConfigurations = new ArrayList<>(); + mNewInterfaces = new ArrayList<>(); + mNewEndpoints = new ArrayList<>(); } return true; @@ -194,6 +188,7 @@ public class UsbHostManager { /* Called from JNI in monitorUsbHostBus() to report new USB configuration for the device currently being added. Returns true if successful, false in case of error. */ + @SuppressWarnings("unused") private void addUsbConfiguration(int id, String name, int attributes, int maxPower) { if (mNewConfiguration != null) { mNewConfiguration.setInterfaces( @@ -208,6 +203,7 @@ public class UsbHostManager { /* Called from JNI in monitorUsbHostBus() to report new USB interface for the device currently being added. Returns true if successful, false in case of error. */ + @SuppressWarnings("unused") private void addUsbInterface(int id, String name, int altSetting, int Class, int subClass, int protocol) { if (mNewInterface != null) { @@ -223,11 +219,13 @@ public class UsbHostManager { /* Called from JNI in monitorUsbHostBus() to report new USB endpoint for the device currently being added. Returns true if successful, false in case of error. */ + @SuppressWarnings("unused") private void addUsbEndpoint(int address, int attributes, int maxPacketSize, int interval) { mNewEndpoints.add(new UsbEndpoint(address, attributes, maxPacketSize, interval)); } /* Called from JNI in monitorUsbHostBus() to finish adding a new device */ + @SuppressWarnings("unused") private void endUsbDeviceAdded() { if (DEBUG) { Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()"); @@ -273,6 +271,7 @@ public class UsbHostManager { } /* Called from JNI in monitorUsbHostBus to report USB device removal */ + @SuppressWarnings("unused") private void usbDeviceRemoved(String deviceName) { synchronized (mLock) { UsbDevice device = mDevices.remove(deviceName); @@ -288,11 +287,7 @@ public class UsbHostManager { synchronized (mLock) { // Create a thread to call into native code to wait for USB host events. // This thread will call us back on usbDeviceAdded and usbDeviceRemoved. - Runnable runnable = new Runnable() { - public void run() { - monitorUsbHostBus(); - } - }; + Runnable runnable = this::monitorUsbHostBus; new Thread(null, runnable, "UsbService host thread").start(); } } diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index 7e2496c4f0f3..e28513a29a3a 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -87,9 +87,6 @@ public class UsbPortManager { // Mostly due a command sent by the remote Usb device. private HALCallback mHALCallback = new HALCallback(null, this); - // Notification object used to listen to the start of the usb daemon. - private final ServiceNotification mServiceNotification = new ServiceNotification(); - // Cookie sent for usb hal death notification. private static final int USB_HAL_DEATH_COOKIE = 1000; @@ -107,18 +104,20 @@ public class UsbPortManager { // Ports may temporarily have different dispositions as they are added or removed // but the class invariant is that this list will only contain ports with DISPOSITION_READY // except while updatePortsLocked() is in progress. - private final ArrayMap<String, PortInfo> mPorts = new ArrayMap<String, PortInfo>(); + private final ArrayMap<String, PortInfo> mPorts = new ArrayMap<>(); // List of all simulated ports, indexed by id. private final ArrayMap<String, RawPortInfo> mSimulatedPorts = - new ArrayMap<String, RawPortInfo>(); + new ArrayMap<>(); public UsbPortManager(Context context) { mContext = context; try { + ServiceNotification serviceNotification = new ServiceNotification(); + boolean ret = IServiceManager.getService() .registerForNotifications("android.hardware.usb@1.0::IUsb", - "", mServiceNotification); + "", serviceNotification); if (!ret) { logAndPrint(Log.ERROR, null, "Failed to register service start notification"); @@ -258,7 +257,6 @@ public class UsbPortManager { logAndPrintException(pw, "Failed to set the USB port mode: " + "portId=" + portId + ", newMode=" + UsbPort.modeToString(newRole.role), e); - return; } } else { // Change power and data role independently as needed. @@ -289,7 +287,6 @@ public class UsbPortManager { + ", newDataRole=" + UsbPort.dataRoleToString(newRole .role), e); - return; } } } @@ -415,10 +412,6 @@ public class UsbPortManager { public IndentingPrintWriter pw; public UsbPortManager portManager; - HALCallback() { - super(); - } - HALCallback(IndentingPrintWriter pw, UsbPortManager portManager) { this.pw = pw; this.portManager = portManager; @@ -434,7 +427,7 @@ public class UsbPortManager { return; } - ArrayList<RawPortInfo> newPortInfo = new ArrayList<RawPortInfo>(); + ArrayList<RawPortInfo> newPortInfo = new ArrayList<>(); for (PortStatus current : currentPortStatus) { RawPortInfo temp = new RawPortInfo(current.portName, @@ -452,7 +445,6 @@ public class UsbPortManager { message.what = MSG_UPDATE_PORTS; message.setData(bundle); portManager.mHandler.sendMessage(message); - return; } @@ -467,7 +459,7 @@ public class UsbPortManager { return; } - ArrayList<RawPortInfo> newPortInfo = new ArrayList<RawPortInfo>(); + ArrayList<RawPortInfo> newPortInfo = new ArrayList<>(); for (PortStatus_1_1 current : currentPortStatus) { RawPortInfo temp = new RawPortInfo(current.status.portName, @@ -485,7 +477,6 @@ public class UsbPortManager { message.what = MSG_UPDATE_PORTS; message.setData(bundle); portManager.mHandler.sendMessage(message); - return; } public void notifyRoleSwitchStatus(String portName, PortRole role, int retval) { @@ -495,7 +486,7 @@ public class UsbPortManager { logAndPrint(Log.ERROR, pw, portName + " role switch failed"); } } - }; + } final class DeathRecipient implements HwBinder.DeathRecipient { public IndentingPrintWriter pw; @@ -701,12 +692,7 @@ public class UsbPortManager { // Guard against possible reentrance by posting the broadcast from the handler // instead of from within the critical section. - mHandler.post(new Runnable() { - @Override - public void run() { - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - }); + mHandler.post(() -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL)); } private static void logAndPrint(int priority, IndentingPrintWriter pw, String msg) { diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java index 840ae221df30..ebb5a62ce7ec 100644 --- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java @@ -225,7 +225,7 @@ class UsbProfileGroupSettingsManager { } else if ("serial-number".equals(name)) { serialNumber = value; } else { - int intValue = -1; + int intValue; int radix = 10; if (value != null && value.length() > 2 && value.charAt(0) == '0' && (value.charAt(1) == 'x' || value.charAt(1) == 'X')) { @@ -388,9 +388,9 @@ class UsbProfileGroupSettingsManager { (filter.mSerialNumber != null && mSerialNumber != null && !mSerialNumber.equals(filter.mSerialNumber))) { - return(false); + return false; } - return(true); + return true; } if (obj instanceof UsbDevice) { UsbDevice device = (UsbDevice)obj; @@ -415,7 +415,7 @@ class UsbProfileGroupSettingsManager { !mProductName.equals(device.getProductName())) || (device.getSerialNumber() != null && !mSerialNumber.equals(device.getSerialNumber()))) { - return(false); + return false; } return true; } @@ -501,8 +501,7 @@ class UsbProfileGroupSettingsManager { public boolean matches(UsbAccessory acc) { if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false; if (mModel != null && !acc.getModel().equals(mModel)) return false; - if (mVersion != null && !acc.getVersion().equals(mVersion)) return false; - return true; + return !(mVersion != null && !acc.getVersion().equals(mVersion)); } /** @@ -517,8 +516,7 @@ class UsbProfileGroupSettingsManager { return false; } if (mModel != null && !Objects.equals(accessory.mModel, mModel)) return false; - if (mVersion != null && !Objects.equals(accessory.mVersion, mVersion)) return false; - return true; + return !(mVersion != null && !Objects.equals(accessory.mVersion, mVersion)); } @Override @@ -624,13 +622,8 @@ class UsbProfileGroupSettingsManager { mPackageMonitor.register(context, null, UserHandle.ALL, true); mMtpNotificationManager = new MtpNotificationManager( parentUserContext, - new MtpNotificationManager.OnOpenInAppListener() { - @Override - public void onOpenInApp(UsbDevice device) { - resolveActivity(createDeviceAttachedIntent(device), - device, false /* showMtpNotification */); - } - }); + device -> resolveActivity(createDeviceAttachedIntent(device), + device, false /* showMtpNotification */)); } /** @@ -727,9 +720,7 @@ class UsbProfileGroupSettingsManager { XmlUtils.nextElement(parser); } } - } catch (IOException e) { - Log.wtf(TAG, "Failed to read single-user settings", e); - } catch (XmlPullParserException e) { + } catch (IOException | XmlPullParserException e) { Log.wtf(TAG, "Failed to read single-user settings", e); } finally { IoUtils.closeQuietly(fis); @@ -1015,8 +1006,8 @@ class UsbProfileGroupSettingsManager { } } - private final ArrayList<ResolveInfo> getDeviceMatchesLocked(UsbDevice device, Intent intent) { - ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>(); + private ArrayList<ResolveInfo> getDeviceMatchesLocked(UsbDevice device, Intent intent) { + ArrayList<ResolveInfo> matches = new ArrayList<>(); List<ResolveInfo> resolveInfos = queryIntentActivitiesForAllProfiles(intent); int count = resolveInfos.size(); for (int i = 0; i < count; i++) { @@ -1029,9 +1020,9 @@ class UsbProfileGroupSettingsManager { return removeForwardIntentIfNotNeeded(preferHighPriority(matches)); } - private final ArrayList<ResolveInfo> getAccessoryMatchesLocked( + private ArrayList<ResolveInfo> getAccessoryMatchesLocked( UsbAccessory accessory, Intent intent) { - ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>(); + ArrayList<ResolveInfo> matches = new ArrayList<>(); List<ResolveInfo> resolveInfos = queryIntentActivitiesForAllProfiles(intent); int count = resolveInfos.size(); for (int i = 0; i < count; i++) { @@ -1402,7 +1393,7 @@ class UsbProfileGroupSettingsManager { void setDevicePackage(@NonNull UsbDevice device, @Nullable String packageName, @NonNull UserHandle user) { DeviceFilter filter = new DeviceFilter(device); - boolean changed = false; + boolean changed; synchronized (mLock) { if (packageName == null) { changed = (mDevicePreferenceMap.remove(filter) != null); @@ -1430,7 +1421,7 @@ class UsbProfileGroupSettingsManager { void setAccessoryPackage(@NonNull UsbAccessory accessory, @Nullable String packageName, @NonNull UserHandle user) { AccessoryFilter filter = new AccessoryFilter(accessory); - boolean changed = false; + boolean changed; synchronized (mLock) { if (packageName == null) { changed = (mAccessoryPreferenceMap.remove(filter) != null); @@ -1460,8 +1451,7 @@ class UsbProfileGroupSettingsManager { UserPackage userPackage = new UserPackage(packageName, user); synchronized (mLock) { if (mDevicePreferenceMap.values().contains(userPackage)) return true; - if (mAccessoryPreferenceMap.values().contains(userPackage)) return true; - return false; + return mAccessoryPreferenceMap.values().contains(userPackage); } } @@ -1493,9 +1483,9 @@ class UsbProfileGroupSettingsManager { synchronized (mLock) { if (mDevicePreferenceMap.containsValue(userPackage)) { // make a copy of the key set to avoid ConcurrentModificationException - Object[] keys = mDevicePreferenceMap.keySet().toArray(); + DeviceFilter[] keys = mDevicePreferenceMap.keySet().toArray(new DeviceFilter[0]); for (int i = 0; i < keys.length; i++) { - Object key = keys[i]; + DeviceFilter key = keys[i]; if (userPackage.equals(mDevicePreferenceMap.get(key))) { mDevicePreferenceMap.remove(key); cleared = true; @@ -1504,9 +1494,10 @@ class UsbProfileGroupSettingsManager { } if (mAccessoryPreferenceMap.containsValue(userPackage)) { // make a copy of the key set to avoid ConcurrentModificationException - Object[] keys = mAccessoryPreferenceMap.keySet().toArray(); + AccessoryFilter[] keys = + mAccessoryPreferenceMap.keySet().toArray(new AccessoryFilter[0]); for (int i = 0; i < keys.length; i++) { - Object key = keys[i]; + AccessoryFilter key = keys[i]; if (userPackage.equals(mAccessoryPreferenceMap.get(key))) { mAccessoryPreferenceMap.remove(key); cleared = true; diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 61e1e8f28c59..e4fcea77fa44 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -134,25 +134,25 @@ public class UsbService extends IUsbManager.Stub { onSwitchUser(UserHandle.USER_SYSTEM); + BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED + .equals(action)) { + if (mDeviceManager != null) { + mDeviceManager.updateUserRestrictions(); + } + } + } + }; + final IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); - mContext.registerReceiver(mReceiver, filter, null, null); + mContext.registerReceiver(receiver, filter, null, null); } - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED - .equals(action)) { - if (mDeviceManager != null) { - mDeviceManager.updateUserRestrictions(); - } - } - } - }; - /** * Set new {@link #mCurrentUserId} and propagate it to other modules. * @@ -681,7 +681,7 @@ public class UsbService extends IUsbManager.Stub { } } - private static final String removeLastChar(String value) { + private static String removeLastChar(String value) { return value.substring(0, value.length() - 1); } } diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java index 7a55be43ffd5..c7e5998db70d 100644 --- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java @@ -28,6 +28,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.util.SparseArray; + import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java index 4a34ece9524e..96c5211cecf4 100644 --- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java @@ -32,6 +32,7 @@ import android.os.Process; import android.os.UserHandle; import android.util.Slog; import android.util.SparseBooleanArray; + import com.android.internal.util.IndentingPrintWriter; import java.util.HashMap; @@ -48,10 +49,10 @@ class UsbUserSettingsManager { // Temporary mapping USB device name to list of UIDs with permissions for the device private final HashMap<String, SparseBooleanArray> mDevicePermissionMap = - new HashMap<String, SparseBooleanArray>(); + new HashMap<>(); // Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap = - new HashMap<UsbAccessory, SparseBooleanArray>(); + new HashMap<>(); private final Object mLock = new Object(); diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 11770fb06c95..f22a6327c80f 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -320,7 +320,8 @@ public class EuiccManager { return; } try { - mController.getDownloadableSubscriptionMetadata(subscription, callbackIntent); + mController.getDownloadableSubscriptionMetadata( + subscription, mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -349,7 +350,8 @@ public class EuiccManager { return; } try { - mController.getDefaultDownloadableSubscriptionList(callbackIntent); + mController.getDefaultDownloadableSubscriptionList( + mContext.getOpPackageName(), callbackIntent); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl index 725b89bcf351..fa43631cee9e 100644 --- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl +++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl @@ -26,8 +26,9 @@ import android.telephony.euicc.EuiccInfo; interface IEuiccController { oneway void continueOperation(in Intent resolutionIntent, in Bundle resolutionExtras); oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription, - in PendingIntent callbackIntent); - oneway void getDefaultDownloadableSubscriptionList(in PendingIntent callbackIntent); + String callingPackage, in PendingIntent callbackIntent); + oneway void getDefaultDownloadableSubscriptionList( + String callingPackage, in PendingIntent callbackIntent); String getEid(); oneway void downloadSubscription(in DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, in PendingIntent callbackIntent); diff --git a/test-runner/src/android/test/ClassPathPackageInfo.java b/test-runner/src/android/test/ClassPathPackageInfo.java deleted file mode 100644 index 2cf76afa1d94..000000000000 --- a/test-runner/src/android/test/ClassPathPackageInfo.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.test; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * The Package object doesn't allow you to iterate over the contained - * classes and subpackages of that package. This is a version that does. - * - * {@hide} Not needed for 1.0 SDK. - */ -@Deprecated -public class ClassPathPackageInfo { - - private final ClassPathPackageInfoSource source; - private final String packageName; - private final Set<String> subpackageNames; - private final Set<Class<?>> topLevelClasses; - - ClassPathPackageInfo(ClassPathPackageInfoSource source, String packageName, - Set<String> subpackageNames, Set<Class<?>> topLevelClasses) { - this.source = source; - this.packageName = packageName; - this.subpackageNames = Collections.unmodifiableSet(subpackageNames); - this.topLevelClasses = Collections.unmodifiableSet(topLevelClasses); - } - - public Set<ClassPathPackageInfo> getSubpackages() { - Set<ClassPathPackageInfo> info = new HashSet<>(); - for (String name : subpackageNames) { - info.add(source.getPackageInfo(name)); - } - return info; - } - - public Set<Class<?>> getTopLevelClassesRecursive() { - Set<Class<?>> set = new HashSet<>(); - addTopLevelClassesTo(set); - return set; - } - - private void addTopLevelClassesTo(Set<Class<?>> set) { - set.addAll(topLevelClasses); - for (ClassPathPackageInfo info : getSubpackages()) { - info.addTopLevelClassesTo(set); - } - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ClassPathPackageInfo) { - ClassPathPackageInfo that = (ClassPathPackageInfo) obj; - return (this.packageName).equals(that.packageName); - } - return false; - } - - @Override - public int hashCode() { - return packageName.hashCode(); - } -} diff --git a/test-runner/src/android/test/ClassPathPackageInfoSource.java b/test-runner/src/android/test/ClassPathPackageInfoSource.java index 9bcc25adf8d3..755b540cbbb8 100644 --- a/test-runner/src/android/test/ClassPathPackageInfoSource.java +++ b/test-runner/src/android/test/ClassPathPackageInfoSource.java @@ -21,15 +21,12 @@ import dalvik.system.DexFile; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * Generate {@link ClassPathPackageInfo}s by scanning apk paths. @@ -39,11 +36,13 @@ import java.util.zip.ZipFile; @Deprecated public class ClassPathPackageInfoSource { - private static final String CLASS_EXTENSION = ".class"; - private static final ClassLoader CLASS_LOADER = ClassPathPackageInfoSource.class.getClassLoader(); + private static String[] apkPaths; + + private static ClassPathPackageInfoSource classPathSource; + private final SimpleCache<String, ClassPathPackageInfo> cache = new SimpleCache<String, ClassPathPackageInfo>() { @Override @@ -54,23 +53,28 @@ public class ClassPathPackageInfoSource { // The class path of the running application private final String[] classPath; - private static String[] apkPaths; - // A cache of jar file contents - private final Map<File, Set<String>> jarFiles = new HashMap<>(); - private ClassLoader classLoader; + private final ClassLoader classLoader; - ClassPathPackageInfoSource() { + private ClassPathPackageInfoSource(ClassLoader classLoader) { + this.classLoader = classLoader; classPath = getClassPath(); } - - public static void setApkPaths(String[] apkPaths) { + static void setApkPaths(String[] apkPaths) { ClassPathPackageInfoSource.apkPaths = apkPaths; } - public ClassPathPackageInfo getPackageInfo(String pkgName) { - return cache.get(pkgName); + public static ClassPathPackageInfoSource forClassPath(ClassLoader classLoader) { + if (classPathSource == null) { + classPathSource = new ClassPathPackageInfoSource(classLoader); + } + return classPathSource; + } + + public Set<Class<?>> getTopLevelClassesRecursive(String packageName) { + ClassPathPackageInfo packageInfo = cache.get(packageName); + return packageInfo.getTopLevelClassesRecursive(); } private ClassPathPackageInfo createPackageInfo(String packageName) { @@ -96,7 +100,7 @@ public class ClassPathPackageInfoSource { + "'. Message: " + e.getMessage(), e); } } - return new ClassPathPackageInfo(this, packageName, subpackageNames, + return new ClassPathPackageInfo(packageName, subpackageNames, topLevelClasses); } @@ -107,9 +111,6 @@ public class ClassPathPackageInfoSource { */ private void findClasses(String packageName, Set<String> classNames, Set<String> subpackageNames) { - String packagePrefix = packageName + '.'; - String pathPrefix = packagePrefix.replace('.', '/'); - for (String entryName : classPath) { File classPathEntry = new File(entryName); @@ -150,58 +151,6 @@ public class ClassPathPackageInfoSource { /** * Finds all classes and sub packages that are below the packageName and - * add them to the respective sets. Searches the package in a class directory. - */ - private void findClassesInDirectory(File classDir, - String packagePrefix, String pathPrefix, Set<String> classNames, - Set<String> subpackageNames) - throws IOException { - File directory = new File(classDir, pathPrefix); - - if (directory.exists()) { - for (File f : directory.listFiles()) { - String name = f.getName(); - if (name.endsWith(CLASS_EXTENSION) && isToplevelClass(name)) { - classNames.add(packagePrefix + getClassName(name)); - } else if (f.isDirectory()) { - subpackageNames.add(packagePrefix + name); - } - } - } - } - - /** - * Finds all classes and sub packages that are below the packageName and - * add them to the respective sets. Searches the package in a single jar file. - */ - private void findClassesInJar(File jarFile, String pathPrefix, - Set<String> classNames, Set<String> subpackageNames) - throws IOException { - Set<String> entryNames = getJarEntries(jarFile); - // check if the Jar contains the package. - if (!entryNames.contains(pathPrefix)) { - return; - } - int prefixLength = pathPrefix.length(); - for (String entryName : entryNames) { - if (entryName.startsWith(pathPrefix)) { - if (entryName.endsWith(CLASS_EXTENSION)) { - // check if the class is in the package itself or in one of its - // subpackages. - int index = entryName.indexOf('/', prefixLength); - if (index >= 0) { - String p = entryName.substring(0, index).replace('/', '.'); - subpackageNames.add(p); - } else if (isToplevelClass(entryName)) { - classNames.add(getClassName(entryName).replace('/', '.')); - } - } - } - } - } - - /** - * Finds all classes and sub packages that are below the packageName and * add them to the respective sets. Searches the package in a single apk file. */ private void findClassesInApk(String apkPath, String packageName, @@ -242,47 +191,6 @@ public class ClassPathPackageInfoSource { } /** - * Gets the class and package entries from a Jar. - */ - private Set<String> getJarEntries(File jarFile) - throws IOException { - Set<String> entryNames = jarFiles.get(jarFile); - if (entryNames == null) { - entryNames = new HashSet<>(); - ZipFile zipFile = new ZipFile(jarFile); - Enumeration<? extends ZipEntry> entries = zipFile.entries(); - while (entries.hasMoreElements()) { - String entryName = entries.nextElement().getName(); - if (entryName.endsWith(CLASS_EXTENSION)) { - // add the entry name of the class - entryNames.add(entryName); - - // add the entry name of the classes package, i.e. the entry name of - // the directory that the class is in. Used to quickly skip jar files - // if they do not contain a certain package. - // - // Also add parent packages so that a JAR that contains - // pkg1/pkg2/Foo.class will be marked as containing pkg1/ in addition - // to pkg1/pkg2/ and pkg1/pkg2/Foo.class. We're still interested in - // JAR files that contains subpackages of a given package, even if - // an intermediate package contains no direct classes. - // - // Classes in the default package will cause a single package named - // "" to be added instead. - int lastIndex = entryName.lastIndexOf('/'); - do { - String packageName = entryName.substring(0, lastIndex + 1); - entryNames.add(packageName); - lastIndex = entryName.lastIndexOf('/', lastIndex - 1); - } while (lastIndex > 0); - } - } - jarFiles.put(jarFile, entryNames); - } - return entryNames; - } - - /** * Checks if a given file name represents a toplevel class. */ private static boolean isToplevelClass(String fileName) { @@ -290,14 +198,6 @@ public class ClassPathPackageInfoSource { } /** - * Given the absolute path of a class file, return the class name. - */ - private static String getClassName(String className) { - int classNameEnd = className.length() - CLASS_EXTENSION.length(); - return className.substring(0, classNameEnd); - } - - /** * Gets the class path from the System Property "java.class.path" and splits * it up into the individual elements. */ @@ -307,7 +207,56 @@ public class ClassPathPackageInfoSource { return classPath.split(Pattern.quote(separator)); } - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; + /** + * The Package object doesn't allow you to iterate over the contained + * classes and subpackages of that package. This is a version that does. + */ + private class ClassPathPackageInfo { + + private final String packageName; + private final Set<String> subpackageNames; + private final Set<Class<?>> topLevelClasses; + + private ClassPathPackageInfo(String packageName, + Set<String> subpackageNames, Set<Class<?>> topLevelClasses) { + this.packageName = packageName; + this.subpackageNames = Collections.unmodifiableSet(subpackageNames); + this.topLevelClasses = Collections.unmodifiableSet(topLevelClasses); + } + + private Set<ClassPathPackageInfo> getSubpackages() { + Set<ClassPathPackageInfo> info = new HashSet<>(); + for (String name : subpackageNames) { + info.add(cache.get(name)); + } + return info; + } + + private Set<Class<?>> getTopLevelClassesRecursive() { + Set<Class<?>> set = new HashSet<>(); + addTopLevelClassesTo(set); + return set; + } + + private void addTopLevelClassesTo(Set<Class<?>> set) { + set.addAll(topLevelClasses); + for (ClassPathPackageInfo info : getSubpackages()) { + info.addTopLevelClassesTo(set); + } + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ClassPathPackageInfo) { + ClassPathPackageInfo that = (ClassPathPackageInfo) obj; + return (this.packageName).equals(that.packageName); + } + return false; + } + + @Override + public int hashCode() { + return packageName.hashCode(); + } } } diff --git a/test-runner/src/android/test/PackageInfoSources.java b/test-runner/src/android/test/PackageInfoSources.java deleted file mode 100644 index 205f86b04d5f..000000000000 --- a/test-runner/src/android/test/PackageInfoSources.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.test; - -/** - * {@hide} Not needed for SDK. - */ -@Deprecated -public class PackageInfoSources { - - private static ClassPathPackageInfoSource classPathSource; - - private PackageInfoSources() { - } - - public static ClassPathPackageInfoSource forClassPath(ClassLoader classLoader) { - if (classPathSource == null) { - classPathSource = new ClassPathPackageInfoSource(); - classPathSource.setClassLoader(classLoader); - } - return classPathSource; - } - -} diff --git a/test-runner/src/android/test/suitebuilder/TestGrouping.java b/test-runner/src/android/test/suitebuilder/TestGrouping.java index 307afb55e47a..030bc426ac19 100644 --- a/test-runner/src/android/test/suitebuilder/TestGrouping.java +++ b/test-runner/src/android/test/suitebuilder/TestGrouping.java @@ -16,9 +16,7 @@ package android.test.suitebuilder; -import android.test.ClassPathPackageInfo; import android.test.ClassPathPackageInfoSource; -import android.test.PackageInfoSources; import android.util.Log; import com.android.internal.util.Predicate; import junit.framework.TestCase; @@ -131,10 +129,9 @@ class TestGrouping { } private List<Class<? extends TestCase>> testCaseClassesInPackage(String packageName) { - ClassPathPackageInfoSource source = PackageInfoSources.forClassPath(classLoader); - ClassPathPackageInfo packageInfo = source.getPackageInfo(packageName); + ClassPathPackageInfoSource source = ClassPathPackageInfoSource.forClassPath(classLoader); - return selectTestClasses(packageInfo.getTopLevelClassesRecursive()); + return selectTestClasses(source.getTopLevelClassesRecursive(packageName)); } @SuppressWarnings("unchecked") diff --git a/test-runner/tests/Android.mk b/test-runner/tests/Android.mk index cc9b01d18fa6..7ee047e47058 100644 --- a/test-runner/tests/Android.mk +++ b/test-runner/tests/Android.mk @@ -18,7 +18,7 @@ include $(CLEAR_VARS) # We only want this apk build for tests. # # Run the tests using the following commands: -# adb -r install ${ANDROID_PRODUCT_OUT}/data/app/FrameworkTestRunnerTests/FrameworkTestRunnerTests.apk +# adb install -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworkTestRunnerTests/FrameworkTestRunnerTests.apk # adb shell am instrument \ -e notAnnotation android.test.suitebuilder.examples.error.RunAsPartOfSeparateTest \ -w com.android.frameworks.testrunner.tests/android.test.InstrumentationTestRunner |