diff --git a/Android.mk b/Android.mk index 9684271891b21..03651fa7f95b6 100644 --- a/Android.mk +++ b/Android.mk @@ -72,6 +72,7 @@ LOCAL_SRC_FILES += \ core/java/android/app/IAppTask.aidl \ core/java/android/app/ITaskStackListener.aidl \ core/java/android/app/IBackupAgent.aidl \ + core/java/android/app/IBatteryService.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ core/java/android/app/INotificationManager.aidl \ core/java/android/app/IProcessObserver.aidl \ @@ -146,9 +147,6 @@ LOCAL_SRC_FILES += \ core/java/android/content/pm/IPackageMoveObserver.aidl \ core/java/android/content/pm/IPackageStatsObserver.aidl \ core/java/android/content/pm/IOnPermissionsChangeListener.aidl \ - core/java/android/content/res/IThemeChangeListener.aidl \ - core/java/android/content/res/IThemeProcessingListener.aidl \ - core/java/android/content/res/IThemeService.aidl \ core/java/android/database/IContentObserver.aidl \ core/java/android/hardware/ICameraService.aidl \ core/java/android/hardware/ICameraServiceListener.aidl \ @@ -252,9 +250,6 @@ LOCAL_SRC_FILES += \ core/java/android/service/voice/IVoiceInteractionService.aidl \ core/java/android/service/voice/IVoiceInteractionSession.aidl \ core/java/android/service/voice/IVoiceInteractionSessionService.aidl \ - core/java/android/service/gesture/IEdgeGestureService.aidl \ - core/java/android/service/gesture/IEdgeGestureActivationListener.aidl \ - core/java/android/service/gesture/IEdgeGestureHostCallback.aidl \ core/java/android/service/gesture/IGestureService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ core/java/android/service/wallpaper/IWallpaperEngine.aidl \ @@ -425,6 +420,7 @@ LOCAL_SRC_FILES += \ packages/services/PacProcessor/com/android/net/IProxyService.aidl \ packages/services/Proxy/com/android/net/IProxyCallback.aidl \ packages/services/Proxy/com/android/net/IProxyPortListener.aidl \ + ../../vendor/cmsdk/sdk/src/java/org/cyanogenmod/internal/themes/IIconCacheManager.aidl \ # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) diff --git a/api/current.txt b/api/current.txt index d7fdb2db68eea..c45cc3dbbf47e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -45134,7 +45134,10 @@ package java.lang.reflect { } public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member { + method public boolean equals(java.lang.Object); method public A getAnnotation(java.lang.Class); + method public java.lang.annotation.Annotation[] getAnnotations(); + method public java.lang.annotation.Annotation[] getDeclaredAnnotations(); method public java.lang.Class getDeclaringClass(); method public java.lang.Class[] getExceptionTypes(); method public java.lang.reflect.Type[] getGenericExceptionTypes(); @@ -45144,6 +45147,7 @@ package java.lang.reflect { method public java.lang.annotation.Annotation[][] getParameterAnnotations(); method public java.lang.Class[] getParameterTypes(); method public java.lang.reflect.TypeVariable>[] getTypeParameters(); + method public boolean isAnnotationPresent(java.lang.Class); method public boolean isSynthetic(); method public boolean isVarArgs(); method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException; @@ -45217,7 +45221,10 @@ package java.lang.reflect { } public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member { + method public boolean equals(java.lang.Object); method public A getAnnotation(java.lang.Class); + method public java.lang.annotation.Annotation[] getAnnotations(); + method public java.lang.annotation.Annotation[] getDeclaredAnnotations(); method public java.lang.Class getDeclaringClass(); method public java.lang.Object getDefaultValue(); method public java.lang.Class[] getExceptionTypes(); @@ -45231,6 +45238,7 @@ package java.lang.reflect { method public java.lang.Class getReturnType(); method public java.lang.reflect.TypeVariable[] getTypeParameters(); method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException; + method public boolean isAnnotationPresent(java.lang.Class); method public boolean isBridge(); method public boolean isSynthetic(); method public boolean isVarArgs(); diff --git a/api/system-current.txt b/api/system-current.txt index 3c88e5979c8ec..1e7b94e883e4c 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -130,6 +130,7 @@ package android { field public static final java.lang.String MODIFY_APPWIDGET_BIND_PERMISSIONS = "android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"; field public static final java.lang.String MODIFY_AUDIO_ROUTING = "android.permission.MODIFY_AUDIO_ROUTING"; field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS"; + field public static final java.lang.String MODIFY_CELL_BROADCASTS = "android.permission.MODIFY_CELL_BROADCASTS"; field public static final java.lang.String MODIFY_NETWORK_ACCOUNTING = "android.permission.MODIFY_NETWORK_ACCOUNTING"; field public static final java.lang.String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS"; field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE"; @@ -32713,19 +32714,25 @@ package android.telecom { field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED"; field public static final java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL"; field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED"; + field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"; field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"; + field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION"; field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS"; field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ',' field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';' + field public static final java.lang.String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT"; field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER"; field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE"; field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME"; + field public static final java.lang.String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT"; field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE"; field public static final java.lang.String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS"; field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS"; + field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telecom.extra.NOTIFICATION_COUNT"; + field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER"; field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS"; field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE"; field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE"; @@ -33425,6 +33432,7 @@ package android.telephony { field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL"; field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; + field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION"; field public static final int CALL_STATE_IDLE = 0; // 0x0 field public static final int CALL_STATE_OFFHOOK = 2; // 0x2 field public static final int CALL_STATE_RINGING = 1; // 0x1 @@ -33441,11 +33449,15 @@ package android.telephony { field public static final int DATA_CONNECTING = 1; // 0x1 field public static final int DATA_DISCONNECTED = 0; // 0x0 field public static final int DATA_SUSPENDED = 3; // 0x3 + field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT"; field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number"; + field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT"; + field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT"; field public static final java.lang.String EXTRA_STATE = "state"; field public static final java.lang.String EXTRA_STATE_IDLE; field public static final java.lang.String EXTRA_STATE_OFFHOOK; field public static final java.lang.String EXTRA_STATE_RINGING; + field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER"; field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7 field public static final int NETWORK_TYPE_CDMA = 4; // 0x4 field public static final int NETWORK_TYPE_EDGE = 2; // 0x2 @@ -47740,7 +47752,10 @@ package java.lang.reflect { } public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member { + method public boolean equals(java.lang.Object); method public A getAnnotation(java.lang.Class); + method public java.lang.annotation.Annotation[] getAnnotations(); + method public java.lang.annotation.Annotation[] getDeclaredAnnotations(); method public java.lang.Class getDeclaringClass(); method public java.lang.Class[] getExceptionTypes(); method public java.lang.reflect.Type[] getGenericExceptionTypes(); @@ -47750,6 +47765,7 @@ package java.lang.reflect { method public java.lang.annotation.Annotation[][] getParameterAnnotations(); method public java.lang.Class[] getParameterTypes(); method public java.lang.reflect.TypeVariable>[] getTypeParameters(); + method public boolean isAnnotationPresent(java.lang.Class); method public boolean isSynthetic(); method public boolean isVarArgs(); method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException; @@ -47823,7 +47839,10 @@ package java.lang.reflect { } public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member { + method public boolean equals(java.lang.Object); method public A getAnnotation(java.lang.Class); + method public java.lang.annotation.Annotation[] getAnnotations(); + method public java.lang.annotation.Annotation[] getDeclaredAnnotations(); method public java.lang.Class getDeclaringClass(); method public java.lang.Object getDefaultValue(); method public java.lang.Class[] getExceptionTypes(); @@ -47837,6 +47856,7 @@ package java.lang.reflect { method public java.lang.Class getReturnType(); method public java.lang.reflect.TypeVariable[] getTypeParameters(); method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException; + method public boolean isAnnotationPresent(java.lang.Class); method public boolean isBridge(); method public boolean isSynthetic(); method public boolean isVarArgs(); diff --git a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java index 3ec63b429a28e..8dffe47123101 100644 --- a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java +++ b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java @@ -47,7 +47,7 @@ public void onShowUsage(PrintStream out) { + " appops reset [--user ] []\n" + " an Android package name.\n" + " an AppOps operation.\n" - + " one of allow, ignore, deny, or default\n" + + " one of allow, ignore, deny, default, or ask\n" + " the user id under which the package is installed. If --user is not\n" + " specified, the current user is assumed.\n"); } @@ -85,6 +85,7 @@ public void onRun() throws Exception { private static final String MODE_DENY = "deny"; private static final String MODE_IGNORE = "ignore"; private static final String MODE_DEFAULT = "default"; + private static final String MODE_ASK = "ask"; private int strOpToOp(String op) { try { @@ -154,6 +155,9 @@ private void runSet() throws Exception { case MODE_DEFAULT: modeInt = AppOpsManager.MODE_DEFAULT; break; + case MODE_ASK: + modeInt = AppOpsManager.MODE_ASK; + break; default: System.err.println("Error: Mode " + mode + " is not valid,"); return; @@ -242,6 +246,9 @@ private void runGet() throws Exception { case AppOpsManager.MODE_DEFAULT: System.out.print("default"); break; + case AppOpsManager.MODE_ASK: + System.out.print("ask"); + break; default: System.out.print("mode="); System.out.print(ent.getMode()); diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 0c05dedef4908..1715728c570d9 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -46,6 +46,10 @@ ifeq ($(TARGET_BOOTANIMATION_USE_RGB565),true) LOCAL_CFLAGS += -DUSE_565 endif +ifneq ($(TARGET_BOOTANIMATION_MULTITHREAD_DECODE),false) + LOCAL_CFLAGS += -DMULTITHREAD_DECODE +endif + LOCAL_MODULE:= bootanimation ifdef TARGET_32_BIT_SURFACEFLINGER diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index b153454a4f552..8878d058656f7 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -72,6 +73,7 @@ #define OEM_SHUTDOWN_ANIMATION_FILE "/oem/media/shutdownanimation.zip" #define SYSTEM_SHUTDOWN_ANIMATION_FILE "/system/media/shutdownanimation.zip" #define SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE "/system/media/shutdownanimation-encrypted.zip" +#define THEME_SHUTDOWN_ANIMATION_FILE "/data/system/theme/shutdownanimation.zip" #define OEM_BOOT_MUSIC_FILE "/oem/media/boot.wav" #define SYSTEM_BOOT_MUSIC_FILE "/system/media/boot.wav" @@ -92,6 +94,11 @@ static pthread_cond_t mp_cond; static bool isMPlayerPrepared = false; static bool isMPlayerCompleted = false; +#ifdef MULTITHREAD_DECODE +static const int MAX_DECODE_THREADS = 2; +static const int MAX_DECODE_CACHE = 3; +#endif + class MPlayerListener : public MediaPlayerListener { void notify(int msg, int /*ext1*/, int /*ext2*/, const Parcel * /*obj*/) @@ -261,16 +268,16 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } -status_t BootAnimation::initTexture(const Animation::Frame& frame) +SkBitmap* BootAnimation::decode(const Animation::Frame& frame) { - //StopWatch watch("blah"); - SkBitmap bitmap; + SkBitmap *bitmap = NULL; SkMemoryStream stream(frame.map->getDataPtr(), frame.map->getDataLength()); SkImageDecoder* codec = SkImageDecoder::Factory(&stream); if (codec != NULL) { + bitmap = new SkBitmap(); codec->setDitherImage(false); - codec->decode(&stream, &bitmap, + codec->decode(&stream, bitmap, #ifdef USE_565 kRGB_565_SkColorType, #else @@ -280,13 +287,23 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame) delete codec; } - // ensure we can call getPixels(). No need to call unlock, since the - // bitmap will go out of scope when we return from this method. - bitmap.lockPixels(); + return bitmap; +} - const int w = bitmap.width(); - const int h = bitmap.height(); - const void* p = bitmap.getPixels(); +status_t BootAnimation::initTexture(const Animation::Frame& frame) +{ + //StopWatch watch("blah"); + return initTexture(decode(frame)); +} + +status_t BootAnimation::initTexture(SkBitmap *bitmap) +{ + // ensure we can call getPixels(). + bitmap->lockPixels(); + + const int w = bitmap->width(); + const int h = bitmap->height(); + const void* p = bitmap->getPixels(); GLint crop[4] = { 0, h, w, -h }; int tw = 1 << (31 - __builtin_clz(w)); @@ -294,7 +311,7 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame) if (tw < w) tw <<= 1; if (th < h) th <<= 1; - switch (bitmap.colorType()) { + switch (bitmap->colorType()) { case kN32_SkColorType: if (tw != w || th != h) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, @@ -324,6 +341,8 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame) glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + bitmap->unlockPixels(); + delete bitmap; return NO_ERROR; } @@ -407,14 +426,8 @@ status_t BootAnimation::readyToRun() { (access(getAnimationFileName(IMG_ENC), R_OK) == 0) && ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_ENC))) != NULL)) || - ((access(THEME_BOOTANIMATION_FILE, R_OK) == 0) && - ((zipFile = ZipFileRO::open(THEME_BOOTANIMATION_FILE)) != NULL)) || - - ((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) && - ((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) || - - ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) && - ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL)) || + ((access(getAnimationFileName(IMG_THM), R_OK) == 0) && + ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_THM))) != NULL)) || ((access(getAnimationFileName(IMG_DATA), R_OK) == 0) && ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_DATA))) != NULL)) || @@ -428,29 +441,26 @@ status_t BootAnimation::readyToRun() { // Preload the bootanimation zip on memory, so we don't stutter // when showing the animation FILE* fd; - if (encryptedAnimation && access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) - fd = fopen(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, "r"); - else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) - fd = fopen(OEM_BOOTANIMATION_FILE, "r"); - else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) - fd = fopen(SYSTEM_BOOTANIMATION_FILE, "r"); + if (encryptedAnimation && access(getAnimationFileName(IMG_ENC), R_OK) == 0) + fd = fopen(getAnimationFileName(IMG_ENC), "r"); + else if (access(getAnimationFileName(IMG_THM), R_OK) == 0) + fd = fopen(getAnimationFileName(IMG_THM), "r"); + else if (access(getAnimationFileName(IMG_DATA), R_OK) == 0) + fd = fopen(getAnimationFileName(IMG_DATA), "r"); + else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0) + fd = fopen(getAnimationFileName(IMG_SYS), "r"); else return NO_ERROR; if (fd != NULL) { - // We could use readahead.. - // ... if bionic supported it :( - //readahead(fd, 0, INT_MAX); - void *crappyBuffer = malloc(2*1024*1024); - if (crappyBuffer != NULL) { - // Read all the zip - while (!feof(fd)) - fread(crappyBuffer, 1024, 2*1024, fd); - - free(crappyBuffer); - } else { - ALOGW("Unable to allocate memory to preload the animation"); - } + // Since including fcntl.h doesn't give us the wrapper, use the syscall. + // 32 bits takes LO/HI offset (we don't care about endianness of 0). +#if defined(__aarch64__) || defined(__x86_64__) + if (syscall(__NR_readahead, fd, 0, INT_MAX)) +#else + if (syscall(__NR_readahead, fd, 0, 0, INT_MAX)) +#endif + ALOGW("Unable to cache the animation"); fclose(fd); } #endif @@ -635,11 +645,16 @@ bool BootAnimation::movie() char path[ANIM_ENTRY_NAME_MAX]; char color[7] = "000000"; // default to black if unspecified + char value[PROPERTY_VALUE_MAX]; char pathType; + + property_get("persist.bootanimation.scale", value, "1"); + double bas = atof(value); + if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps); - animation.width = width; - animation.height = height; + animation.width = width * bas; + animation.height = height * bas; animation.fps = fps; } else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) { @@ -734,12 +749,11 @@ bool BootAnimation::movie() clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); pthread_mutex_init(&mp_lock, NULL); - pthread_cond_init(&mp_cond, NULL); + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&mp_cond, &attr); - property_get("persist.sys.silent", value, "null"); - if (strncmp(value, "1", 1) != 0) { - playBackgroundMusic(); - } for (size_t i=0 ; inext()); +#else initTexture(frame); +#endif } if (!clearReg.isEmpty()) { @@ -843,6 +869,12 @@ bool BootAnimation::movie() usleep(part.pause * ns2us(frameDuration)); +#ifdef MULTITHREAD_DECODE + if (frameManager) { + delete frameManager; + } +#endif + // For infinite parts, we've now played them at least once, so perhaps exit if(exitPending() && !part.count) break; @@ -862,10 +894,16 @@ bool BootAnimation::movie() } + property_get("persist.sys.silent", value, "null"); + if (strncmp(value, "1", 1) != 0) { + ALOGD("playing boot audio here"); + playBackgroundMusic(); + } + if (isMPlayerPrepared) { ALOGD("waiting for media player to complete."); struct timespec timeout; - clock_gettime(CLOCK_REALTIME, &timeout); + clock_gettime(CLOCK_MONOTONIC, &timeout); timeout.tv_sec += 5; //timeout after 5s. pthread_mutex_lock(&mp_lock); @@ -887,12 +925,14 @@ bool BootAnimation::movie() const char *BootAnimation::getAnimationFileName(ImageID image) { - const char *fileName[2][3] = { { OEM_BOOTANIMATION_FILE, + const char *fileName[2][4] = { { OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE, - SYSTEM_ENCRYPTED_BOOTANIMATION_FILE }, { + SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, + THEME_BOOTANIMATION_FILE }, { OEM_SHUTDOWN_ANIMATION_FILE, SYSTEM_SHUTDOWN_ANIMATION_FILE, - SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE} }; + SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE, + THEME_SHUTDOWN_ANIMATION_FILE} }; int state; char sku[PROPERTY_VALUE_MAX]; char skusuffix[PATH_MAX]; @@ -1012,6 +1052,119 @@ bool BootAnimation::checkBootState(void) return ret; } +#ifdef MULTITHREAD_DECODE + +FrameManager::FrameManager(int numThreads, size_t maxSize, const SortedVector& frames) : + mMaxSize(maxSize), + mFrameCounter(0), + mNextIdx(0), + mFrames(frames), + mExit(false) +{ + pthread_mutex_init(&mBitmapsMutex, NULL); + pthread_cond_init(&mSpaceAvailableCondition, NULL); + pthread_cond_init(&mBitmapReadyCondition, NULL); + for (int i = 0; i < numThreads; i++) { + DecodeThread *thread = new DecodeThread(this); + thread->run("bootanimation", PRIORITY_URGENT_DISPLAY); + mThreads.add(thread); + } +} + +FrameManager::~FrameManager() +{ + mExit = true; + pthread_cond_broadcast(&mSpaceAvailableCondition); + pthread_cond_broadcast(&mBitmapReadyCondition); + for (size_t i = 0; i < mThreads.size(); i++) { + mThreads.itemAt(i)->requestExitAndWait(); + } + + // Any bitmap left in the queue won't get cleaned up by + // the consumer. Clean up now. + for(size_t i = 0; i < mDecodedFrames.size(); i++) { + delete mDecodedFrames[i].bitmap; + } +} + +SkBitmap* FrameManager::next() +{ + pthread_mutex_lock(&mBitmapsMutex); + + while(mDecodedFrames.size() == 0 || + mDecodedFrames.itemAt(0).idx != mNextIdx) { + pthread_cond_wait(&mBitmapReadyCondition, &mBitmapsMutex); + } + DecodeWork work = mDecodedFrames.itemAt(0); + mDecodedFrames.removeAt(0); + mNextIdx++; + pthread_cond_signal(&mSpaceAvailableCondition); + pthread_mutex_unlock(&mBitmapsMutex); + // The caller now owns the bitmap + return work.bitmap; +} + +FrameManager::DecodeWork FrameManager::getWork() +{ + DecodeWork work = { + .frame = NULL, + .bitmap = NULL, + .idx = 0 + }; + + pthread_mutex_lock(&mBitmapsMutex); + + while(mDecodedFrames.size() >= mMaxSize && !mExit) { + pthread_cond_wait(&mSpaceAvailableCondition, &mBitmapsMutex); + } + + if (!mExit) { + work.frame = &mFrames.itemAt(mFrameCounter % mFrames.size()); + work.idx = mFrameCounter; + mFrameCounter++; + } + + pthread_mutex_unlock(&mBitmapsMutex); + return work; +} + +void FrameManager::completeWork(DecodeWork work) { + size_t insertIdx; + pthread_mutex_lock(&mBitmapsMutex); + + for(insertIdx = 0; insertIdx < mDecodedFrames.size(); insertIdx++) { + if (work.idx < mDecodedFrames.itemAt(insertIdx).idx) { + break; + } + } + + mDecodedFrames.insertAt(work, insertIdx); + pthread_cond_signal(&mBitmapReadyCondition); + + pthread_mutex_unlock(&mBitmapsMutex); +} + +FrameManager::DecodeThread::DecodeThread(FrameManager* manager) : + Thread(false), + mManager(manager) +{ + +} + +bool FrameManager::DecodeThread::threadLoop() +{ + DecodeWork work = mManager->getWork(); + if (work.frame != NULL) { + work.bitmap = BootAnimation::decode(*work.frame); + mManager->completeWork(work); + return true; + } + + return false; +} + +#endif + // --------------------------------------------------------------------------- }; // namespace android diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 5bc1e8a45abac..090894f7addd5 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -26,6 +26,8 @@ #include #include +#include + class SkBitmap; namespace android { @@ -34,11 +36,17 @@ class AudioPlayer; class Surface; class SurfaceComposerClient; class SurfaceControl; +#ifdef MULTITHREAD_DECODE +class FrameManager; +#endif // --------------------------------------------------------------------------- class BootAnimation : public Thread, public IBinder::DeathRecipient { +#ifdef MULTITHREAD_DECODE + friend class FrameManager; +#endif public: enum { eOrientationDefault = 0, @@ -89,11 +97,12 @@ class BootAnimation : public Thread, public IBinder::DeathRecipient status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(const Animation::Frame& frame); + status_t initTexture(SkBitmap *bitmap); bool android(); bool readFile(const char* name, String8& outString); bool movie(); - enum ImageID { IMG_DATA = 0, IMG_SYS = 1, IMG_ENC = 2 }; + enum ImageID { IMG_DATA = 0, IMG_SYS = 1, IMG_ENC = 2, IMG_THM = 3 }; const char *getAnimationFileName(ImageID image); const char *getBootRingtoneFileName(ImageID image); void playBackgroundMusic(); @@ -101,6 +110,8 @@ class BootAnimation : public Thread, public IBinder::DeathRecipient void checkExit(); void checkShowAndroid(); + static SkBitmap *decode(const Animation::Frame& frame); + sp mSession; sp mAudioPlayer; AssetManager mAssets; @@ -115,6 +126,50 @@ class BootAnimation : public Thread, public IBinder::DeathRecipient ZipFileRO *mZip; }; +#ifdef MULTITHREAD_DECODE + +class FrameManager { +public: + struct DecodeWork { + const BootAnimation::Animation::Frame *frame; + SkBitmap *bitmap; + size_t idx; + }; + + FrameManager(int numThreads, size_t maxSize, const SortedVector& frames); + virtual ~FrameManager(); + + SkBitmap* next(); + +protected: + DecodeWork getWork(); + void completeWork(DecodeWork work); + +private: + + class DecodeThread : public Thread { + public: + DecodeThread(FrameManager* manager); + virtual ~DecodeThread() {} + private: + virtual bool threadLoop(); + FrameManager *mManager; + }; + + size_t mMaxSize; + size_t mFrameCounter; + size_t mNextIdx; + const SortedVector& mFrames; + Vector mDecodedFrames; + pthread_mutex_t mBitmapsMutex; + pthread_cond_t mSpaceAvailableCondition; + pthread_cond_t mBitmapReadyCondition; + bool mExit; + Vector > mThreads; +}; + +#endif + // --------------------------------------------------------------------------- }; // namespace android diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 58c3a9ccc89e4..4869adff8f017 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -262,6 +262,10 @@ public int run(String[] args) throws IOException, RemoteException { return runMovePrimaryStorage(); } + if ("set-user-restriction".equals(op)) { + return runSetUserRestriction(); + } + try { if (args.length == 1) { if (args[0].equalsIgnoreCase("-l")) { @@ -1518,6 +1522,38 @@ public int runMovePrimaryStorage() { } } + public int runSetUserRestriction() { + int userId = UserHandle.USER_OWNER; + String opt = nextOption(); + if (opt != null && "--user".equals(opt)) { + String arg = nextArg(); + if (arg == null || !isNumber(arg)) { + System.err.println("Error: valid userId not specified"); + return 1; + } + userId = Integer.parseInt(arg); + } + + String restriction = nextArg(); + String arg = nextArg(); + boolean value; + if ("1".equals(arg)) { + value = true; + } else if ("0".equals(arg)) { + value = false; + } else { + System.err.println("Error: valid value not specified"); + return 1; + } + try { + mUm.setUserRestriction(restriction, value, userId); + return 0; + } catch (RemoteException e) { + System.err.println(e.toString()); + return 1; + } + } + private int runUninstall() throws RemoteException { int flags = 0; int userId = UserHandle.USER_ALL; diff --git a/cmds/tm/Android.mk b/cmds/tm/Android.mk index 34a41ddce9f4d..97e8ee44ac250 100644 --- a/cmds/tm/Android.mk +++ b/cmds/tm/Android.mk @@ -4,6 +4,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.internal LOCAL_MODULE := tm include $(BUILD_JAVA_LIBRARY) diff --git a/cmds/tm/src/com/android/commands/tm/Tm.java b/cmds/tm/src/com/android/commands/tm/Tm.java index af1ac75e9e173..0ba5cb982c4d9 100644 --- a/cmds/tm/src/com/android/commands/tm/Tm.java +++ b/cmds/tm/src/com/android/commands/tm/Tm.java @@ -21,17 +21,19 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.ParceledListSlice; -import android.content.pm.ThemeUtils; -import android.content.res.IThemeService; -import android.content.res.ThemeChangeRequest; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.util.AndroidException; import com.android.internal.os.BaseCommand; +import cyanogenmod.app.CMContextConstants; +import cyanogenmod.themes.IThemeService; +import cyanogenmod.themes.ThemeChangeRequest; + +import org.cyanogenmod.internal.util.ThemeUtils; + import java.io.PrintStream; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -81,7 +83,8 @@ public void onShowUsage(PrintStream out) { } public void onRun() throws Exception { - mTs = IThemeService.Stub.asInterface(ServiceManager.getService("themes")); + mTs = IThemeService.Stub.asInterface(ServiceManager + .getService(CMContextConstants.CM_THEME_SERVICE)); if (mTs == null) { System.err.println(NO_SYSTEM_ERROR_CODE); throw new AndroidException("Can't connect to theme service; is the system running?"); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index ad08c239a7e9f..0ae918762e1b7 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1325,6 +1325,23 @@ public List getRunningTasks(int maxNum) } } + /** + * Check whether the current foreground tasks belongs to a given package. + * + * @param packageName Name of the package to check for + * + * @return Whether the current foreground tasks belongs to the given package + * @hide + */ + public boolean isPackageInForeground(String packageName) { + try { + return ActivityManagerNative.getDefault().isPackageInForeground(packageName); + } catch (RemoteException e) { + // System dead, we will be dead too soon! + return false; + } + } + /** * Completely remove the given task. * diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index d638de6a9151c..544331fb6b405 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -647,6 +647,15 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) return true; } + case IS_PACKAGE_IN_FOREGROUND_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String packageName = data.readString(); + boolean result = isPackageInForeground(packageName); + reply.writeNoException(); + reply.writeInt(result ? 1 : 0); + return true; + } + case GET_RECENT_TASKS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int maxNum = data.readInt(); @@ -1591,9 +1600,10 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) case START_BACKUP_AGENT_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data); + String packageName = data.readString(); int backupRestoreMode = data.readInt(); - boolean success = bindBackupAgent(info, backupRestoreMode); + int userId = data.readInt(); + boolean success = bindBackupAgent(packageName, backupRestoreMode, userId); reply.writeNoException(); reply.writeInt(success ? 1 : 0); return true; @@ -2087,11 +2097,14 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) return true; } - case SHOW_BOOT_MESSAGE_TRANSACTION: { + case UPDATE_BOOT_PROGRESS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - CharSequence msg = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); + int stage = data.readInt(); + ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data); + int current = data.readInt(); + int total = data.readInt(); boolean always = data.readInt() != 0; - showBootMessage(msg, always); + updateBootProgress(stage, info, current, total, always); reply.writeNoException(); return true; } @@ -3300,6 +3313,18 @@ public List getTasks(int maxNum, int flags) reply.recycle(); return list; } + public boolean isPackageInForeground(String packageName) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + mRemote.transact(IS_PACKAGE_IN_FOREGROUND_TRANSACTION, data, reply, 0); + reply.readException(); + boolean result = reply.readInt() != 0; + data.recycle(); + reply.recycle(); + return result; + } public List getRecentTasks(int maxNum, int flags, int userId) throws RemoteException { Parcel data = Parcel.obtain(); @@ -3853,13 +3878,14 @@ public IBinder peekService(Intent service, String resolvedType, String callingPa return binder; } - public boolean bindBackupAgent(ApplicationInfo app, int backupRestoreMode) + public boolean bindBackupAgent(String packageName, int backupRestoreMode, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); - app.writeToParcel(data, 0); + data.writeString(packageName); data.writeInt(backupRestoreMode); + data.writeInt(userId); mRemote.transact(START_BACKUP_AGENT_TRANSACTION, data, reply, 0); reply.readException(); boolean success = reply.readInt() != 0; @@ -5262,13 +5288,17 @@ public long[] getProcessPss(int[] pids) throws RemoteException { return res; } - public void showBootMessage(CharSequence msg, boolean always) throws RemoteException { + public void updateBootProgress(int stage, ApplicationInfo optimizedApp, + int currentAppPos, int totalAppCount, boolean always) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); - TextUtils.writeToParcel(msg, data, 0); + data.writeInt(stage); + optimizedApp.writeToParcel(data, 0); + data.writeInt(currentAppPos); + data.writeInt(totalAppCount); data.writeInt(always ? 1 : 0); - mRemote.transact(SHOW_BOOT_MESSAGE_TRANSACTION, data, reply, 0); + mRemote.transact(UPDATE_BOOT_PROGRESS_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7d3b572f0343e..782dc462726b7 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2456,16 +2456,6 @@ private Activity performLaunchActivity(ActivityClientRecord r, Intent customInte return activity; } - private void sendAppLaunchFailureBroadcast(ActivityClientRecord r) { - String pkg = null; - if (r.packageInfo != null && !TextUtils.isEmpty(r.packageInfo.getPackageName())) { - pkg = r.packageInfo.getPackageName(); - } - Intent intent = new Intent(Intent.ACTION_APP_FAILURE, - (pkg != null)? Uri.fromParts("package", pkg, null) : null); - getSystemContext().sendBroadcast(intent); - } - private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { int displayId = Display.DEFAULT_DISPLAY; try { @@ -4279,6 +4269,11 @@ final void handleConfigurationChanged(Configuration config, CompatibilityInfo co configDiff = mConfiguration.updateFrom(config); config = applyCompatConfiguration(mCurDefaultDisplayDpi); + + final Theme systemTheme = getSystemContext().getTheme(); + if ((systemTheme.getChangingConfigurations() & configDiff) != 0) { + systemTheme.rebase(); + } } ArrayList callbacks = collectComponentCallbacks(false, config); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 9c0d93123d773..c075ed675948e 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -24,8 +24,6 @@ import android.content.Intent; import android.content.IntentSender; import android.graphics.SurfaceTexture; -import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.Message; import android.os.OperationCanceledException; @@ -45,6 +43,17 @@ import dalvik.system.CloseGuard; import java.lang.ref.WeakReference; +import java.util.ArrayDeque; +import java.util.concurrent.Executor; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.android.internal.annotations.GuardedBy; + /** @hide */ public class ActivityView extends ViewGroup { @@ -53,9 +62,64 @@ public class ActivityView extends ViewGroup { private static final int MSG_SET_SURFACE = 1; - DisplayMetrics mMetrics = new DisplayMetrics(); + private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); + private static final int MINIMUM_POOL_SIZE = 1; + private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; + private static final int KEEP_ALIVE = 1; + + private static final ThreadFactory sThreadFactory = new ThreadFactory() { + private final AtomicInteger mCount = new AtomicInteger(1); + + public Thread newThread(Runnable r) { + return new Thread(r, "ActivityView #" + mCount.getAndIncrement()); + } + }; + + private static final BlockingQueue sPoolWorkQueue = + new LinkedBlockingQueue(128); + + /** + * An {@link Executor} that can be used to execute tasks in parallel. + */ + private static final Executor sExecutor = new ThreadPoolExecutor(MINIMUM_POOL_SIZE, + MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); + + + private static class SerialExecutor implements Executor { + private final ArrayDeque mTasks = new ArrayDeque(); + private Runnable mActive; + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + + protected synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + sExecutor.execute(mActive); + } + } + } + + private final SerialExecutor mExecutor = new SerialExecutor(); + + private final int mDensityDpi; private final TextureView mTextureView; + + @GuardedBy("mActivityContainerLock") private ActivityContainerWrapper mActivityContainer; + private Object mActivityContainerLock = new Object(); + private Activity mActivity; private int mWidth; private int mHeight; @@ -63,8 +127,6 @@ public class ActivityView extends ViewGroup { private int mLastVisibility; private ActivityViewCallback mActivityViewCallback; - private HandlerThread mThread = new HandlerThread("ActivityViewThread"); - private Handler mHandler; public ActivityView(Context context) { this(context, null); @@ -97,28 +159,14 @@ public ActivityView(Context context, AttributeSet attrs, int defStyle) { + e); } - mThread.start(); - mHandler = new Handler(mThread.getLooper()) { - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - if (msg.what == MSG_SET_SURFACE) { - try { - mActivityContainer.setSurface((Surface) msg.obj, msg.arg1, msg.arg2, - mMetrics.densityDpi); - } catch (RemoteException e) { - throw new RuntimeException( - "ActivityView: Unable to set surface of ActivityContainer. " + e); - } - } - } - }; mTextureView = new TextureView(context); mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); addView(mTextureView); WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(mMetrics); + DisplayMetrics metrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(metrics); + mDensityDpi = metrics.densityDpi; mLastVisibility = getVisibility(); @@ -131,15 +179,13 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } @Override - protected void onVisibilityChanged(View changedView, int visibility) { + protected void onVisibilityChanged(View changedView, final int visibility) { super.onVisibilityChanged(changedView, visibility); if (mSurface != null && (visibility == View.GONE || mLastVisibility == View.GONE)) { - Message msg = Message.obtain(mHandler, MSG_SET_SURFACE); - msg.obj = (visibility == View.GONE) ? null : mSurface; - msg.arg1 = mWidth; - msg.arg2 = mHeight; - mHandler.sendMessage(msg); + if (DEBUG) Log.v(TAG, "visibility changed; enqueing runnable"); + final Surface surface = (visibility == View.GONE) ? null : mSurface; + setSurfaceAsync(surface, mWidth, mHeight, mDensityDpi, false); } mLastVisibility = visibility; } @@ -230,8 +276,10 @@ public void release() { Log.e(TAG, "Duplicate call to release"); return; } - mActivityContainer.release(); - mActivityContainer = null; + synchronized (mActivityContainerLock) { + mActivityContainer.release(); + mActivityContainer = null; + } if (mSurface != null) { mSurface.release(); @@ -241,21 +289,37 @@ public void release() { mTextureView.setSurfaceTextureListener(null); } - private void attachToSurfaceWhenReady() { - final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); - if (surfaceTexture == null || mSurface != null) { - // Either not ready to attach, or already attached. - return; - } - - mSurface = new Surface(surfaceTexture); - try { - mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi); - } catch (RemoteException e) { - mSurface.release(); - mSurface = null; - throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e); - } + private void setSurfaceAsync(final Surface surface, final int width, final int height, + final int densityDpi, final boolean callback) { + mExecutor.execute(new Runnable() { + public void run() { + try { + synchronized (mActivityContainerLock) { + if (mActivityContainer != null) { + mActivityContainer.setSurface(surface, width, height, densityDpi); + } + } + } catch (RemoteException e) { + throw new RuntimeException( + "ActivityView: Unable to set surface of ActivityContainer. ", + e); + } + if (callback) { + post(new Runnable() { + @Override + public void run() { + if (mActivityViewCallback != null) { + if (surface != null) { + mActivityViewCallback.onSurfaceAvailable(ActivityView.this); + } else { + mActivityViewCallback.onSurfaceDestroyed(ActivityView.this); + } + } + } + }); + } + } + }); } /** @@ -306,10 +370,8 @@ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, + height); mWidth = width; mHeight = height; - attachToSurfaceWhenReady(); - if (mActivityViewCallback != null) { - mActivityViewCallback.onSurfaceAvailable(ActivityView.this); - } + mSurface = new Surface(surfaceTexture); + setSurfaceAsync(mSurface, mWidth, mHeight, mDensityDpi, true); } @Override @@ -329,15 +391,7 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed"); mSurface.release(); mSurface = null; - try { - mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi); - } catch (RemoteException e) { - throw new RuntimeException( - "ActivityView: Unable to set surface of ActivityContainer. " + e); - } - if (mActivityViewCallback != null) { - mActivityViewCallback.onSurfaceDestroyed(ActivityView.this); - } + setSurfaceAsync(null, mWidth, mHeight, mDensityDpi, true); return true; } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index c590fac8c3eba..11a5ee85f0865 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1381,11 +1381,6 @@ public static class OpEntry implements Parcelable { private final int mAllowedCount; private final int mIgnoredCount; - public OpEntry(int op, int mode, long time, long rejectTime, int duration, - int proxyUid, String proxyPackage) { - this(op, mode, time, rejectTime, duration, proxyUid, proxyPackage, 0, 0); - } - public OpEntry(int op, int mode, long time, long rejectTime, int duration, int proxyUid, String proxyPackage, int allowedCount, int ignoredCount) { mOp = op; diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index c0cd9ec2ec642..c829daa9eed1e 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -2046,6 +2046,19 @@ public void setComponentProtectedSetting(ComponentName componentName, boolean ne } } + /** @hide */ + @Override + public boolean isComponentProtected(String callingPackage, int callingUid, + ComponentName componentName) { + try { + return mPM.isComponentProtected(callingPackage, callingUid, componentName, + mContext.getUserId()); + } catch (RemoteException re) { + Log.e(TAG, "Failed to get component protected setting", re); + return false; + } + } + @Override public PackageInstaller getPackageInstaller() { synchronized (mLock) { diff --git a/core/java/android/app/ComposedIconInfo.java b/core/java/android/app/ComposedIconInfo.java index f49c230011c6b..71321c1faf4ac 100644 --- a/core/java/android/app/ComposedIconInfo.java +++ b/core/java/android/app/ComposedIconInfo.java @@ -74,11 +74,9 @@ private ComposedIconInfo(Parcel source) { iconPaletteBack = source.readInt(); swatchType = SwatchType.values()[source.readInt()]; int numDefaultColors = source.readInt(); - if (numDefaultColors > 0) { - defaultSwatchColors = new int[numDefaultColors]; - for (int i = 0; i < numDefaultColors; i++) { - defaultSwatchColors[i] = source.readInt(); - } + defaultSwatchColors = new int[numDefaultColors]; + for (int i = 0; i < numDefaultColors; i++) { + defaultSwatchColors[i] = source.readInt(); } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 479010d211fde..6896c21bcabf2 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -40,8 +40,6 @@ import android.content.res.AssetManager; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; -import android.content.res.IThemeService; -import android.content.res.ThemeManager; import android.content.res.Resources; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; @@ -2020,6 +2018,11 @@ private File[] ensureDirsExistOrFilter(File[] dirs) { } result.add(dir); } + + // Make sure there is at least one element, let the callers handle that + if (result.size() == 0) { + result.add(null); + } return result.toArray(new File[result.size()]); } diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index fb0e79b849b28..b382b7615b0f6 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -266,6 +266,13 @@ public class DownloadManager { */ public final static int PAUSED_UNKNOWN = 4; + /** + * Value of {@link #COLUMN_REASON} when the download is paused by manual. + * + * @hide + */ + public final static int PAUSED_BY_MANUAL = 5; + /** * Broadcast intent action sent by the download manager when a download completes. */ @@ -865,6 +872,7 @@ Cursor runQuery(ContentResolver resolver, String[] projection, Uri baseUri) { parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY)); parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK)); parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI)); + parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_MANUAL)); } if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) { parts.add(statusClause("=", Downloads.Impl.STATUS_SUCCESS)); @@ -1030,7 +1038,7 @@ public Uri getUriForDownloadedFile(long id) { if (cursor.moveToFirst()) { int status = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_STATUS)); if (DownloadManager.STATUS_SUCCESSFUL == status) { - return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, id); + return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id); } } } finally { @@ -1099,6 +1107,34 @@ public void restartDownload(long... ids) { mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids)); } + /** + * Pause the given running download by manual. + * + * @param id the ID of the download to be paused + * @return the number of downloads actually updated + * @hide + */ + public int pauseDownload(long id) { + ContentValues values = new ContentValues(); + values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PAUSED_BY_MANUAL); + + return mResolver.update(ContentUris.withAppendedId(mBaseUri, id), values, null, null); + } + + /** + * Resume the given paused download by manual. + * + * @param id the ID of the download to be resumed + * @return the number of downloads actually updated + * @hide + */ + public int resumeDownload(long id) { + ContentValues values = new ContentValues(); + values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_RUNNING); + + return mResolver.update(ContentUris.withAppendedId(mBaseUri, id), values, null, null); + } + /** * Returns maximum size, in bytes, of downloads that may go over a mobile connection; or null if * there's no limit @@ -1227,7 +1263,7 @@ private static void validateArgumentIsNonEmpty(String paramName, String val) { * @hide */ public Uri getDownloadUri(long id) { - return ContentUris.withAppendedId(mBaseUri, id); + return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id); } /** @@ -1308,7 +1344,7 @@ private String getLocalUri() { // return content URI for cache download long downloadId = getLong(getColumnIndex(Downloads.Impl._ID)); - return ContentUris.withAppendedId(mBaseUri, downloadId).toString(); + return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, downloadId).toString(); } private long getReason(int status) { @@ -1335,6 +1371,9 @@ private long getPausedReason(int status) { case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: return PAUSED_QUEUED_FOR_WIFI; + case Downloads.Impl.STATUS_PAUSED_BY_MANUAL: + return PAUSED_BY_MANUAL; + default: return PAUSED_UNKNOWN; } @@ -1390,6 +1429,7 @@ private int translateStatus(int status) { case Downloads.Impl.STATUS_WAITING_TO_RETRY: case Downloads.Impl.STATUS_WAITING_FOR_NETWORK: case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: + case Downloads.Impl.STATUS_PAUSED_BY_MANUAL: return STATUS_PAUSED; case Downloads.Impl.STATUS_SUCCESS: diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index a27f9c88d2153..75951cfeb0ff8 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -129,6 +129,7 @@ public int addAppTask(IBinder activityToken, Intent intent, ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException; public Point getAppTaskThumbnailSize() throws RemoteException; public List getTasks(int maxNum, int flags) throws RemoteException; + public boolean isPackageInForeground(String packageName) throws RemoteException; public List getRecentTasks(int maxNum, int flags, int userId) throws RemoteException; public ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) throws RemoteException; @@ -183,7 +184,7 @@ public void serviceDoneExecuting(IBinder token, int type, int startId, public IBinder peekService(Intent service, String resolvedType, String callingPackage) throws RemoteException; - public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode) + public boolean bindBackupAgent(String packageName, int backupRestoreMode, int userId) throws RemoteException; public void clearPendingBackup() throws RemoteException; public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException; @@ -407,7 +408,8 @@ public void setPackageAskScreenCompat(String packageName, boolean ask) public long[] getProcessPss(int[] pids) throws RemoteException; - public void showBootMessage(CharSequence msg, boolean always) throws RemoteException; + public void updateBootProgress(int stage, ApplicationInfo optimizedApp, + int currentAppPos, int totalAppCount, boolean always) throws RemoteException; public void keyguardWaitingForActivityDrawn() throws RemoteException; @@ -621,6 +623,11 @@ private WaitResult(Parcel source) { } } + public static final int BOOT_STAGE_STARTING_APPS = 1; + public static final int BOOT_STAGE_FSTRIM = 2; + public static final int BOOT_STAGE_PREPARING_APPS = 3; + public static final int BOOT_STAGE_COMPLETE = 4; + String descriptor = "android.app.IActivityManager"; // Please keep these transaction codes the same -- they are also @@ -756,7 +763,7 @@ private WaitResult(Parcel source) { int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134; int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135; int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136; - int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137; + int UPDATE_BOOT_PROGRESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137; int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139; int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140; int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141; @@ -870,4 +877,5 @@ private WaitResult(Parcel source) { = IBinder.FIRST_CALL_TRANSACTION+299; int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300; int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301; + int IS_PACKAGE_IN_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+302; } diff --git a/core/java/android/content/res/IThemeChangeListener.aidl b/core/java/android/app/IBatteryService.aidl similarity index 65% rename from core/java/android/content/res/IThemeChangeListener.aidl rename to core/java/android/app/IBatteryService.aidl index a2e2abd6def7e..196159b170685 100644 --- a/core/java/android/content/res/IThemeChangeListener.aidl +++ b/core/java/android/app/IBatteryService.aidl @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project +/** + * Copyright (c) 2016, The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,10 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.res; -/** {@hide} */ -oneway interface IThemeChangeListener { - void onProgress(int progress); - void onFinish(boolean isSuccess); +package android.app; + +/** + * System private API for talking with the battery service. + * + * {@hide} + */ +interface IBatteryService { + boolean isDockBatterySupported(); } diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index f78fb47e5f5e9..06c064f0e9d67 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -55,6 +55,12 @@ interface INotificationManager void setPackageVisibilityOverride(String pkg, int uid, int visibility); int getPackageVisibilityOverride(String pkg, int uid); + void setShowNotificationForPackageOnKeyguard(String pkg, int uid, int status); + int getShowNotificationForPackageOnKeyguard(String pkg, int uid); + + void setPackageNotificationSoundTimeout(String pkg, int uid, long timeout); + long getPackageNotificationSoundTimeout(String pkg, int uid); + // TODO: Remove this when callers have been migrated to the equivalent // INotificationListener method. StatusBarNotification[] getActiveNotifications(String callingPkg); @@ -77,7 +83,7 @@ interface INotificationManager void setInterruptionFilter(String pkg, int interruptionFilter); ComponentName getEffectsSuppressor(); - boolean matchesCallFilter(in Bundle extras); + boolean[] matchesCallFilter(in Bundle extras); boolean isSystemConditionProviderEnabled(String path); int getZenMode(); @@ -97,4 +103,6 @@ interface INotificationManager void applyRestore(in byte[] payload, int user); ParceledListSlice getAppActiveNotifications(String callingPkg, int userId); + + boolean deviceLightsCan(int lightCapability); } diff --git a/core/java/android/app/IconPackHelper.java b/core/java/android/app/IconPackHelper.java index 627330fc18787..9c71ddd5cbf5e 100644 --- a/core/java/android/app/IconPackHelper.java +++ b/core/java/android/app/IconPackHelper.java @@ -25,7 +25,6 @@ import java.util.Random; import android.content.pm.PackageInfo; -import android.content.res.IThemeService; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -44,7 +43,10 @@ import android.os.ServiceManager; import android.util.Log; import android.util.TypedValue; + import com.android.internal.util.cm.palette.Palette; + +import org.cyanogenmod.internal.themes.IIconCacheManager; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; @@ -103,6 +105,12 @@ public class IconPackHelper { private static final float DEFAULT_SCALE = 1.0f; private static final int COMPOSED_ICON_COOKIE = 128; + private static final String ICON_CACHE_SERVICE = "cmiconcache"; + + public static final String SYSTEM_THEME_PATH = "/data/system/theme"; + public static final String SYSTEM_THEME_ICON_CACHE_DIR = SYSTEM_THEME_PATH + + File.separator + "icons"; + private final Context mContext; private Map mIconPackResourceMap; private String mLoadedIconPackName; @@ -410,15 +418,12 @@ public static Resources createIconResource(Context context, String packageName) String prefixPath; String iconApkPath; - String iconResPath; if (info.isLegacyIconPackApk) { - iconResPath = ""; iconApkPath = ""; prefixPath = ""; } else { prefixPath = ThemeUtils.ICONS_PATH; //path inside APK iconApkPath = ThemeUtils.getIconPackApkPath(packageName); - iconResPath = ThemeUtils.getIconPackResPath(packageName); } AssetManager assets = new AssetManager(); @@ -587,11 +592,11 @@ public static boolean shouldComposeIcon(ComposedIconInfo iconInfo) { public static class IconCustomizer { private static final Random sRandom = new Random(); - private static final IThemeService sThemeService; + private static final IIconCacheManager sIconCacheManager; static { - sThemeService = IThemeService.Stub.asInterface( - ServiceManager.getService(Context.THEME_SERVICE)); + sIconCacheManager = IIconCacheManager.Stub.asInterface( + ServiceManager.getService(ICON_CACHE_SERVICE)); } public static Drawable getComposedIconDrawable(Drawable icon, Context context, @@ -628,33 +633,42 @@ public static void getValue(Resources res, int resId, TypedValue outValue, } TypedValue tempValue = new TypedValue(); tempValue.setTo(outValue); - outValue.assetCookie = COMPOSED_ICON_COOKIE; - outValue.data = resId & (COMPOSED_ICON_COOKIE << 24 | 0x00ffffff); - outValue.string = getCachedIconPath(pkgName, resId, outValue.density); - int hashCode = outValue.string.hashCode() & 0x7fffffff; - int defaultSwatchColor = 0; - - if (!(new File(outValue.string.toString()).exists())) { - // compose the icon and cache it - int back = 0; - if (iconInfo.swatchType != ComposedIconInfo.SwatchType.None) { - back = iconInfo.iconPaletteBack; - if (iconInfo.defaultSwatchColors.length > 0) { - defaultSwatchColor =iconInfo.defaultSwatchColors[ - hashCode % iconInfo.defaultSwatchColors.length]; + // Catch all exceptions and restore outValue to tempValue if one occurs + try { + outValue.assetCookie = COMPOSED_ICON_COOKIE; + outValue.data = resId & (COMPOSED_ICON_COOKIE << 24 | 0x00ffffff); + outValue.string = getCachedIconPath(pkgName, resId, outValue.density); + int hashCode = outValue.string.hashCode() & 0x7fffffff; + int defaultSwatchColor = 0; + + if (!(new File(outValue.string.toString()).exists())) { + // compose the icon and cache it + int back = 0; + if (iconInfo.swatchType != ComposedIconInfo.SwatchType.None) { + back = iconInfo.iconPaletteBack; + if (iconInfo.defaultSwatchColors.length > 0) { + defaultSwatchColor = iconInfo.defaultSwatchColors[ + hashCode % iconInfo.defaultSwatchColors.length]; + } + } else if (iconInfo.iconBacks != null && iconInfo.iconBacks.length > 0) { + back = iconInfo.iconBacks[hashCode % iconInfo.iconBacks.length]; + } + if (DEBUG) { + Log.d(TAG, "Composing icon for " + pkgName); + } + Bitmap bmp = createIconBitmap(baseIcon, res, back, defaultSwatchColor, + iconInfo); + if (!cacheComposedIcon(bmp, + getCachedIconName(pkgName, resId, outValue.density))) { + Log.w(TAG, "Unable to cache icon " + outValue.string); + // restore the original TypedValue + outValue.setTo(tempValue); } - } else if (iconInfo.iconBacks != null && iconInfo.iconBacks.length > 0) { - back = iconInfo.iconBacks[hashCode % iconInfo.iconBacks.length]; - } - if (DEBUG) { - Log.d(TAG, "Composing icon for " + pkgName); - } - Bitmap bmp = createIconBitmap(baseIcon, res, back, defaultSwatchColor, iconInfo); - if (!cacheComposedIcon(bmp, getCachedIconName(pkgName, resId, outValue.density))) { - Log.w(TAG, "Unable to cache icon " + outValue.string); - // restore the original TypedValue - outValue.setTo(tempValue); } + } catch (Exception e) { + // catch all, restore the original value and log it + outValue.setTo(tempValue); + Log.w(TAG, "getValue failed for " + outValue.string, e); } } @@ -802,7 +816,7 @@ private static Bitmap createIconBitmap(Drawable icon, Resources res, int iconBac private static boolean cacheComposedIcon(Bitmap bmp, String path) { try { - return sThemeService.cacheComposedIcon(bmp, path); + return sIconCacheManager.cacheComposedIcon(bmp, path); } catch (RemoteException e) { Log.e(TAG, "Unable to cache icon.", e); } @@ -811,7 +825,7 @@ private static boolean cacheComposedIcon(Bitmap bmp, String path) { } private static String getCachedIconPath(String pkgName, int resId, int density) { - return String.format("%s/%s", ThemeUtils.SYSTEM_THEME_ICON_CACHE_DIR, + return String.format("%s/%s", SYSTEM_THEME_ICON_CACHE_DIR, getCachedIconName(pkgName, resId, density)); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index cd07c9c51135e..8835a090f09fe 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -45,6 +45,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.MathUtils; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -62,6 +63,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.Set; /** * A class that represents how a persistent notification is to be presented to @@ -519,6 +522,21 @@ public class Notification implements Parcelable @Priority public int priority; + /** + * Default. + * Show all notifications from an app on keyguard. + * + * @hide + */ + public static final int SHOW_ALL_NOTI_ON_KEYGUARD = 0x01; + + /** + * Show only notifications from an app which are not ongoing ones. + * + * @hide + */ + public static final int SHOW_NO_ONGOING_NOTI_ON_KEYGUARD = 0x02; + /** * Accent color (an ARGB integer like the constants in {@link android.graphics.Color}) * to be applied by the standard Style templates when presenting this notification. @@ -960,6 +978,9 @@ public Action(int icon, CharSequence title, PendingIntent intent) { private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, RemoteInput[] remoteInputs) { this.mIcon = icon; + if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) { + this.icon = icon.getResId(); + } this.title = title; this.actionIntent = intent; this.mExtras = extras != null ? extras : new Bundle(); @@ -1607,13 +1628,23 @@ public final void lightenPayload() { bigContentView = null; headsUpContentView = null; mLargeIcon = null; - if (extras != null) { - extras.remove(Notification.EXTRA_LARGE_ICON); - extras.remove(Notification.EXTRA_LARGE_ICON_BIG); - extras.remove(Notification.EXTRA_PICTURE); - extras.remove(Notification.EXTRA_BIG_TEXT); + if (extras != null && !extras.isEmpty()) { // Prevent light notifications from being rebuilt. extras.remove(Builder.EXTRA_NEEDS_REBUILD); + final Set keyset = extras.keySet(); + final int N = keyset.size(); + final String[] keys = keyset.toArray(new String[N]); + for (int i=0; iFor custom display notifications created using {@link #setDisplayIntent}, - * the default is {@link #SIZE_LARGE}. All other notifications size automatically based + * the default is {@link #SIZE_MEDIUM}. All other notifications size automatically based * on their content. */ public static final int SIZE_DEFAULT = 0; diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 605c006130878..eae2599c358d6 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -19,6 +19,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; +import android.app.Notification; import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; @@ -340,12 +341,12 @@ public ComponentName getEffectsSuppressor() { /** * @hide */ - public boolean matchesCallFilter(Bundle extras) { + public boolean[] matchesCallFilter(Bundle extras) { INotificationManager service = getService(); try { return service.matchesCallFilter(extras); } catch (RemoteException e) { - return false; + return null; } } @@ -512,6 +513,16 @@ public ArraySet getPackagesRequestingNotificationPolicyAccess() { return new ArraySet(); } + /** @hide */ + public int getShowNotificationForPackageOnKeyguard(String pkg, int uid) { + INotificationManager service = getService(); + try { + return getService().getShowNotificationForPackageOnKeyguard(pkg, uid); + } catch (RemoteException e) { + return Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + } + } + private Context mContext; private static void checkRequired(String name, Object value) { @@ -754,4 +765,32 @@ public static int zenModeFromInterruptionFilter(int interruptionFilter, int defV default: return defValue; } } + + /** @hide */ + public static final int LIGHTS_RGB_NOTIFICATION = 0; + /** @hide */ + public static final int LIGHTS_RGB_BATTERY = 1 ; + /** @hide */ + public static final int LIGHTS_MULTIPLE_LED = 2; + /** @hide */ + public static final int LIGHTS_LED_PULSE = 3; + /** @hide */ + public static final int LIGHTS_SEGMENTED_BATTERY_LIGHTS = 4; + /** @hide */ + public static final int LIGHTS_ADJUSTABLE_NOTIFICATION_BRIGHTNESS = 5; + + /** @hide */ + public boolean deviceLightsCan(int lightCapability) { + INotificationManager service = getService(); + try { + return service.deviceLightsCan(lightCapability); + } catch (RemoteException e) { + return true; + } catch (NullPointerException e) { + return true; + } + // If the service isn't up yet, assume everything is possible + } + + } diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 7492cd03e38c8..c8aec2e1d109a 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -335,18 +335,6 @@ public Resources getTopLevelThemedResources(String resDir, int displayId, String ResourcesKey key = new ResourcesKey(resDir, displayId, null, compatInfo.applicationScale, isThemeable, themeConfig); - synchronized (this) { - WeakReference wr = mActiveResources.get(key); - r = wr != null ? wr.get() : null; - if (r != null && r.getAssets().isUpToDate()) { - if (false) { - Slog.w(TAG, "Returning cached resources " + r + " " + resDir - + ": appScale=" + r.getCompatibilityInfo().applicationScale); - } - return r; - } - } - AssetManager assets = new AssetManager(); assets.setAppName(packageName); assets.setThemeSupport(isThemeable); @@ -387,20 +375,7 @@ public Resources getTopLevelThemedResources(String resDir, int displayId, String + r.getCompatibilityInfo().applicationScale); } - synchronized (this) { - WeakReference wr = mActiveResources.get(key); - Resources existing = wr != null ? wr.get() : null; - if (existing != null && existing.getAssets().isUpToDate()) { - // Someone else already created the resources while we were - // unlocked; go ahead and use theirs. - r.getAssets().close(); - return existing; - } - - // XXX need to remove entries when weak references go away - mActiveResources.put(key, new WeakReference(r)); - return r; - } + return r; } /** @@ -576,6 +551,7 @@ private boolean attachThemeAssets(AssetManager assets, ThemeConfig theme) { PackageInfo piTheme = null; PackageInfo piTarget = null; PackageInfo piAndroid = null; + PackageInfo piCm = null; // Some apps run in process of another app (eg keyguard/systemUI) so we must get the // package name from the res tables. The 0th base package name will be the android group. @@ -609,23 +585,28 @@ private boolean attachThemeAssets(AssetManager assets, ThemeConfig theme) { } piAndroid = getPackageManager().getPackageInfo("android", 0, UserHandle.getCallingUserId()); + piCm = getPackageManager().getPackageInfo("cyanogenmod.platform", 0, + UserHandle.getCallingUserId()); } catch (RemoteException e) { } if (piTheme == null || piTheme.applicationInfo == null || piTarget == null || piTarget.applicationInfo == null || piAndroid == null || piAndroid.applicationInfo == null || + piCm == null || piCm.applicationInfo == null || piTheme.mOverlayTargets == null) { return false; } + // Attach themed resources for target String themePackageName = piTheme.packageName; String themePath = piTheme.applicationInfo.publicSourceDir; if (!piTarget.isThemeApk && piTheme.mOverlayTargets.contains(basePackageName)) { String targetPackagePath = piTarget.applicationInfo.sourceDir; String prefixPath = ThemeUtils.getOverlayPathToTarget(basePackageName); - String resCachePath = ThemeUtils.getTargetCacheDir(piTarget.packageName, piTheme); + String resCachePath = ThemeUtils.getTargetCacheDir(piTarget.packageName, + piTheme.packageName); String resApkPath = resCachePath + "/resources.apk"; String idmapPath = ThemeUtils.getIdmapPath(piTarget.packageName, piTheme.packageName); int cookie = assets.addOverlayPath(idmapPath, themePath, resApkPath, @@ -637,9 +618,28 @@ private boolean attachThemeAssets(AssetManager assets, ThemeConfig theme) { } } + // Attach themed resources for cmsdk + if (!piTarget.isThemeApk && !piCm.packageName.equals(basePackageName) && + piTheme.mOverlayTargets.contains(piCm.packageName)) { + String resCachePath= ThemeUtils.getTargetCacheDir(piCm.packageName, + piTheme.packageName); + String prefixPath = ThemeUtils.getOverlayPathToTarget(piCm.packageName); + String targetPackagePath = piCm.applicationInfo.publicSourceDir; + String resApkPath = resCachePath + "/resources.apk"; + String idmapPath = ThemeUtils.getIdmapPath(piCm.packageName, piTheme.packageName); + int cookie = assets.addOverlayPath(idmapPath, themePath, + resApkPath, targetPackagePath, prefixPath); + if (cookie != 0) { + assets.setThemePackageName(themePackageName); + assets.addThemeCookie(cookie); + } + } + + // Attach themed resources for android framework if (!piTarget.isThemeApk && !"android".equals(basePackageName) && piTheme.mOverlayTargets.contains("android")) { - String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName, piTheme); + String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName, + piTheme.packageName); String prefixPath = ThemeUtils.getOverlayPathToTarget(piAndroid.packageName); String targetPackagePath = piAndroid.applicationInfo.publicSourceDir; String resApkPath = resCachePath + "/resources.apk"; @@ -742,7 +742,7 @@ private boolean attachCommonAssets(AssetManager assets, ThemeConfig theme) { String themePath = piTheme.applicationInfo.publicSourceDir; String prefixPath = ThemeUtils.COMMON_RES_PATH; String resCachePath = - ThemeUtils.getTargetCacheDir(ThemeUtils.COMMON_RES_TARGET, piTheme); + ThemeUtils.getTargetCacheDir(ThemeUtils.COMMON_RES_TARGET, piTheme.packageName); String resApkPath = resCachePath + "/resources.apk"; int cookie = assets.addCommonOverlayPath(themePath, resApkPath, prefixPath); diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 5e8ad68957b2b..fad3f62a8f949 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -92,6 +92,7 @@ public class StatusBarManager { public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0; public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1; + public static final int CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE = 2; private Context mContext; private IStatusBarService mService; diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 08f4efdc6fa76..34c967f96faa2 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -37,9 +37,7 @@ import android.content.RestrictionsManager; import android.content.pm.ILauncherApps; import android.content.pm.LauncherApps; -import android.content.res.IThemeService; import android.content.res.Resources; -import android.content.res.ThemeManager; import android.hardware.ConsumerIrManager; import android.hardware.ISerialManager; import android.hardware.SensorManager; @@ -256,7 +254,9 @@ public DownloadManager createService(ContextImpl ctx) { new StaticServiceFetcher() { @Override public BatteryManager createService() { - return new BatteryManager(); + IBinder b = ServiceManager.getService(Context.BATTERY_SERVICE); + IBatteryService service = IBatteryService.Stub.asInterface(b); + return new BatteryManager(service); }}); registerService(Context.NFC_SERVICE, NfcManager.class, @@ -706,15 +706,6 @@ public MidiManager createService(ContextImpl ctx) { public RadioManager createService(ContextImpl ctx) { return new RadioManager(ctx); }}); - - registerService(Context.THEME_SERVICE, ThemeManager.class, - new CachedServiceFetcher() { - public ThemeManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.THEME_SERVICE); - IThemeService service = IThemeService.Stub.asInterface(b); - return new ThemeManager(ctx.getOuterContext(), - service); - }}); } /** diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index 7718a36154646..0335e2863a7bb 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -21,6 +21,8 @@ import android.content.res.XmlResourceParser; import android.os.*; import android.os.Process; +import android.os.storage.StorageManager; +import android.os.storage.StorageVolume; import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; @@ -207,6 +209,8 @@ public static class BackupScheme { final int mFullBackupContent; final PackageManager mPackageManager; + final StorageManager mStorageManager; + final StorageVolume[] mVolumes; final String mPackageName; /** @@ -230,6 +234,15 @@ String tokenToDirectoryPath(String domainToken) { } else { return null; } + } else if (domainToken.startsWith(FullBackup.SHARED_PREFIX)) { + int slash = domainToken.indexOf('/'); + int i = Integer.parseInt(domainToken.substring(slash + 1)); + + if (i < mVolumes.length) { + return mVolumes[i].getPath(); + } else { + Log.e(TAG, "Could not find volume for " + domainToken); + } } else if (domainToken.equals(FullBackup.NO_BACKUP_TREE_TOKEN)) { return NOBACKUP_DIR.getCanonicalPath(); } @@ -263,6 +276,8 @@ String tokenToDirectoryPath(String domainToken) { SHAREDPREF_DIR = context.getSharedPrefsFile("foo").getParentFile(); CACHE_DIR = context.getCacheDir(); NOBACKUP_DIR = context.getNoBackupFilesDir(); + mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); + mVolumes = mStorageManager.getVolumeList(); if (android.os.Process.myUid() != Process.SYSTEM_UID) { EXTERNAL_DIR = context.getExternalFilesDir(null); } else { diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index 0fce4e2cd1841..a88aa312550dd 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -165,14 +165,18 @@ public void add(UsageStats right) { mPackageName + "' with UsageStats for package '" + right.mPackageName + "'."); } - if (right.mEndTimeStamp > mEndTimeStamp) { + if (right.mBeginTimeStamp > mBeginTimeStamp) { + // The incoming UsageStat begins after this one, so use its last time used fields + // as the source of truth. + // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with + // regards to their mEndTimeStamp. mLastEvent = right.mLastEvent; - mEndTimeStamp = right.mEndTimeStamp; mLastTimeUsed = right.mLastTimeUsed; mBeginIdleTime = right.mBeginIdleTime; mLastTimeSystemUsed = right.mLastTimeSystemUsed; } mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp); + mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp); mTotalTimeInForeground += right.mTotalTimeInForeground; mLaunchCount += right.mLaunchCount; } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 24beba60a9fab..71183d9f561df 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -95,7 +95,7 @@ */ public final class BluetoothAdapter { private static final String TAG = "BluetoothAdapter"; - private static final boolean DBG = true; + private static final boolean DBG = false; private static final boolean VDBG = false; /** @@ -2067,13 +2067,14 @@ public void onBluetoothServiceUp(IBluetooth bluetoothService) { } public void onBluetoothServiceDown() { - if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); + Log.d(TAG, "onBluetoothServiceDown: " + mService); synchronized (mManagerCallback) { mService = null; if (mLeScanClients != null) mLeScanClients.clear(); if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); synchronized (mProxyServiceStateCallbacks) { + Log.d(TAG, "onBluetoothServiceDown: Sending callbacks to " + mProxyServiceStateCallbacks.size() + " clients"); for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ try { if (cb != null) { @@ -2085,6 +2086,7 @@ public void onBluetoothServiceDown() { } } } + Log.d(TAG, "onBluetoothServiceDown: Finished sending callbacks to registered clients"); } public void onBrEdrDown() { diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index e742b2bc06eea..d7d248f650f90 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -25,6 +25,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelUuid; +import android.os.Process; import android.os.RemoteException; import android.util.Log; @@ -823,6 +824,9 @@ public boolean createBond() { return false; } try { + Log.i(TAG, "createBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.createBond(this, TRANSPORT_AUTO); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -854,6 +858,9 @@ public boolean createBond(int transport) { throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport"); } try { + Log.i(TAG, "createBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.createBond(this, transport); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -922,6 +929,9 @@ public boolean cancelBondProcess() { return false; } try { + Log.i(TAG, "cancelBondProcess() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.cancelBondProcess(this); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -943,6 +953,9 @@ public boolean removeBond() { return false; } try { + Log.i(TAG, "removeBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.removeBond(this); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -1153,12 +1166,12 @@ public boolean setPasskey(int passkey) { /** * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing. - *

Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. + *

Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. * * @return true confirmation has been sent out * false for error */ - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPairingConfirmation(boolean confirm) { if (sService == null) { Log.e(TAG, "BT not enabled. Cannot set pairing confirmation"); diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 8d4742b3978dc..da810329aa60e 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -24,6 +24,7 @@ import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import java.util.ArrayList; @@ -302,7 +303,7 @@ boolean doBind() { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + UserHandle.CURRENT_OR_SELF)) { Log.e(TAG, "Could not bind to Bluetooth Headset Service with " + intent); return false; } @@ -708,6 +709,48 @@ public int getAudioState(BluetoothDevice device) { return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; } + /** + * Sets whether audio routing is allowed. When set to {@code false}, the AG will not route any + * audio to the HF unless explicitly told to. + * This method should be used in cases where the SCO channel is shared between multiple profiles + * and must be delegated by a source knowledgeable + * Note: This is an internal function and shouldn't be exposed + * + * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise. + * + * @hide + */ + public void setAudioRouteAllowed(boolean allowed) { + if (VDBG) log("setAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + mService.setAudioRouteAllowed(allowed); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + + /** + * Returns whether audio routing is allowed. see {@link #setAudioRouteAllowed(boolean)}. + * Note: This is an internal function and shouldn't be exposed + * + * @hide + */ + public boolean getAudioRouteAllowed() { + if (VDBG) log("getAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + return mService.getAudioRouteAllowed(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + /** * Check if Bluetooth SCO audio is connected. * diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 10d851fbf5858..484a856539b86 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -1075,6 +1075,41 @@ public int getAudioState(BluetoothDevice device) { return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; } + /** + * Sets whether audio routing is allowed. + * + * Note: This is an internal function and shouldn't be exposed + */ + public void setAudioRouteAllowed(boolean allowed) { + if (VDBG) log("setAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + mService.setAudioRouteAllowed(allowed); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + + /** + * Returns whether audio routing is allowed. + * + * Note: This is an internal function and shouldn't be exposed + */ + public boolean getAudioRouteAllowed() { + if (VDBG) log("getAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + return mService.getAudioRouteAllowed(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + /** * Initiates a connection of audio channel. * diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java index 7b5a045e27f08..002f63f7426eb 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java @@ -19,6 +19,8 @@ import android.os.Parcel; import android.os.Parcelable; +import java.util.UUID; + /** * This class represents a single call, its state and properties. * It implements {@link Parcelable} for inter-process message passing. @@ -67,14 +69,21 @@ public final class BluetoothHeadsetClientCall implements Parcelable { private String mNumber; private boolean mMultiParty; private final boolean mOutgoing; + private final UUID mUUID; /** * Creates BluetoothHeadsetClientCall instance. */ public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number, boolean multiParty, boolean outgoing) { + this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing); + } + + public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state, + String number, boolean multiParty, boolean outgoing) { mDevice = device; mId = id; + mUUID = uuid; mState = state; mNumber = number != null ? number : ""; mMultiParty = multiParty; @@ -133,6 +142,16 @@ public int getId() { return mId; } + /** + * Gets call's UUID. + * + * @return call uuid + * @hide + */ + public UUID getUUID() { + return mUUID; + } + /** * Gets call's current state. * @@ -172,10 +191,16 @@ public boolean isOutgoing() { } public String toString() { + return toString(false); + } + + public String toString(boolean loggable) { StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mDevice: "); - builder.append(mDevice); + builder.append(loggable ? mDevice.hashCode() : mDevice); builder.append(", mId: "); builder.append(mId); + builder.append(", mUUID: "); + builder.append(mUUID); builder.append(", mState: "); switch (mState) { case CALL_STATE_ACTIVE: builder.append("ACTIVE"); break; @@ -189,7 +214,7 @@ public String toString() { default: builder.append(mState); break; } builder.append(", mNumber: "); - builder.append(mNumber); + builder.append(loggable ? mNumber.hashCode() : mNumber); builder.append(", mMultiParty: "); builder.append(mMultiParty); builder.append(", mOutgoing: "); @@ -206,8 +231,8 @@ public String toString() { @Override public BluetoothHeadsetClientCall createFromParcel(Parcel in) { return new BluetoothHeadsetClientCall((BluetoothDevice)in.readParcelable(null), - in.readInt(), in.readInt(), in.readString(), - in.readInt() == 1, in.readInt() == 1); + in.readInt(), UUID.fromString(in.readString()), in.readInt(), + in.readString(), in.readInt() == 1, in.readInt() == 1); } @Override @@ -220,6 +245,7 @@ public BluetoothHeadsetClientCall[] newArray(int size) { public void writeToParcel(Parcel out, int flags) { out.writeParcelable(mDevice, 0); out.writeInt(mId); + out.writeString(mUUID.toString()); out.writeInt(mState); out.writeString(mNumber); out.writeInt(mMultiParty ? 1 : 0); diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl index 0e23fada83178..0bb4088f62c93 100755 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl @@ -50,6 +50,8 @@ interface IBluetoothHeadset { boolean isAudioOn(); boolean connectAudio(); boolean disconnectAudio(); + void setAudioRouteAllowed(boolean allowed); + boolean getAudioRouteAllowed(); boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device); boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device); void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type); diff --git a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl index e518b7d225f85..79ae4e48fa7da 100644 --- a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl @@ -62,6 +62,8 @@ interface IBluetoothHeadsetClient { int getAudioState(in BluetoothDevice device); boolean connectAudio(); boolean disconnectAudio(); + void setAudioRouteAllowed(boolean allowed); + boolean getAudioRouteAllowed(); Bundle getCurrentAgFeatures(in BluetoothDevice device); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index fc40a7317695c..7ddda110bf1bc 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3150,16 +3150,6 @@ public final T getSystemService(Class serviceClass) { */ public static final String BATTERY_SERVICE = "batterymanager"; - /** - * Use with {@link #getSystemService} to retrieve a - * {@link android.content.res.ThemeManager} for accessing theme service. - * - * @see #getSystemService - * @see android.content.res.ThemeManager - * @hide - */ - public static final String THEME_SERVICE = "themes"; - /** * Use with {@link #getSystemService} to retrieve a * {@link android.nfc.NfcManager} for using NFC. diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2a24fe3059a74..c06f98a05ff66 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1604,6 +1604,23 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend public static final String ACTION_GET_PERMISSIONS_COUNT = "android.intent.action.GET_PERMISSIONS_COUNT"; + /** + * Broadcast action that requests list of all apps that have runtime permissions. It will + * respond to the request by sending a broadcast with action defined by + * {@link #EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT}. The response will contain + * {@link #EXTRA_GET_PERMISSIONS_APP_LIST_RESULT}, as well as + * {@link #EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT}, with contents described below or + * a null upon failure. + * + *

{@link #EXTRA_GET_PERMISSIONS_APP_LIST_RESULT} will contain a list of package names of + * apps that have runtime permissions. {@link #EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT} + * will contain the list of app labels corresponding ot the apps in the first list. + * + * @hide + */ + public static final String ACTION_GET_PERMISSIONS_PACKAGES + = "android.intent.action.GET_PERMISSIONS_PACKAGES"; + /** * Extra included in response to {@link #ACTION_GET_PERMISSIONS_COUNT}. * @hide @@ -1618,6 +1635,28 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend public static final String EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT = "android.intent.extra.GET_PERMISSIONS_GROUP_LIST_RESULT"; + /** + * String list of apps that have one or more runtime permissions. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_APP_LIST_RESULT + = "android.intent.extra.GET_PERMISSIONS_APP_LIST_RESULT"; + + /** + * String list of app labels for apps that have one or more runtime permissions. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT + = "android.intent.extra.GET_PERMISSIONS_APP_LABEL_LIST_RESULT"; + + /** + * Boolean list describing if the app is a system app for apps that have one or more runtime + * permissions. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT + = "android.intent.extra.GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT"; + /** * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_COUNT} broadcasts. * @hide @@ -1625,6 +1664,13 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend public static final String EXTRA_GET_PERMISSIONS_RESPONSE_INTENT = "android.intent.extra.GET_PERMISSIONS_RESONSE_INTENT"; + /** + * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_PACKAGES} broadcasts. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT + = "android.intent.extra.GET_PERMISSIONS_PACKAGES_RESONSE_INTENT"; + /** * Activity action: Launch UI to manage which apps have a given permission. *

@@ -2880,21 +2926,6 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend public static final String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK"; - /** - * Broadcast Action: Indicate that unrecoverable error happened during app launch. - * Could indicate that curently applied theme is malicious. - * @hide - */ - public static final String ACTION_APP_FAILURE = - "com.tmobile.intent.action.APP_FAILURE"; - - /** - * Broadcast Action: Request to reset the unrecoverable errors count to 0. - * @hide - */ - public static final String ACTION_APP_FAILURE_RESET = - "com.tmobile.intent.action.APP_FAILURE_RESET"; - /** * Activity Action: Shows the brightness setting dialog. * @hide @@ -3081,6 +3112,39 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend public static final String ACTION_DOZE_PULSE_STARTING = "android.intent.action.DOZE_PULSE_STARTING"; + /** + * Broadcast action: reports when a new thermal event has been reached. When the device + * is reaching its maximum temperatue, the thermal level reported + * {@hide} + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_THERMAL_EVENT = "android.intent.action.THERMAL_EVENT"; + + /** {@hide} */ + public static final String EXTRA_THERMAL_STATE = "android.intent.extra.THERMAL_STATE"; + + /** + * Thermal state when the device is normal. This state is sent in the + * {@link ACTION_THERMAL_EVENT} broadcast as {@link EXTRA_THERMAL_STATE}. + * {@hide} + */ + public static final int EXTRA_THERMAL_STATE_NORMAL = 0; + + /** + * Thermal state where the device is approaching its maximum threshold. This state is sent in + * the {@link ACTION_THERMAL_EVENT} broadcast as {@link EXTRA_THERMAL_STATE}. + * {@hide} + */ + public static final int EXTRA_THERMAL_STATE_WARNING = 1; + + /** + * Thermal state where the device has reached its maximum threshold. This state is sent in the + * {@link ACTION_THERMAL_EVENT} broadcast as {@link EXTRA_THERMAL_STATE}. + * {@hide} + */ + public static final int EXTRA_THERMAL_STATE_EXCEEDED = 2; + + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). @@ -3182,6 +3246,13 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_HOME = "android.intent.category.HOME"; + /** + * This is the home activity that is displayed when the device is finished setting up and ready + * for use. + * @hide + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String CATEGORY_HOME_MAIN = "android.intent.category.HOME_MAIN"; /** * This is the setup wizard activity, that is the first activity that is displayed * when the user sets up the device for the first time. @@ -3282,14 +3353,6 @@ public static Intent createChooser(Intent target, CharSequence title, IntentSend @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE"; - /** - * Used to indicate that a theme package has been installed or un-installed. - * - * @hide - */ - public static final String CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE = - "com.tmobile.intent.category.THEME_PACKAGE_INSTALL_STATE_CHANGE"; - // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Application launch intent categories (see addCategory()). diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 3a17e23b0547a..ed5dfa5393ecb 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -883,6 +883,15 @@ public boolean match(AuthorityEntry other) { return true; } + @Override + public boolean equals(Object obj) { + if (obj instanceof AuthorityEntry) { + final AuthorityEntry other = (AuthorityEntry)obj; + return match(other); + } + return false; + } + /** * Determine whether this AuthorityEntry matches the given data Uri. * Note that this comparison is case-sensitive, unlike formal @@ -917,7 +926,7 @@ public int match(Uri data) { } return MATCH_CATEGORY_HOST; } - }; + } /** * Add a new Intent data "scheme specific part" to match against. The filter must diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java index a586d6fc96ae9..ab3c30bb2d2a3 100644 --- a/core/java/android/content/SyncInfo.java +++ b/core/java/android/content/SyncInfo.java @@ -24,6 +24,13 @@ * Information about the sync operation that is currently underway. */ public class SyncInfo implements Parcelable { + /** + * Used when the caller receiving this object doesn't have permission to access the accounts + * on device. + * @See Manifest.permission.GET_ACCOUNTS + */ + private static final Account REDACTED_ACCOUNT = new Account("*****", "*****"); + /** @hide */ public final int authorityId; @@ -44,6 +51,17 @@ public class SyncInfo implements Parcelable { */ public final long startTime; + /** + * Creates a SyncInfo object with an unusable Account. Used when the caller receiving this + * object doesn't have access to the accounts on the device. + * @See Manifest.permission.GET_ACCOUNTS + * @hide + */ + public static SyncInfo createAccountRedacted( + int authorityId, String authority, long startTime) { + return new SyncInfo(authorityId, REDACTED_ACCOUNT, authority, startTime); + } + /** @hide */ public SyncInfo(int authorityId, Account account, String authority, long startTime) { this.authorityId = authorityId; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 7c77f543bf1a5..51f13affddeb5 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -519,4 +519,11 @@ interface IPackageManager { void updateIconMapping(String pkgName); ComposedIconInfo getComposedIconInfo(); int processThemeResources(String themePkgName); + + /** Protected Apps */ + boolean isComponentProtected(in String callingPackage, in int callingUid, + in ComponentName componentName, int userId); + + /** protected broadcast ext */ + boolean isProtectedBroadcastAllowed(in String actionName, in int callingUid); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 8928ad30b3958..8f0500e9b8513 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4560,6 +4560,13 @@ public void onCreated(int moveId, Bundle extras) {} */ public abstract void setComponentProtectedSetting(ComponentName componentName, boolean newState); + /** + * Return whether or not a specific component is protected + * @hide + */ + public abstract boolean isComponentProtected(String callingPackage, int callingUid, + ComponentName componentName); + /** * Adds a {@link CrossProfileIntentFilter}. After calling this method all intents sent from the * user with id sourceUserId can also be be resolved by activities in the user with id diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index dba6d56a0b0df..bb46ef0b4d14c 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1133,6 +1133,7 @@ private boolean packageHasIconPack(File originalFile) { */ public void collectManifestDigest(Package pkg) throws PackageParserException { pkg.manifestDigest = null; + pkg.manifestHashCode = 0; // TODO: extend to gather digest for split APKs try { @@ -1141,7 +1142,7 @@ public void collectManifestDigest(Package pkg) throws PackageParserException { final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME); if (je != null) { pkg.manifestDigest = ManifestDigest.fromInputStream(jarFile.getInputStream(je)); - pkg.manifestHashCode = ThemeUtils.getPackageHashCode(pkg); + pkg.manifestHashCode = ThemeUtils.getPackageHashCode(pkg, jarFile); } } finally { jarFile.close(); @@ -1876,14 +1877,18 @@ private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags, String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); + String permission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_permission); + sa.recycle(); if (name != null && (flags&PARSE_IS_SYSTEM) != 0) { if (pkg.protectedBroadcasts == null) { - pkg.protectedBroadcasts = new ArrayList(); + pkg.protectedBroadcasts = new ArrayMap<>(); } - if (!pkg.protectedBroadcasts.contains(name)) { - pkg.protectedBroadcasts.add(name.intern()); + if (!pkg.protectedBroadcasts.containsKey(name)) { + pkg.protectedBroadcasts.put(name.intern(), + permission != null ? permission.intern() : null); } } @@ -4518,7 +4523,10 @@ public final static class Package { public final ArrayList requestedPermissions = new ArrayList(); - public ArrayList protectedBroadcasts; + /** + * Maps from package -> permission, null for system (default behavior) + */ + public ArrayMap protectedBroadcasts; public ArrayList libraryNames = null; public ArrayList usesLibraries = null; diff --git a/core/java/android/content/pm/ThemeUtils.java b/core/java/android/content/pm/ThemeUtils.java index 357b372a42b27..07e73b544420a 100644 --- a/core/java/android/content/pm/ThemeUtils.java +++ b/core/java/android/content/pm/ThemeUtils.java @@ -15,111 +15,31 @@ */ package android.content.pm; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.IntentFilter; -import android.content.res.AssetManager; -import android.content.res.Configuration; import android.content.res.ThemeConfig; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.media.RingtoneManager; -import android.net.Uri; -import android.os.FileUtils; -import android.os.SystemProperties; -import android.provider.MediaStore; -import android.provider.Settings; -import android.provider.ThemesContract; -import android.provider.ThemesContract.ThemesColumns; import android.text.TextUtils; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.WindowManager; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.InputStreamReader; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.CRC32; +import java.util.jar.StrictJarFile; import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import static android.content.res.ThemeConfig.SYSTEM_DEFAULT; /** * @hide */ public class ThemeUtils { - private static final String TAG = "ThemeUtils"; + private static final String TAG = ThemeUtils.class.getSimpleName(); /* Path inside a theme APK to the overlay folder */ public static final String OVERLAY_PATH = "assets/overlays/"; public static final String ICONS_PATH = "assets/icons/"; public static final String COMMON_RES_PATH = "assets/overlays/common/"; - public static final String FONT_XML = "fonts.xml"; public static final String RESOURCE_CACHE_DIR = "/data/resource-cache/"; - public static final String IDMAP_SUFFIX = "@idmap"; - public static final String COMMON_RES_SUFFIX = ".common"; public static final String COMMON_RES_TARGET = "common"; - public static final String ICON_HASH_FILENAME = "hash"; - - // path to external theme resources, i.e. bootanimation.zip - public static final String SYSTEM_THEME_PATH = "/data/system/theme"; - public static final String SYSTEM_THEME_FONT_PATH = SYSTEM_THEME_PATH + File.separator + "fonts"; - public static final String SYSTEM_THEME_RINGTONE_PATH = SYSTEM_THEME_PATH - + File.separator + "ringtones"; - public static final String SYSTEM_THEME_NOTIFICATION_PATH = SYSTEM_THEME_PATH - + File.separator + "notifications"; - public static final String SYSTEM_THEME_ALARM_PATH = SYSTEM_THEME_PATH - + File.separator + "alarms"; - public static final String SYSTEM_THEME_ICON_CACHE_DIR = SYSTEM_THEME_PATH - + File.separator + "icons"; - // internal path to bootanimation.zip inside theme apk - public static final String THEME_BOOTANIMATION_PATH = "assets/bootanimation/bootanimation.zip"; - - public static final String SYSTEM_MEDIA_PATH = "/system/media/audio"; - public static final String SYSTEM_ALARMS_PATH = SYSTEM_MEDIA_PATH + File.separator - + "alarms"; - public static final String SYSTEM_RINGTONES_PATH = SYSTEM_MEDIA_PATH + File.separator - + "ringtones"; - public static final String SYSTEM_NOTIFICATIONS_PATH = SYSTEM_MEDIA_PATH + File.separator - + "notifications"; - - // path to asset lockscreen and wallpapers directory - public static final String LOCKSCREEN_WALLPAPER_PATH = "lockscreen"; - public static final String WALLPAPER_PATH = "wallpapers"; - - private static final String MEDIA_CONTENT_URI = "content://media/internal/audio/media"; - - // Constants for theme change broadcast - public static final String ACTION_THEME_CHANGED = "org.cyanogenmod.intent.action.THEME_CHANGED"; - public static final String CATEGORY_THEME_COMPONENT_PREFIX = "org.cyanogenmod.intent.category."; - public static final String EXTRA_COMPONENTS = "components"; - public static final String EXTRA_REQUEST_TYPE = "request_type"; - public static final String EXTRA_UPDATE_TIME = "update_time"; - - public static final int SYSTEM_TARGET_API = 0; // Package name for any app which does not have a specific theme applied private static final String DEFAULT_PKG = "default"; - private static final String SETTINGS_DB = - "/data/data/com.android.providers.settings/databases/settings.db"; - private static final String SETTINGS_SECURE_TABLE = "secure"; + private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; /** * IDMAP hash version code used to alter the resulting hash and force recreating @@ -154,18 +74,10 @@ public static String getOverlayResourceCacheDir(String themePkgName) { /** * Get the path of the resource cache for the given target and theme - * @param targetPkgName - * @param themePkg + * @param targetPkgName Target app package name + * @param themePkgName Theme package name * @return Path to the resource cache for this target and theme */ - public static String getTargetCacheDir(String targetPkgName, PackageInfo themePkg) { - return getTargetCacheDir(targetPkgName, themePkg.packageName); - } - - public static String getTargetCacheDir(String targetPkgName, PackageParser.Package themePkg) { - return getTargetCacheDir(targetPkgName, themePkg.packageName); - } - public static String getTargetCacheDir(String targetPkgName, String themePkgName) { return getOverlayResourceCacheDir(themePkgName) + File.separator + targetPkgName; } @@ -179,18 +91,10 @@ public static String getIconPackDir(String pkgName) { return getOverlayResourceCacheDir(pkgName) + File.separator + "icons"; } - public static String getIconHashFile(String pkgName) { - return getIconPackDir(pkgName) + File.separator + ICON_HASH_FILENAME; - } - public static String getIconPackApkPath(String pkgName) { return getIconPackDir(pkgName) + "/resources.apk"; } - public static String getIconPackResPath(String pkgName) { - return getIconPackDir(pkgName) + "/resources.arsc"; - } - public static String getIdmapPath(String targetPkgName, String overlayPkgName) { return getTargetCacheDir(targetPkgName, overlayPkgName) + File.separator + "idmap"; } @@ -209,507 +113,6 @@ public static String getCommonPackageName(String themePackageName) { return COMMON_RES_TARGET; } - public static void createCacheDirIfNotExists() throws IOException { - File file = new File(RESOURCE_CACHE_DIR); - if (!file.exists() && !file.mkdir()) { - throw new IOException("Could not create dir: " + file.toString()); - } - FileUtils.setPermissions(file, FileUtils.S_IRWXU - | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - - public static void createResourcesDirIfNotExists(String targetPkgName, String overlayPkgName) - throws IOException { - createDirIfNotExists(getOverlayResourceCacheDir(overlayPkgName)); - File file = new File(getTargetCacheDir(targetPkgName, overlayPkgName)); - if (!file.exists() && !file.mkdir()) { - throw new IOException("Could not create dir: " + file.toString()); - } - FileUtils.setPermissions(file, FileUtils.S_IRWXU - | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - - public static void createIconDirIfNotExists(String pkgName) throws IOException { - createDirIfNotExists(getOverlayResourceCacheDir(pkgName)); - File file = new File(getIconPackDir(pkgName)); - if (!file.exists() && !file.mkdir()) { - throw new IOException("Could not create dir: " + file.toString()); - } - FileUtils.setPermissions(file, FileUtils.S_IRWXU - | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - - private static boolean dirExists(String dirPath) { - final File dir = new File(dirPath); - return dir.exists() && dir.isDirectory(); - } - - private static void createDirIfNotExists(String dirPath) { - if (!dirExists(dirPath)) { - File dir = new File(dirPath); - if (dir.mkdir()) { - FileUtils.setPermissions(dir, FileUtils.S_IRWXU | - FileUtils.S_IRWXG| FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - } - } - - /** - * Create SYSTEM_THEME_PATH directory if it does not exist - */ - public static void createThemeDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_PATH); - } - - /** - * Create SYSTEM_FONT_PATH directory if it does not exist - */ - public static void createFontDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_FONT_PATH); - } - - /** - * Create SYSTEM_THEME_RINGTONE_PATH directory if it does not exist - */ - public static void createRingtoneDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_RINGTONE_PATH); - } - - /** - * Create SYSTEM_THEME_NOTIFICATION_PATH directory if it does not exist - */ - public static void createNotificationDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_NOTIFICATION_PATH); - } - - /** - * Create SYSTEM_THEME_ALARM_PATH directory if it does not exist - */ - public static void createAlarmDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_ALARM_PATH); - } - - /** - * Create SYSTEM_THEME_ICON_CACHE_DIR directory if it does not exist - */ - public static void createIconCacheDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_ICON_CACHE_DIR); - } - - public static void clearIconCache() { - FileUtils.deleteContents(new File(SYSTEM_THEME_ICON_CACHE_DIR)); - } - - public static InputStream getInputStreamFromAsset(Context ctx, String path) throws IOException { - if (ctx == null || path == null) - return null; - InputStream is = null; - String ASSET_BASE = "file:///android_asset/"; - path = path.substring(ASSET_BASE.length()); - AssetManager assets = ctx.getAssets(); - is = assets.open(path); - return is; - } - - public static void closeQuietly(InputStream stream) { - if (stream == null) - return; - try { - stream.close(); - } catch (IOException e) { - } - } - - public static void closeQuietly(OutputStream stream) { - if (stream == null) - return; - try { - stream.close(); - } catch (IOException e) { - } - } - - /** - * Scale the boot animation to better fit the device by editing the desc.txt found - * in the bootanimation.zip - * @param context Context to use for getting an instance of the WindowManager - * @param input InputStream of the original bootanimation.zip - * @param dst Path to store the newly created bootanimation.zip - * @throws IOException - */ - public static void copyAndScaleBootAnimation(Context context, InputStream input, String dst) - throws IOException { - final OutputStream os = new FileOutputStream(dst); - final ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(os)); - final ZipInputStream bootAni = new ZipInputStream(new BufferedInputStream(input)); - ZipEntry ze; - - zos.setMethod(ZipOutputStream.STORED); - final byte[] bytes = new byte[4096]; - int len; - while ((ze = bootAni.getNextEntry()) != null) { - ZipEntry entry = new ZipEntry(ze.getName()); - entry.setMethod(ZipEntry.STORED); - entry.setCrc(ze.getCrc()); - entry.setSize(ze.getSize()); - entry.setCompressedSize(ze.getSize()); - if (!ze.getName().equals("desc.txt")) { - // just copy this entry straight over into the output zip - zos.putNextEntry(entry); - while ((len = bootAni.read(bytes)) > 0) { - zos.write(bytes, 0, len); - } - } else { - String line; - BufferedReader reader = new BufferedReader(new InputStreamReader(bootAni)); - final String[] info = reader.readLine().split(" "); - - int scaledWidth; - int scaledHeight; - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - DisplayMetrics dm = new DisplayMetrics(); - wm.getDefaultDisplay().getRealMetrics(dm); - // just in case the device is in landscape orientation we will - // swap the values since most (if not all) animations are portrait - if (dm.widthPixels > dm.heightPixels) { - scaledWidth = dm.heightPixels; - scaledHeight = dm.widthPixels; - } else { - scaledWidth = dm.widthPixels; - scaledHeight = dm.heightPixels; - } - - int width = Integer.parseInt(info[0]); - int height = Integer.parseInt(info[1]); - - if (width == height) - scaledHeight = scaledWidth; - else { - // adjust scaledHeight to retain original aspect ratio - float scale = (float)scaledWidth / (float)width; - int newHeight = (int)((float)height * scale); - if (newHeight < scaledHeight) - scaledHeight = newHeight; - } - - CRC32 crc32 = new CRC32(); - int size = 0; - ByteBuffer buffer = ByteBuffer.wrap(bytes); - line = String.format("%d %d %s\n", scaledWidth, scaledHeight, info[2]); - buffer.put(line.getBytes()); - size += line.getBytes().length; - crc32.update(line.getBytes()); - while ((line = reader.readLine()) != null) { - line = String.format("%s\n", line); - buffer.put(line.getBytes()); - size += line.getBytes().length; - crc32.update(line.getBytes()); - } - entry.setCrc(crc32.getValue()); - entry.setSize(size); - entry.setCompressedSize(size); - zos.putNextEntry(entry); - zos.write(buffer.array(), 0, size); - } - zos.closeEntry(); - } - zos.close(); - } - - public static boolean isValidAudible(String fileName) { - return (fileName != null && - (fileName.endsWith(".mp3") || fileName.endsWith(".ogg"))); - } - - public static boolean setAudible(Context context, File ringtone, int type, String name) { - final String path = ringtone.getAbsolutePath(); - final String mimeType = name.endsWith(".ogg") ? "audio/ogg" : "audio/mp3"; - ContentValues values = new ContentValues(); - values.put(MediaStore.MediaColumns.DATA, path); - values.put(MediaStore.MediaColumns.TITLE, name); - values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType); - values.put(MediaStore.MediaColumns.SIZE, ringtone.length()); - values.put(MediaStore.Audio.Media.IS_RINGTONE, type == RingtoneManager.TYPE_RINGTONE); - values.put(MediaStore.Audio.Media.IS_NOTIFICATION, - type == RingtoneManager.TYPE_NOTIFICATION); - values.put(MediaStore.Audio.Media.IS_ALARM, type == RingtoneManager.TYPE_ALARM); - values.put(MediaStore.Audio.Media.IS_MUSIC, false); - - Uri uri = MediaStore.Audio.Media.getContentUriForPath(path); - Uri newUri = null; - Cursor c = context.getContentResolver().query(uri, - new String[] {MediaStore.MediaColumns._ID}, - MediaStore.MediaColumns.DATA + "='" + path + "'", - null, null); - if (c != null && c.getCount() > 0) { - c.moveToFirst(); - long id = c.getLong(0); - c.close(); - newUri = Uri.withAppendedPath(Uri.parse(MEDIA_CONTENT_URI), "" + id); - context.getContentResolver().update(uri, values, - MediaStore.MediaColumns._ID + "=" + id, null); - } - if (newUri == null) - newUri = context.getContentResolver().insert(uri, values); - try { - RingtoneManager.setActualDefaultRingtoneUri(context, type, newUri); - } catch (Exception e) { - return false; - } - return true; - } - - public static boolean setDefaultAudible(Context context, int type) { - final String audiblePath = getDefaultAudiblePath(type); - if (audiblePath != null) { - Uri uri = MediaStore.Audio.Media.getContentUriForPath(audiblePath); - Cursor c = context.getContentResolver().query(uri, - new String[] {MediaStore.MediaColumns._ID}, - MediaStore.MediaColumns.DATA + "='" + audiblePath + "'", - null, null); - if (c != null && c.getCount() > 0) { - c.moveToFirst(); - long id = c.getLong(0); - c.close(); - uri = Uri.withAppendedPath( - Uri.parse(MEDIA_CONTENT_URI), "" + id); - } - if (uri != null) - RingtoneManager.setActualDefaultRingtoneUri(context, type, uri); - } else { - return false; - } - return true; - } - - public static String getDefaultAudiblePath(int type) { - final String name; - final String path; - switch (type) { - case RingtoneManager.TYPE_ALARM: - name = SystemProperties.get("ro.config.alarm_alert", null); - path = name != null ? SYSTEM_ALARMS_PATH + File.separator + name : null; - break; - case RingtoneManager.TYPE_NOTIFICATION: - name = SystemProperties.get("ro.config.notification_sound", null); - path = name != null ? SYSTEM_NOTIFICATIONS_PATH + File.separator + name : null; - break; - case RingtoneManager.TYPE_RINGTONE: - name = SystemProperties.get("ro.config.ringtone", null); - path = name != null ? SYSTEM_RINGTONES_PATH + File.separator + name : null; - break; - default: - path = null; - break; - } - return path; - } - - public static void clearAudibles(Context context, String audiblePath) { - final File audibleDir = new File(audiblePath); - if (audibleDir.exists()) { - String[] files = audibleDir.list(); - final ContentResolver resolver = context.getContentResolver(); - for (String s : files) { - final String filePath = audiblePath + File.separator + s; - Uri uri = MediaStore.Audio.Media.getContentUriForPath(filePath); - resolver.delete(uri, MediaStore.MediaColumns.DATA + "=\"" - + filePath + "\"", null); - (new File(filePath)).delete(); - } - } - } - - public static Context createUiContext(final Context context) { - try { - Context uiContext = context.createPackageContext("com.android.systemui", - Context.CONTEXT_RESTRICTED); - return new ThemedUiContext(uiContext, context.getApplicationContext()); - } catch (PackageManager.NameNotFoundException e) { - } - - return null; - } - - public static void registerThemeChangeReceiver(final Context context, - final BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter(ACTION_THEME_CHANGED); - - context.registerReceiver(receiver, filter); - } - - public static String getLockscreenWallpaperPath(AssetManager assetManager) throws IOException { - String[] assets = assetManager.list(LOCKSCREEN_WALLPAPER_PATH); - String asset = getFirstNonEmptyAsset(assets); - if (asset == null) return null; - return LOCKSCREEN_WALLPAPER_PATH + File.separator + asset; - } - - public static String getWallpaperPath(AssetManager assetManager) throws IOException { - String[] assets = assetManager.list(WALLPAPER_PATH); - String asset = getFirstNonEmptyAsset(assets); - if (asset == null) return null; - return WALLPAPER_PATH + File.separator + asset; - } - - public static List getWallpaperPathList(AssetManager assetManager) - throws IOException { - List wallpaperList = new ArrayList(); - String[] assets = assetManager.list(WALLPAPER_PATH); - for (String asset : assets) { - if (!TextUtils.isEmpty(asset)) { - wallpaperList.add(WALLPAPER_PATH + File.separator + asset); - } - } - return wallpaperList; - } - - // Returns the first non-empty asset name. Empty assets can occur if the APK is built - // with folders included as zip entries in the APK. Searching for files inside "folderName" via - // assetManager.list("folderName") can cause these entries to be included as empty strings. - private static String getFirstNonEmptyAsset(String[] assets) { - if (assets == null) return null; - String filename = null; - for(String asset : assets) { - if (!TextUtils.isEmpty(asset)) { - filename = asset; - break; - } - } - return filename; - } - - public static String getDefaultThemePackageName(Context context) { - final String defaultThemePkg = Settings.Secure.getString(context.getContentResolver(), - Settings.Secure.DEFAULT_THEME_PACKAGE); - if (!TextUtils.isEmpty(defaultThemePkg)) { - PackageManager pm = context.getPackageManager(); - try { - if (pm.getPackageInfo(defaultThemePkg, 0) != null) { - return defaultThemePkg; - } - } catch (PackageManager.NameNotFoundException e) { - // doesn't exist so system will be default - Log.w(TAG, "Default theme " + defaultThemePkg + " not found", e); - } - } - - return SYSTEM_DEFAULT; - } - - private static class ThemedUiContext extends ContextWrapper { - private Context mAppContext; - - public ThemedUiContext(Context context, Context appContext) { - super(context); - mAppContext = appContext; - } - - @Override - public Context getApplicationContext() { - return mAppContext; - } - - @Override - public String getPackageName() { - return mAppContext.getPackageName(); - } - } - - // Returns a mutable list of all theme components - public static List getAllComponents() { - List components = new ArrayList(9); - components.add(ThemesColumns.MODIFIES_FONTS); - components.add(ThemesColumns.MODIFIES_LAUNCHER); - components.add(ThemesColumns.MODIFIES_ALARMS); - components.add(ThemesColumns.MODIFIES_BOOT_ANIM); - components.add(ThemesColumns.MODIFIES_ICONS); - components.add(ThemesColumns.MODIFIES_LOCKSCREEN); - components.add(ThemesColumns.MODIFIES_NOTIFICATIONS); - components.add(ThemesColumns.MODIFIES_OVERLAYS); - components.add(ThemesColumns.MODIFIES_RINGTONES); - components.add(ThemesColumns.MODIFIES_STATUS_BAR); - components.add(ThemesColumns.MODIFIES_NAVIGATION_BAR); - components.add(ThemesColumns.MODIFIES_LIVE_LOCK_SCREEN); - return components; - } - - /** - * Returns a mutable list of all the theme components supported by a given package - * NOTE: This queries the themes content provider. If there isn't a provider installed - * or if it is too early in the boot process this method will not work. - */ - public static List getSupportedComponents(Context context, String pkgName) { - List supportedComponents = new ArrayList(); - - String selection = ThemesContract.ThemesColumns.PKG_NAME + "= ?"; - String[] selectionArgs = new String[]{ pkgName }; - Cursor c = context.getContentResolver().query(ThemesContract.ThemesColumns.CONTENT_URI, - null, selection, selectionArgs, null); - - if (c != null) { - if (c.moveToFirst()) { - List allComponents = getAllComponents(); - for (String component : allComponents) { - int index = c.getColumnIndex(component); - if (c.getInt(index) == 1) { - supportedComponents.add(component); - } - } - } - c.close(); - } - return supportedComponents; - } - - /** - * Get the components from the default theme. If the default theme is not SYSTEM then any - * components that are not in the default theme will come from SYSTEM to create a complete - * component map. - * @param context - * @return - */ - public static Map getDefaultComponents(Context context) { - String defaultThemePkg = getDefaultThemePackageName(context); - List defaultComponents = null; - List systemComponents = getSupportedComponents(context, SYSTEM_DEFAULT); - if (!SYSTEM_DEFAULT.equals(defaultThemePkg)) { - defaultComponents = getSupportedComponents(context, defaultThemePkg); - } - - Map componentMap = new HashMap(systemComponents.size()); - if (defaultComponents != null) { - for (String component : defaultComponents) { - componentMap.put(component, defaultThemePkg); - } - } - for (String component : systemComponents) { - if (!componentMap.containsKey(component)) { - componentMap.put(component, SYSTEM_DEFAULT); - } - } - - return componentMap; - } - - /** - * Takes an existing component map and adds any missing components from the default - * map of components. - * @param context - * @param componentMap An existing component map - */ - public static void completeComponentMap(Context context, - Map componentMap) { - if (componentMap == null) return; - - Map defaultComponents = getDefaultComponents(context); - for (String component : defaultComponents.keySet()) { - if (!componentMap.containsKey(component)) { - componentMap.put(component, defaultComponents.get(component)); - } - } - } - /** * Convenience method to determine if a theme component is a per app theme and not a standard * component. @@ -727,8 +130,24 @@ public static boolean isPerAppThemeComponent(String component) { * @param pkg * @return */ - public static int getPackageHashCode(PackageParser.Package pkg) { + public static int getPackageHashCode(PackageParser.Package pkg, StrictJarFile jarFile) { int hash = pkg.manifestDigest != null ? pkg.manifestDigest.hashCode() : 0; + final ZipEntry je = jarFile.findEntry(MANIFEST_NAME); + if (je != null) { + try { + try { + ManifestDigest digest = ManifestDigest.fromInputStream( + jarFile.getInputStream(je)); + if (digest != null) { + hash += digest.hashCode(); + } + } finally { + jarFile.close(); + } + } catch (IOException | RuntimeException e) { + // Failed to generate digest from manifest.mf + } + } hash = 31 * hash + IDMAP_HASH_VERSION; return hash; } diff --git a/core/java/android/content/res/IThemeService.aidl b/core/java/android/content/res/IThemeService.aidl deleted file mode 100644 index 90cb9fb0f502f..0000000000000 --- a/core/java/android/content/res/IThemeService.aidl +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -import android.content.res.IThemeChangeListener; -import android.content.res.IThemeProcessingListener; -import android.content.res.ThemeChangeRequest; -import android.graphics.Bitmap; - -import java.util.Map; - -/** {@hide} */ -interface IThemeService { - void requestThemeChangeUpdates(in IThemeChangeListener listener); - void removeUpdates(in IThemeChangeListener listener); - - void requestThemeChange(in ThemeChangeRequest request, boolean removePerAppThemes); - void applyDefaultTheme(); - boolean isThemeApplying(); - int getProgress(); - - boolean cacheComposedIcon(in Bitmap icon, String path); - - boolean processThemeResources(String themePkgName); - boolean isThemeBeingProcessed(String themePkgName); - void registerThemeProcessingListener(in IThemeProcessingListener listener); - void unregisterThemeProcessingListener(in IThemeProcessingListener listener); - - void rebuildResourceCache(); -} diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 85ecc0a07eda2..7fa04f9ec947d 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -120,6 +120,8 @@ public class Resources { public static final int THEME_APP_PKG_ID = 0x61; /** @hide */ public static final int THEME_ICON_PKG_ID = 0x62; + /** @hide */ + public static final int THEME_CM_PKG_ID = 0x63; /** * The common resource pkg id needs to be less than the THEME_FRAMEWORK_PKG_ID * otherwise aapt will complain and fail @@ -1554,10 +1556,12 @@ public final class Theme { * if not already defined in the theme. */ public void applyStyle(int resId, boolean force) { - AssetManager.applyThemeStyle(mTheme, resId, force); + synchronized (mKey) { + AssetManager.applyThemeStyle(mTheme, resId, force); - mThemeResId = resId; - mKey.append(resId, force); + mThemeResId = resId; + mKey.append(resId, force); + } } /** @@ -1570,10 +1574,14 @@ public void applyStyle(int resId, boolean force) { * @param other The existing Theme to copy from. */ public void setTo(Theme other) { - AssetManager.copyTheme(mTheme, other.mTheme); + synchronized (mKey) { + synchronized (other.mKey) { + AssetManager.copyTheme(mTheme, other.mTheme); - mThemeResId = other.mThemeResId; - mKey.setTo(other.getKey()); + mThemeResId = other.mThemeResId; + mKey.setTo(other.getKey()); + } + } } /** @@ -1596,11 +1604,13 @@ public void setTo(Theme other) { * @see #obtainStyledAttributes(AttributeSet, int[], int, int) */ public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { - final int len = attrs.length; - final TypedArray array = TypedArray.obtain(Resources.this, len); - array.mTheme = this; - AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices); - return array; + synchronized (mKey) { + final int len = attrs.length; + final TypedArray array = TypedArray.obtain(Resources.this, len); + array.mTheme = this; + AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices); + return array; + } } /** @@ -1610,7 +1620,7 @@ public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { *

Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done * with the array. * - * @param resid The desired style resource. + * @param resId The desired style resource. * @param attrs The desired attributes in the style. * * @throws NotFoundException Throws NotFoundException if the given ID does not exist. @@ -1623,39 +1633,15 @@ public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { * @see #obtainStyledAttributes(int[]) * @see #obtainStyledAttributes(AttributeSet, int[], int, int) */ - public TypedArray obtainStyledAttributes(@StyleRes int resid, @StyleableRes int[] attrs) + public TypedArray obtainStyledAttributes(@StyleRes int resId, @StyleableRes int[] attrs) throws NotFoundException { - final int len = attrs.length; - final TypedArray array = TypedArray.obtain(Resources.this, len); - array.mTheme = this; - if (false) { - int[] data = array.mData; - - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("Attributes:"); - String s = " Attrs:"; - int i; - for (i=0; ioutValue is valid, else false. */ public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) { - boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs); - if (false) { - System.out.println( - "resolveAttribute #" + Integer.toHexString(resid) - + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type) - + ", data=0x" + Integer.toHexString(outValue.data)); + synchronized (mKey) { + return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs); } - return got; } /** @@ -1855,8 +1811,11 @@ public Drawable getDrawable(@DrawableRes int id) throws NotFoundException { * @see ActivityInfo */ public int getChangingConfigurations() { - final int nativeChangingConfig = AssetManager.getThemeChangingConfigurations(mTheme); - return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig); + synchronized (mKey) { + final int nativeChangingConfig = + AssetManager.getThemeChangingConfigurations(mTheme); + return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig); + } } /** @@ -1867,7 +1826,9 @@ public int getChangingConfigurations() { * @param prefix Text to prefix each line printed. */ public void dump(int priority, String tag, String prefix) { - AssetManager.dumpTheme(mTheme, priority, tag, prefix); + synchronized (mKey) { + AssetManager.dumpTheme(mTheme, priority, tag, prefix); + } } @Override @@ -1917,19 +1878,21 @@ private String getResourceNameFromHexString(String hexString) { */ @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true) public String[] getTheme() { - final int N = mKey.mCount; - final String[] themes = new String[N * 2]; - for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) { - final int resId = mKey.mResId[j]; - final boolean forced = mKey.mForce[j]; - try { - themes[i] = getResourceName(resId); - } catch (NotFoundException e) { - themes[i] = Integer.toHexString(i); + synchronized (mKey) { + final int N = mKey.mCount; + final String[] themes = new String[N * 2]; + for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) { + final int resId = mKey.mResId[j]; + final boolean forced = mKey.mForce[j]; + try { + themes[i] = getResourceName(resId); + } catch (NotFoundException e) { + themes[i] = Integer.toHexString(i); + } + themes[i + 1] = forced ? "forced" : "not forced"; } - themes[i + 1] = forced ? "forced" : "not forced"; + return themes; } - return themes; } /** @hide */ @@ -1950,13 +1913,15 @@ public void encode(@NonNull ViewHierarchyEncoder encoder) { * @hide */ public void rebase() { - AssetManager.clearTheme(mTheme); - - // Reapply the same styles in the same order. - for (int i = 0; i < mKey.mCount; i++) { - final int resId = mKey.mResId[i]; - final boolean force = mKey.mForce[i]; - AssetManager.applyThemeStyle(mTheme, resId, force); + synchronized (mKey) { + AssetManager.clearTheme(mTheme); + + // Reapply the same styles in the same order. + for (int i = 0; i < mKey.mCount; i++) { + final int resId = mKey.mResId[i]; + final boolean force = mKey.mForce[i]; + AssetManager.applyThemeStyle(mTheme, resId, force); + } } } } diff --git a/core/java/android/content/res/ThemeChangeRequest.java b/core/java/android/content/res/ThemeChangeRequest.java deleted file mode 100644 index 1d13bb0c409ea..0000000000000 --- a/core/java/android/content/res/ThemeChangeRequest.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2015 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -import android.content.pm.ThemeUtils; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - - -import static android.provider.ThemesContract.ThemesColumns.*; - -/** @hide */ -public final class ThemeChangeRequest implements Parcelable { - public static final int DEFAULT_WALLPAPER_ID = -1; - - private final Map mThemeComponents = new HashMap(); - private final Map mPerAppOverlays = new HashMap(); - private RequestType mRequestType; - private long mWallpaperId = -1; - - public String getOverlayThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_OVERLAYS); - } - - public String getStatusBarThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_STATUS_BAR); - } - - public String getNavBarThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_NAVIGATION_BAR); - } - - public String getFontThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_FONTS); - } - - public String getIconsThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_ICONS); - } - - public String getBootanimationThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_BOOT_ANIM); - } - - public String getWallpaperThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_LAUNCHER); - } - - public String getLockWallpaperThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_LOCKSCREEN); - } - - public String getAlarmThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_ALARMS); - } - - public String getNotificationThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_NOTIFICATIONS); - } - - public String getRingtoneThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_RINGTONES); - } - - public String getLiveLockScreenThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_LIVE_LOCK_SCREEN); - } - - public final Map getThemeComponentsMap() { - return Collections.unmodifiableMap(mThemeComponents); - } - - public long getWallpaperId() { - return mWallpaperId; - } - - /** - * Get the mapping for per app themes - * @return A mapping of apps and the theme to apply for each one. or null if none set. - */ - public final Map getPerAppOverlays() { - return Collections.unmodifiableMap(mPerAppOverlays); - } - - public int getNumChangesRequested() { - return mThemeComponents.size() + mPerAppOverlays.size(); - } - - public RequestType getReqeustType() { - return mRequestType; - } - - private String getThemePackageNameForComponent(String componentName) { - return mThemeComponents.get(componentName); - } - - private ThemeChangeRequest(Map components, Map perAppThemes, - RequestType requestType, long wallpaperId) { - if (components != null) { - mThemeComponents.putAll(components); - } - if (perAppThemes != null) { - mPerAppOverlays.putAll(perAppThemes); - } - mRequestType = requestType; - mWallpaperId = wallpaperId; - } - - private ThemeChangeRequest(Parcel source) { - int numComponents = source.readInt(); - for (int i = 0; i < numComponents; i++) { - mThemeComponents.put(source.readString(), source.readString()); - } - - numComponents = source.readInt(); - for (int i = 0 ; i < numComponents; i++) { - mPerAppOverlays.put(source.readString(), source.readString()); - } - mRequestType = RequestType.values()[source.readInt()]; - mWallpaperId = source.readLong(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mThemeComponents.size()); - for (String component : mThemeComponents.keySet()) { - dest.writeString(component); - dest.writeString(mThemeComponents.get(component)); - } - dest.writeInt((mPerAppOverlays.size())); - for (String appPkgName : mPerAppOverlays.keySet()) { - dest.writeString(appPkgName); - dest.writeString(mPerAppOverlays.get(appPkgName)); - } - dest.writeInt(mRequestType.ordinal()); - dest.writeLong(mWallpaperId); - } - - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public ThemeChangeRequest createFromParcel(Parcel source) { - return new ThemeChangeRequest(source); - } - - @Override - public ThemeChangeRequest[] newArray(int size) { - return new ThemeChangeRequest[size]; - } - }; - - public enum RequestType { - USER_REQUEST, - USER_REQUEST_MIXNMATCH, - THEME_UPDATED, - THEME_REMOVED, - THEME_RESET; - } - - public static class Builder { - Map mThemeComponents = new HashMap(); - Map mPerAppOverlays = new HashMap(); - RequestType mRequestType = RequestType.USER_REQUEST; - long mWallpaperId; - - public Builder() {} - - public Builder(ThemeConfig themeConfig) { - if (themeConfig != null) { - buildChangeRequestFromThemeConfig(themeConfig); - } - } - - public Builder setOverlay(String pkgName) { - return setComponent(MODIFIES_OVERLAYS, pkgName); - } - - public Builder setStatusBar(String pkgName) { - return setComponent(MODIFIES_STATUS_BAR, pkgName); - } - - public Builder setNavBar(String pkgName) { - return setComponent(MODIFIES_NAVIGATION_BAR, pkgName); - } - - public Builder setFont(String pkgName) { - return setComponent(MODIFIES_FONTS, pkgName); - } - - public Builder setIcons(String pkgName) { - return setComponent(MODIFIES_ICONS, pkgName); - } - - public Builder setBootanimation(String pkgName) { - return setComponent(MODIFIES_BOOT_ANIM, pkgName); - } - - public Builder setWallpaper(String pkgName) { - return setComponent(MODIFIES_LAUNCHER, pkgName); - } - - // Used in the case that more than one wallpaper exists for a given pkg name - public Builder setWallpaperId(long id) { - mWallpaperId = id; - return this; - } - - public Builder setLockWallpaper(String pkgName) { - return setComponent(MODIFIES_LOCKSCREEN, pkgName); - } - - public Builder setAlarm(String pkgName) { - return setComponent(MODIFIES_ALARMS, pkgName); - } - - public Builder setNotification(String pkgName) { - return setComponent(MODIFIES_NOTIFICATIONS, pkgName); - } - - public Builder setRingtone(String pkgName) { - return setComponent(MODIFIES_RINGTONES, pkgName); - } - - public Builder setLiveLockScreen(String pkgName) { - return setComponent(MODIFIES_LIVE_LOCK_SCREEN, pkgName); - } - - public Builder setComponent(String component, String pkgName) { - if (pkgName != null) { - mThemeComponents.put(component, pkgName); - } else { - mThemeComponents.remove(component); - } - return this; - } - - public Builder setAppOverlay(String appPkgName, String themePkgName) { - if (appPkgName != null) { - if (themePkgName != null) { - mPerAppOverlays.put(appPkgName, themePkgName); - } else { - mPerAppOverlays.remove(appPkgName); - } - } - - return this; - } - - public Builder setRequestType(RequestType requestType) { - mRequestType = requestType != null ? requestType : RequestType.USER_REQUEST; - return this; - } - - public ThemeChangeRequest build() { - return new ThemeChangeRequest(mThemeComponents, mPerAppOverlays, - mRequestType, mWallpaperId); - } - - private void buildChangeRequestFromThemeConfig(ThemeConfig themeConfig) { - if (themeConfig.getFontPkgName() != null) { - this.setFont(themeConfig.getFontPkgName()); - } - if (themeConfig.getIconPackPkgName() != null) { - this.setIcons(themeConfig.getIconPackPkgName()); - } - if (themeConfig.getOverlayPkgName() != null) { - this.setOverlay(themeConfig.getOverlayPkgName()); - } - if (themeConfig.getOverlayForStatusBar() != null) { - this.setStatusBar(themeConfig.getOverlayForStatusBar()); - } - if (themeConfig.getOverlayForNavBar() != null) { - this.setNavBar(themeConfig.getOverlayForNavBar()); - } - - // Check if there are any per-app overlays using this theme - final Map themes = themeConfig.getAppThemes(); - for (String appPkgName : themes.keySet()) { - if (ThemeUtils.isPerAppThemeComponent(appPkgName)) { - this.setAppOverlay(appPkgName, themes.get(appPkgName).getOverlayPkgName()); - } - } - } - } -} diff --git a/core/java/android/content/res/ThemeConfig.java b/core/java/android/content/res/ThemeConfig.java index ac95d6b139a40..f3048010d4592 100644 --- a/core/java/android/content/res/ThemeConfig.java +++ b/core/java/android/content/res/ThemeConfig.java @@ -1,12 +1,12 @@ /* - * Copyright (C) 2014 The CyanogenMod Project + * Copyright (C) 2016 The CyanogenMod Project * Portions copyright (C) 2014, T-Mobile USA, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,12 +17,13 @@ package android.content.res; import android.content.ContentResolver; -import android.content.res.ThemeChangeRequest.RequestType; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.JsonReader; import android.util.JsonToken; import android.util.JsonWriter; @@ -34,8 +35,6 @@ import java.io.StringWriter; import java.io.Writer; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; /** @@ -61,9 +60,7 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable red theme) - protected final Map mThemes = new HashMap(); - - private RequestType mLastThemeChangeRequestType = RequestType.USER_REQUEST; + protected final Map mThemes = new ArrayMap<>(); public ThemeConfig(Map appThemes) { mThemes.putAll(appThemes); @@ -111,10 +108,6 @@ public Map getAppThemes() { return Collections.unmodifiableMap(mThemes); } - public RequestType getLastThemeChangeRequestType() { - return mLastThemeChangeRequestType; - } - private AppTheme getThemeFor(String pkgName) { AppTheme theme = mThemes.get(pkgName); if (theme == null) theme = getDefaultTheme(); @@ -136,12 +129,11 @@ public boolean equals(Object object) { ThemeConfig o = (ThemeConfig) object; Map currThemes = (mThemes == null) ? - new HashMap() : mThemes; + new ArrayMap() : mThemes; Map newThemes = (o.mThemes == null) ? - new HashMap() : o.mThemes; + new ArrayMap() : o.mThemes; - return (currThemes.equals(newThemes) && - mLastThemeChangeRequestType == o.mLastThemeChangeRequestType); + return currThemes.equals(newThemes); } return false; } @@ -160,8 +152,6 @@ public String toString() { public int hashCode() { int hash = 17; hash = 31 * hash + mThemes.hashCode(); - hash = 31 * hash + (mLastThemeChangeRequestType == null ? 0 : - mLastThemeChangeRequestType.ordinal()); return hash; } @@ -227,7 +217,6 @@ public int describeContents() { public void writeToParcel(Parcel dest, int flags) { String json = JsonSerializer.toJson(this); dest.writeString(json); - dest.writeInt(mLastThemeChangeRequestType.ordinal()); } public static final Parcelable.Creator CREATOR = @@ -235,7 +224,6 @@ public void writeToParcel(Parcel dest, int flags) { public ThemeConfig createFromParcel(Parcel source) { String json = source.readString(); ThemeConfig themeConfig = JsonSerializer.fromJson(json); - themeConfig.mLastThemeChangeRequestType = RequestType.values()[source.readInt()]; return themeConfig; } @@ -351,10 +339,9 @@ public String toString() { public static class Builder { - private HashMap mOverlays = new HashMap(); - private HashMap mIcons = new HashMap(); - private HashMap mFonts = new HashMap(); - private RequestType mLastThemeChangeRequestType = RequestType.USER_REQUEST; + private Map mOverlays = new ArrayMap<>(); + private Map mIcons = new ArrayMap<>(); + private Map mFonts = new ArrayMap<>(); public Builder() {} @@ -366,7 +353,6 @@ public Builder(ThemeConfig theme) { mIcons.put(key, appTheme.getIconPackPkgName()); mOverlays.put(key, appTheme.getOverlayPkgName()); } - mLastThemeChangeRequestType = theme.mLastThemeChangeRequestType; } /** @@ -427,18 +413,13 @@ public Builder font(String appPkgName, String themePkgName) { return this; } - public Builder setLastThemeChangeRequestType(RequestType requestType) { - mLastThemeChangeRequestType = requestType; - return this; - } - public ThemeConfig build() { - HashSet appPkgSet = new HashSet(); + ArraySet appPkgSet = new ArraySet<>(); appPkgSet.addAll(mOverlays.keySet()); appPkgSet.addAll(mIcons.keySet()); appPkgSet.addAll(mFonts.keySet()); - HashMap appThemes = new HashMap(); + Map appThemes = new ArrayMap<>(); for(String appPkgName : appPkgSet) { String icon = mIcons.get(appPkgName); String overlay = mOverlays.get(appPkgName); @@ -455,7 +436,6 @@ public ThemeConfig build() { } } ThemeConfig themeConfig = new ThemeConfig(appThemes); - themeConfig.mLastThemeChangeRequestType = mLastThemeChangeRequestType; return themeConfig; } } @@ -506,7 +486,7 @@ private static void writeAppTheme(JsonWriter writer, AppTheme appTheme) throws I public static ThemeConfig fromJson(String json) { if (json == null) return null; - HashMap map = new HashMap(); + Map map = new ArrayMap<>(); StringReader reader = null; JsonReader jsonReader = null; try { @@ -582,7 +562,7 @@ private static void closeQuietly(JsonWriter writer) { public static class SystemConfig extends ThemeConfig { public SystemConfig() { - super(new HashMap()); + super(new ArrayMap()); } } @@ -593,7 +573,7 @@ public SystemAppTheme() { @Override public String toString() { - return "No Theme Applied (Holo)"; + return "No Theme Applied (System)"; } } } diff --git a/core/java/android/content/res/ThemeManager.java b/core/java/android/content/res/ThemeManager.java deleted file mode 100644 index fd05f1e53c9cd..0000000000000 --- a/core/java/android/content/res/ThemeManager.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -import android.content.Context; -import android.content.pm.ThemeUtils; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * {@hide} - */ -public class ThemeManager { - private static final String TAG = ThemeManager.class.getName(); - private Context mContext; - private IThemeService mService; - private Handler mHandler; - - private Set mChangeListeners = - new HashSet(); - - private Set mProcessingListeners = - new HashSet(); - - public ThemeManager(Context context, IThemeService service) { - mContext = context; - mService = service; - mHandler = new Handler(Looper.getMainLooper()); - } - - private final IThemeChangeListener mThemeChangeListener = new IThemeChangeListener.Stub() { - @Override - public void onProgress(final int progress) throws RemoteException { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mChangeListeners) { - List listenersToRemove = new ArrayList - (); - for (ThemeChangeListener listener : mChangeListeners) { - try { - listener.onProgress(progress); - } catch (Throwable e) { - Log.w(TAG, "Unable to update theme change progress", e); - listenersToRemove.add(listener); - } - } - if (listenersToRemove.size() > 0) { - for (ThemeChangeListener listener : listenersToRemove) { - mChangeListeners.remove(listener); - } - } - } - } - }); - } - - @Override - public void onFinish(final boolean isSuccess) throws RemoteException { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mChangeListeners) { - List listenersToRemove = new ArrayList - (); - for (ThemeChangeListener listener : mChangeListeners) { - try { - listener.onFinish(isSuccess); - } catch (Throwable e) { - Log.w(TAG, "Unable to update theme change listener", e); - listenersToRemove.add(listener); - } - } - if (listenersToRemove.size() > 0) { - for (ThemeChangeListener listener : listenersToRemove) { - mChangeListeners.remove(listener); - } - } - } - } - }); - } - }; - - private final IThemeProcessingListener mThemeProcessingListener = - new IThemeProcessingListener.Stub() { - @Override - public void onFinishedProcessing(final String pkgName) throws RemoteException { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mProcessingListeners) { - List listenersToRemove = new ArrayList - (); - for (ThemeProcessingListener listener : mProcessingListeners) { - try { - listener.onFinishedProcessing(pkgName); - } catch (Throwable e) { - Log.w(TAG, "Unable to update theme change progress", e); - listenersToRemove.add(listener); - } - } - if (listenersToRemove.size() > 0) { - for (ThemeProcessingListener listener : listenersToRemove) { - mProcessingListeners.remove(listener); - } - } - } - } - }); - } - }; - - - public void addClient(ThemeChangeListener listener) { - synchronized (mChangeListeners) { - if (mChangeListeners.contains(listener)) { - throw new IllegalArgumentException("Client was already added "); - } - if (mChangeListeners.size() == 0) { - try { - mService.requestThemeChangeUpdates(mThemeChangeListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to register listener", e); - } - } - mChangeListeners.add(listener); - } - } - - public void removeClient(ThemeChangeListener listener) { - synchronized (mChangeListeners) { - mChangeListeners.remove(listener); - if (mChangeListeners.size() == 0) { - try { - mService.removeUpdates(mThemeChangeListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to remove listener", e); - } - } - } - } - - public void onClientPaused(ThemeChangeListener listener) { - removeClient(listener); - } - - public void onClientResumed(ThemeChangeListener listener) { - addClient(listener); - } - - public void onClientDestroyed(ThemeChangeListener listener) { - removeClient(listener); - } - - /** - * Register a ThemeProcessingListener to be notified when a theme is done being processed. - * @param listener ThemeChangeListener to register - */ - public void registerProcessingListener(ThemeProcessingListener listener) { - synchronized (mProcessingListeners) { - if (mProcessingListeners.contains(listener)) { - throw new IllegalArgumentException("Listener was already added "); - } - if (mProcessingListeners.size() == 0) { - try { - mService.registerThemeProcessingListener(mThemeProcessingListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to register listener", e); - } - } - mProcessingListeners.add(listener); - } - } - - /** - * Unregister a ThemeChangeListener. - * @param listener ThemeChangeListener to unregister - */ - public void unregisterProcessingListener(ThemeChangeListener listener) { - synchronized (mProcessingListeners) { - mProcessingListeners.remove(listener); - if (mProcessingListeners.size() == 0) { - try { - mService.unregisterThemeProcessingListener(mThemeProcessingListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to remove listener", e); - } - } - } - } - - /** - * Convenience method. Applies the entire theme. - */ - public void requestThemeChange(String pkgName) { - //List components = ThemeUtils.getSupportedComponents(mContext, pkgName); - //requestThemeChange(pkgName, components); - } - - public void requestThemeChange(String pkgName, List components) { - requestThemeChange(pkgName, components, true); - } - - public void requestThemeChange(String pkgName, List components, - boolean removePerAppThemes) { - Map componentMap = new HashMap(components.size()); - for (String component : components) { - componentMap.put(component, pkgName); - } - requestThemeChange(componentMap, removePerAppThemes); - } - - public void requestThemeChange(Map componentMap) { - requestThemeChange(componentMap, true); - } - - public void requestThemeChange(Map componentMap, boolean removePerAppThemes) { - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - for (String component : componentMap.keySet()) { - builder.setComponent(component, componentMap.get(component)); - } - - requestThemeChange(builder.build(), removePerAppThemes); - } - - public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) { - try { - mService.requestThemeChange(request, removePerAppThemes); - } catch (RemoteException e) { - logThemeServiceException(e); - } - } - - public void applyDefaultTheme() { - try { - mService.applyDefaultTheme(); - } catch (RemoteException e) { - logThemeServiceException(e); - } - } - - public boolean isThemeApplying() { - try { - return mService.isThemeApplying(); - } catch (RemoteException e) { - logThemeServiceException(e); - } - - return false; - } - - public boolean isThemeBeingProcessed(String themePkgName) { - try { - return mService.isThemeBeingProcessed(themePkgName); - } catch (RemoteException e) { - logThemeServiceException(e); - } - return false; - } - - public int getProgress() { - try { - return mService.getProgress(); - } catch (RemoteException e) { - logThemeServiceException(e); - } - return -1; - } - - public boolean processThemeResources(String themePkgName) { - try { - return mService.processThemeResources(themePkgName); - } catch (RemoteException e) { - logThemeServiceException(e); - } - return false; - } - - private void logThemeServiceException(Exception e) { - Log.w(TAG, "Unable to access ThemeService", e); - } - - public interface ThemeChangeListener { - void onProgress(int progress); - void onFinish(boolean isSuccess); - } - - public interface ThemeProcessingListener { - void onFinishedProcessing(String pkgName); - } -} - diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index dc576a5a85985..dd15d38896102 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -40,6 +40,7 @@ import android.text.TextUtils; import android.view.Surface; import android.view.SurfaceHolder; +import android.os.SystemProperties; import java.io.IOException; import java.lang.ref.WeakReference; @@ -483,8 +484,21 @@ private int cameraInitVersion(int cameraId, int halVersion) { mEventHandler = null; } - return native_setup(new WeakReference(this), cameraId, halVersion, - ActivityThread.currentOpPackageName()); + String packageName = ActivityThread.currentOpPackageName(); + + //Force HAL1 if the package name falls in this bucket + String packageList = SystemProperties.get("camera.hal1.packagelist", ""); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + halVersion = CAMERA_HAL_API_VERSION_1_0; + break; + } + } + } + return native_setup(new WeakReference(this), cameraId, halVersion, packageName); } private int cameraInitNormal(int cameraId) { @@ -3471,8 +3485,8 @@ public void setGpsTimestamp(long timestamp) { } /** - * Sets GPS processing method. It will store up to 32 characters - * in JPEG EXIF header. + * Sets GPS processing method. The method will be stored in a UTF-8 string up to 31 bytes + * long, in the JPEG EXIF header. * * @param processing_method The processing method to get this location. */ diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index a2ef078a6a71a..74642113a23e7 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -398,17 +398,24 @@ public List> getAvailableCaptureResultKeys() { * this camera device.

*

For devices at the LEGACY level or above:

*
    - *
  • This list will always include (30, 30).
  • - *
  • Also, for constant-framerate recording, for each normal + *
  • + *

    For constant-framerate recording, for each normal + * {@link android.media.CamcorderProfile CamcorderProfile}, that is, a * {@link android.media.CamcorderProfile CamcorderProfile} that has * {@link android.media.CamcorderProfile#quality quality} in * the range [{@link android.media.CamcorderProfile#QUALITY_LOW QUALITY_LOW}, * {@link android.media.CamcorderProfile#QUALITY_2160P QUALITY_2160P}], if the profile is * supported by the device and has * {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} x, this list will - * always include (x,x).

  • - *
  • For preview streaming use case, this list will always include (min, max) where - * min <= 15 and max >= 30.
  • + * always include (x,x).

    + * + *
  • + *

    Also, a camera device must either not support any + * {@link android.media.CamcorderProfile CamcorderProfile}, + * or support at least one + * normal {@link android.media.CamcorderProfile CamcorderProfile} that has + * {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} x >= 24.

    + *
  • *
*

For devices at the LIMITED level or above:

*
    diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 35a1d960e22df..f61892ec61143 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -472,13 +472,13 @@ private static boolean shouldKeyBeAdded(TKey key, Field field, int[] filt *
  • The maximum available resolution for RAW_SENSOR streams * will match either the value in * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} or - * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.
  • + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. *
  • All DNG-related optional metadata entries are provided * by the camera device.
  • *
* - * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3f566eb927567..67835a0239d35 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -556,6 +556,10 @@ public void removeTarget(@NonNull Surface outputTarget) { * Set a capture request field to a value. The field definitions can be * found in {@link CaptureRequest}. * + *

Setting a field to {@code null} will remove that field from the capture request. + * Unless the field is optional, removing it will likely produce an error from the camera + * device when the request is submitted.

+ * * @param key The metadata field to write. * @param value The value to set the field to, which must be of a matching * type to the key. diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java index a0a03b101ef16..c26d07d2bc2ef 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -81,6 +81,7 @@ public class RequestThreadManager { private static final int PREVIEW_FRAME_TIMEOUT = 1000; // ms private static final int JPEG_FRAME_TIMEOUT = 4000; // ms (same as CTS for API2) + private static final int HDR_TIMEOUT = 20000; //ms private static final int REQUEST_COMPLETE_TIMEOUT = JPEG_FRAME_TIMEOUT; private static final float ASPECT_RATIO_TOLERANCE = 0.01f; @@ -825,7 +826,9 @@ public boolean handleMessage(Message msg) { if (holder.hasJpegTargets()) { doJpegCapture(holder); - if (!mReceivedJpeg.block(JPEG_FRAME_TIMEOUT)) { + if (!mReceivedJpeg.block( + mParams.getSceneMode().equals(mParams.SCENE_MODE_HDR) + ? HDR_TIMEOUT : JPEG_FRAME_TIMEOUT)) { Log.e(TAG, "Hit timeout for jpeg callback!"); mCaptureCollector.failNextJpeg(); } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 122df2394b6b4..62396a38ff987 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -258,6 +258,7 @@ public long getOpId() { public static class AuthenticationResult { private Fingerprint mFingerprint; private CryptoObject mCryptoObject; + private int mUserId; /** * Authentication result @@ -266,9 +267,10 @@ public static class AuthenticationResult { * @param fingerprint the recognized fingerprint data, if allowed. * @hide */ - public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { + public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId) { mCryptoObject = crypto; mFingerprint = fingerprint; + mUserId = userId; } /** @@ -285,6 +287,12 @@ public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { * @hide */ public Fingerprint getFingerprint() { return mFingerprint; } + + /** + * Obtain the userId for which this fingerprint was authenticated. + * @hide + */ + public int getUserId() { return mUserId; } }; /** @@ -754,7 +762,7 @@ public void handleMessage(android.os.Message msg) { sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); break; case MSG_AUTHENTICATION_SUCCEEDED: - sendAuthenticatedSucceeded((Fingerprint) msg.obj); + sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */); break; case MSG_AUTHENTICATION_FAILED: sendAuthenticatedFailed(); @@ -799,9 +807,10 @@ private void sendEnrollResult(Fingerprint fp, int remaining) { } } - private void sendAuthenticatedSucceeded(Fingerprint fp) { + private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) { if (mAuthenticationCallback != null) { - final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); + final AuthenticationResult result = + new AuthenticationResult(mCryptoObject, fp, userId); mAuthenticationCallback.onAuthenticationSucceeded(result); } } @@ -941,8 +950,8 @@ public void onAcquired(long deviceId, int acquireInfo) { } @Override // binder call - public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) { - mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget(); + public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) { + mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget(); } @Override // binder call diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl index 57a429fe5fa75..b024b29fef06b 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl @@ -26,7 +26,7 @@ import android.os.UserHandle; oneway interface IFingerprintServiceReceiver { void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining); void onAcquired(long deviceId, int acquiredInfo); - void onAuthenticationSucceeded(long deviceId, in Fingerprint fp); + void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId); void onAuthenticationFailed(long deviceId); void onError(long deviceId, int error); void onRemoved(long deviceId, int fingerId, int groupId); diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 7f5f3776d3556..9e639e8f05a1c 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -48,6 +48,9 @@ interface INetworkPolicyManager { /** Snooze limit on policy matching given template. */ void snoozeLimit(in NetworkTemplate template); + /** Snooze warning on policy matching given template. */ + void snoozeWarning(in NetworkTemplate template); + /** Control if background data is restricted system-wide. */ void setRestrictBackground(boolean restrictBackground); boolean getRestrictBackground(); diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 6436e42676558..17033c4e0ebab 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -57,4 +57,5 @@ interface INetworkStatsService { /** Advise persistance threshold; may be overridden internally. */ void advisePersistThreshold(long thresholdBytes); + void resetDataUsageHistoryForAllUid(in NetworkTemplate template); } diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index a83e722403102..7f4d6e3c584c6 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -20,6 +20,7 @@ import static android.net.NetworkPolicy.CYCLE_NONE; import static android.text.format.Time.MONTH_DAY; +import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -48,6 +49,12 @@ public class NetworkPolicyManager { public static final int POLICY_REJECT_METERED_BACKGROUND = 0x1; /** Allow network use (metered or not) in the background in battery save mode. */ public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2; + /** Reject application network traffic on wifi network **/ + public static final int POLICY_REJECT_ON_WLAN = 0x8000; + /** Reject application network traffic on cellular network **/ + public static final int POLICY_REJECT_ON_DATA = 0x10000; + /** Reject application background network traffic on WiFi network **/ + public static final int POLICY_REJECT_ON_WLAN_BACKGROUND = 0x20000; /* RULE_* are not masks and they must be exclusive */ public static final int RULE_UNKNOWN = -1; @@ -81,6 +88,54 @@ public class NetworkPolicyManager { */ public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE"; + /** + * Broadcast intent action for informing a custom component about a network policy + * notification. + * @hide + */ + @SystemApi + public static final String ACTION_SHOW_NETWORK_POLICY_NOTIFICATION = + "android.net.action.SHOW_NETWORK_POLICY_NOTIFICATION"; + + /** + * The sequence number associated with the notification - a higher number + * indicates previous notifications may be disregarded. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_SEQUENCE_NUMBER = + "android.net.extra.NOTIFICATION_SEQUENCE_NUMBER"; + + /** + * The type of notification that should be presented to the user. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_TYPE = "android.net.extra.NOTIFICATION_TYPE"; + + @SystemApi + public static final int NOTIFICATION_TYPE_NONE = 0; + @SystemApi + public static final int NOTIFICATION_TYPE_USAGE_WARNING = 1; + @SystemApi + public static final int NOTIFICATION_TYPE_USAGE_REACHED_LIMIT = 2; + @SystemApi + public static final int NOTIFICATION_TYPE_USAGE_EXCEEDED_LIMIT = 3; + + /** + * The number of bytes used on the network in the notification. + * @hide + */ + @SystemApi + public static final String EXTRA_BYTES_USED = "android.net.extra.BYTES_USED"; + + /** + * The network policy for the network in the notification. + * @hide + */ + @SystemApi + public static final String EXTRA_NETWORK_POLICY = "android.net.extra.NETWORK_POLICY"; + private final Context mContext; private INetworkPolicyManager mService; diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java index 29daf352e1d32..5880e5dcccef3 100644 --- a/core/java/android/net/NetworkScorerAppManager.java +++ b/core/java/android/net/NetworkScorerAppManager.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -90,8 +91,13 @@ public NetworkScorerAppData(String packageName, int packageUid, CharSequence sco * @return the list of scorers, or the empty list if there are no valid scorers. */ public static Collection getAllValidScorers(Context context) { - List scorers = new ArrayList<>(); + // Network scorer apps can only run as the primary user so exit early if we're not the + // primary user. + if (UserHandle.getCallingUserId() != 0 /*USER_SYSTEM*/) { + return Collections.emptyList(); + } + List scorers = new ArrayList<>(); PackageManager pm = context.getPackageManager(); // Only apps installed under the primary user of the device can be scorers. List receivers = @@ -104,8 +110,9 @@ public static Collection getAllValidScorers(Context contex continue; } if (!permission.BROADCAST_NETWORK_PRIVILEGED.equals(receiverInfo.permission)) { - // Receiver doesn't require the BROADCAST_NETWORK_PRIVILEGED permission, which means - // anyone could trigger network scoring and flood the framework with score requests. + // Receiver doesn't require the BROADCAST_NETWORK_PRIVILEGED permission, which + // means anyone could trigger network scoring and flood the framework with score + // requests. continue; } if (pm.checkPermission(permission.SCORE_NETWORKS, receiverInfo.packageName) != @@ -127,8 +134,8 @@ public static Collection getAllValidScorers(Context contex } } - // NOTE: loadLabel will attempt to load the receiver's label and fall back to the app - // label if none is present. + // NOTE: loadLabel will attempt to load the receiver's label and fall back to the + // app label if none is present. scorers.add(new NetworkScorerAppData(receiverInfo.packageName, receiverInfo.applicationInfo.uid, receiverInfo.loadLabel(pm), configurationActivityClassName)); diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java index 9bdf4f6db8e65..85bf79ab3d69d 100644 --- a/core/java/android/net/PacProxySelector.java +++ b/core/java/android/net/PacProxySelector.java @@ -30,6 +30,7 @@ import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; +import java.net.URISyntaxException; import java.util.List; /** @@ -67,7 +68,15 @@ public List select(URI uri) { String response = null; String urlString; try { + // Strip path and username/password from URI so it's not visible to PAC script. The + // path often contains credentials the app does not want exposed to a potentially + // malicious PAC script. + if (!"http".equalsIgnoreCase(uri.getScheme())) { + uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null); + } urlString = uri.toURL().toString(); + } catch (URISyntaxException e) { + urlString = uri.getHost(); } catch (MalformedURLException e) { urlString = uri.getHost(); } diff --git a/core/java/android/net/ZeroBalanceHelper.java b/core/java/android/net/ZeroBalanceHelper.java new file mode 100644 index 0000000000000..e0ffca5a0518d --- /dev/null +++ b/core/java/android/net/ZeroBalanceHelper.java @@ -0,0 +1,99 @@ +/* + ** Copyright (c) 2015, The Linux Foundation. All rights reserved. + + ** Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above + ** copyright notice, this list of conditions and the following + ** disclaimer in the documentation and/or other materials provided + ** with the distribution. + ** * Neither the name of The Linux Foundation nor the names of its + ** contributors may be used to endorse or promote products derived + ** from this software without specific prior written permission. + + ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.net; + +import android.app.ActivityThread; +import android.content.Context; +import android.content.Intent; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.util.Log; + +import com.android.internal.R; + +/** @hide */ +public final class ZeroBalanceHelper { + + public static final String BACKGROUND_DATA_PROPERTY = "sys.background.data.disable"; + public static final String BACKGROUND_DATA_BROADCAST = "org.codeaurora.background.data"; + public static final String TAG = "ZeroBalance"; + + private static int sRedirectCount = 0; + private static int sRedirectMaxCount = 3; + + private Context mContext = null; + + public ZeroBalanceHelper() { + mContext = ActivityThread.currentApplication(); + } + + public void setBgDataProperty(String enabled) { + Intent intent = new Intent(); + intent.setAction(BACKGROUND_DATA_BROADCAST); + intent.putExtra("enabled", enabled); + mContext.sendBroadcast(intent); + } + + public String getBgDataProperty() { + String isBgDataPropertySet = SystemProperties.get(BACKGROUND_DATA_PROPERTY, "false"); + if (Boolean.parseBoolean(isBgDataPropertySet)) { + sRedirectCount = 0; + } + return isBgDataPropertySet; + } + + private String getConfiguredRedirectURL() { + String redirectURL = mContext.getResources().getString( + com.android.internal.R.string.operator_config_url); + Log.d(TAG, "Returning the configured redirect URL : " + + redirectURL); + return redirectURL; + } + + public synchronized void setHttpRedirectCount(String url) { + String redirectUrl = getConfiguredRedirectURL(); + if (redirectUrl != null && url.contains(redirectUrl)) { + sRedirectCount++; + Log.d(TAG, "http:sRedirectCount="+sRedirectCount); + if (sRedirectCount >= sRedirectMaxCount) { + Log.d(TAG,"http:Background Data will be disabled" ); + setBgDataProperty("true"); + sRedirectCount = 0; + } + } else { + Log.d(TAG,"http: resetting the counter "); + sRedirectCount = 0; + } + } + + public boolean getFeatureConfigValue() { + return mContext.getResources().getBoolean(R.bool.config_zero_balance_operator); + } +} diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 961a3f41cd5eb..0107d93c3cfc9 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -1,4 +1,7 @@ /* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,6 +31,7 @@ import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; import android.nfc.INfcUnlockHandler; import android.os.Bundle; +import android.os.IBinder; /** * @hide @@ -37,6 +41,7 @@ interface INfcAdapter INfcTag getNfcTagInterface(); INfcCardEmulation getNfcCardEmulationInterface(); INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg); + IBinder getNfcAdapterVendorInterface(in String vendor); int getState(); boolean disable(boolean saveState); diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index d619c0a8e117d..c7d4c65d99c0d 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -371,40 +371,44 @@ public BeamShareData createBeamShareData(byte peerLlcpVersion) { flags = state.flags; activity = state.activity; } - - // Make callbacks without lock - if (ndefCallback != null) { - message = ndefCallback.createNdefMessage(event); - } - if (urisCallback != null) { - uris = urisCallback.createBeamUris(event); - if (uris != null) { - ArrayList validUris = new ArrayList(); - for (Uri uri : uris) { - if (uri == null) { - Log.e(TAG, "Uri not allowed to be null."); - continue; - } - String scheme = uri.getScheme(); - if (scheme == null || (!scheme.equalsIgnoreCase("file") && - !scheme.equalsIgnoreCase("content"))) { - Log.e(TAG, "Uri needs to have " + - "either scheme file or scheme content"); - continue; + final long ident = Binder.clearCallingIdentity(); + try { + // Make callbacks without lock + if (ndefCallback != null) { + message = ndefCallback.createNdefMessage(event); + } + if (urisCallback != null) { + uris = urisCallback.createBeamUris(event); + if (uris != null) { + ArrayList validUris = new ArrayList(); + for (Uri uri : uris) { + if (uri == null) { + Log.e(TAG, "Uri not allowed to be null."); + continue; + } + String scheme = uri.getScheme(); + if (scheme == null || (!scheme.equalsIgnoreCase("file") && + !scheme.equalsIgnoreCase("content"))) { + Log.e(TAG, "Uri needs to have " + + "either scheme file or scheme content"); + continue; + } + uri = ContentProvider.maybeAddUserId(uri, UserHandle.myUserId()); + validUris.add(uri); } - uri = ContentProvider.maybeAddUserId(uri, UserHandle.myUserId()); - validUris.add(uri); - } - uris = validUris.toArray(new Uri[validUris.size()]); + uris = validUris.toArray(new Uri[validUris.size()]); + } } - } - if (uris != null && uris.length > 0) { - for (Uri uri : uris) { - // Grant the NFC process permission to read these URIs - activity.grantUriPermission("com.android.nfc", uri, - Intent.FLAG_GRANT_READ_URI_PERMISSION); + if (uris != null && uris.length > 0) { + for (Uri uri : uris) { + // Grant the NFC process permission to read these URIs + activity.grantUriPermission("com.android.nfc", uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION); + } } + } finally { + Binder.restoreCallingIdentity(ident); } return new BeamShareData(message, uris, new UserHandle(UserHandle.myUserId()), flags); } diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java index 78a9401a2abd9..9abf32565337c 100644 --- a/core/java/android/nfc/cardemulation/AidGroup.java +++ b/core/java/android/nfc/cardemulation/AidGroup.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2015 The Android Open Source Project * + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -37,7 +40,7 @@ * * @hide */ -public final class AidGroup implements Parcelable { +public class AidGroup implements Parcelable { /** * The maximum number of AIDs that can be present in any one group. */ @@ -45,9 +48,9 @@ public final class AidGroup implements Parcelable { static final String TAG = "AidGroup"; - final List aids; - final String category; - final String description; + protected List aids; + protected String category; + protected String description; /** * Creates a new AidGroup object. diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java index 8c92288d00479..302c02daa638b 100644 --- a/core/java/android/nfc/tech/MifareClassic.java +++ b/core/java/android/nfc/tech/MifareClassic.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2015 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -173,6 +175,10 @@ public MifareClassic(Tag tag) throws RemoteException { mType = TYPE_CLASSIC; mSize = SIZE_4K; break; + case 0x19: + mType = TYPE_CLASSIC; + mSize = SIZE_2K; + break; case 0x28: mType = TYPE_CLASSIC; mSize = SIZE_1K; diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java index 88730f9af3dff..b7fa455e3880c 100644 --- a/core/java/android/nfc/tech/NfcA.java +++ b/core/java/android/nfc/tech/NfcA.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2015 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,8 +68,15 @@ public static NfcA get(Tag tag) { /** @hide */ public NfcA(Tag tag) throws RemoteException { super(tag, TagTechnology.NFC_A); - Bundle extras = tag.getTechExtras(TagTechnology.NFC_A); - mSak = extras.getShort(EXTRA_SAK); + Bundle extras; + mSak = 0; + if(tag.hasTech(TagTechnology.MIFARE_CLASSIC)) + { + extras = tag.getTechExtras(TagTechnology.MIFARE_CLASSIC); + mSak = extras.getShort(EXTRA_SAK); + } + extras = tag.getTechExtras(TagTechnology.NFC_A); + mSak |= extras.getShort(EXTRA_SAK); mAtqa = extras.getByteArray(EXTRA_ATQA); } diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 1f3e9a7025ebf..050820c3ec957 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +17,7 @@ package android.os; +import android.app.IBatteryService; import android.content.Context; import android.os.BatteryProperty; import android.os.IBatteryPropertiesRegistrar; @@ -93,6 +95,79 @@ public class BatteryManager { */ public static final String EXTRA_TECHNOLOGY = "technology"; + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock status constant. + * @hide + */ + public static final String EXTRA_DOCK_STATUS = "dock_status"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock health constant. + * @hide + */ + public static final String EXTRA_DOCK_HEALTH = "dock_health"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * boolean indicating whether a dock battery is present. + * @hide + */ + public static final String EXTRA_DOCK_PRESENT = "dock_present"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer field containing the current dock battery level, from 0 to + * {@link #EXTRA_SCALE}. + * @hide + */ + public static final String EXTRA_DOCK_LEVEL = "dock_level"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the maximum dock battery level. + * @hide + */ + public static final String EXTRA_DOCK_SCALE = "dock_scale"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the resource ID of a small status bar icon + * indicating the current dock battery state. + * @hide + */ + public static final String EXTRA_DOCK_ICON_SMALL = "dock_icon-small"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer indicating whether the device is plugged in to a dock power + * source. + * @hide + */ + public static final String EXTRA_DOCK_PLUGGED = "dock_plugged"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock battery voltage level. + * @hide + */ + public static final String EXTRA_DOCK_VOLTAGE = "dock_voltage"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock battery temperature. + * @hide + */ + public static final String EXTRA_DOCK_TEMPERATURE = "dock_temperature"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * String describing the technology of the current dock battery. + * @hide + */ + public static final String EXTRA_DOCK_TECHNOLOGY = "dock_technology"; + /** * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: * Int value set to nonzero if an unsupported charger is attached @@ -133,10 +208,23 @@ public class BatteryManager { /** Power source is wireless. */ public static final int BATTERY_PLUGGED_WIRELESS = 4; + // values of the "dock_plugged" field in the ACTION_BATTERY_CHANGED intent. + // These must be powers of 2. + /** Power source is an DockAC charger. + * @hide*/ + public static final int BATTERY_DOCK_PLUGGED_AC = 1; + /** Power source is an DockUSB charger. + * @hide*/ + public static final int BATTERY_DOCK_PLUGGED_USB = 2; + /** @hide */ public static final int BATTERY_PLUGGED_ANY = BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS; + /** @hide */ + public static final int BATTERY_DOCK_PLUGGED_ANY = + BATTERY_DOCK_PLUGGED_AC | BATTERY_DOCK_PLUGGED_USB; + /** * Sent when the device's battery has started charging (or has reached full charge * and the device is on power). This is a good time to do work that you would like to @@ -191,6 +279,7 @@ public class BatteryManager { */ public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; + private final IBatteryService mBatteryService; private final IBatteryStats mBatteryStats; private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar; @@ -202,6 +291,27 @@ public BatteryManager() { ServiceManager.getService(BatteryStats.SERVICE_NAME)); mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface( ServiceManager.getService("batteryproperties")); + mBatteryService = null; + } + + /** @hide */ + public BatteryManager(IBatteryService service) { + super(); + mBatteryStats = IBatteryStats.Stub.asInterface( + ServiceManager.getService(BatteryStats.SERVICE_NAME)); + mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface( + ServiceManager.getService("batteryproperties")); + mBatteryService = service; + } + + /** @hide */ + public boolean isDockBatterySupported() { + try { + return mBatteryService != null && mBatteryService.isDockBatterySupported(); + } catch (RemoteException ex) { + // Ignore + } + return false; } /** @@ -223,8 +333,10 @@ public boolean isCharging() { * * Returns the requested value, or Long.MIN_VALUE if property not * supported on this system or on other error. + * fromDock determines if the property is query from the normal battery + * or the dock battery. */ - private long queryProperty(int id) { + private long queryProperty(int id, boolean fromDock) { long ret; if (mBatteryPropertiesRegistrar == null) { @@ -234,7 +346,13 @@ private long queryProperty(int id) { try { BatteryProperty prop = new BatteryProperty(); - if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0) + final int callResult; + if (!fromDock) { + callResult = mBatteryPropertiesRegistrar.getProperty(id, prop); + } else { + callResult = mBatteryPropertiesRegistrar.getDockProperty(id, prop); + } + if (callResult == 0) ret = prop.getLong(); else ret = Long.MIN_VALUE; @@ -255,7 +373,7 @@ private long queryProperty(int id) { * @return the property value, or Integer.MIN_VALUE if not supported. */ public int getIntProperty(int id) { - return (int)queryProperty(id); + return (int)queryProperty(id, false); } /** @@ -268,6 +386,40 @@ public int getIntProperty(int id) { * @return the property value, or Long.MIN_VALUE if not supported. */ public long getLongProperty(int id) { - return queryProperty(id); + return queryProperty(id, false); + } + + /** + * Return the value of a dock battery property of integer type. If the + * platform does not provide the property queried, this value will + * be Integer.MIN_VALUE. + * + * @param id identifier of the requested property + * + * @return the property value, or Integer.MIN_VALUE if not supported. + * @hide + */ + public int getIntDockProperty(int id) { + if (!isDockBatterySupported()) { + return Integer.MIN_VALUE; + } + return (int)queryProperty(id, true); + } + + /** + * Return the value of a dock battery property of long type If the + * platform does not provide the property queried, this value will + * be Long.MIN_VALUE. + * + * @param id identifier of the requested property + * + * @return the property value, or Long.MIN_VALUE if not supported. + * @hide + */ + public long getLongDockProperty(int id) { + if (!isDockBatterySupported()) { + return Long.MIN_VALUE; + } + return queryProperty(id, true); } } diff --git a/core/java/android/os/BatteryManagerInternal.java b/core/java/android/os/BatteryManagerInternal.java index f3a95b90d5c11..1abb3d5244d85 100644 --- a/core/java/android/os/BatteryManagerInternal.java +++ b/core/java/android/os/BatteryManagerInternal.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +43,26 @@ public abstract class BatteryManagerInternal { */ public abstract boolean getBatteryLevelLow(); + /** + * Returns whether dock batteries is supported + */ + public abstract boolean isDockBatterySupported(); + + /** + * Returns the current dock plug type. + */ + public abstract int getDockPlugType(); + + /** + * Returns dock battery level as a percentage. + */ + public abstract int getDockBatteryLevel(); + + /** + * Returns whether we currently consider the dock battery level to be low. + */ + public abstract boolean getDockBatteryLevelLow(); + /** * Returns a non-zero value if an unsupported charger is attached. */ diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java index 29e868c604544..cad741ac7a615 100644 --- a/core/java/android/os/BatteryProperties.java +++ b/core/java/android/os/BatteryProperties.java @@ -1,4 +1,5 @@ /* Copyright 2013, The Android Open Source Project + * Copyright 2016, The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +32,16 @@ public class BatteryProperties implements Parcelable { public int batteryTemperature; public String batteryTechnology; + public boolean dockBatterySupported; + public boolean chargerDockAcOnline; + public int dockBatteryStatus; + public int dockBatteryHealth; + public boolean dockBatteryPresent; + public int dockBatteryLevel; + public int dockBatteryVoltage; + public int dockBatteryTemperature; + public String dockBatteryTechnology; + public BatteryProperties() { } @@ -46,6 +57,16 @@ public void set(BatteryProperties other) { batteryVoltage = other.batteryVoltage; batteryTemperature = other.batteryTemperature; batteryTechnology = other.batteryTechnology; + + dockBatterySupported = other.dockBatterySupported; + chargerDockAcOnline = other.chargerDockAcOnline; + dockBatteryStatus = other.dockBatteryStatus; + dockBatteryHealth = other.dockBatteryHealth; + dockBatteryPresent = other.dockBatteryPresent; + dockBatteryLevel = other.dockBatteryLevel; + dockBatteryVoltage = other.dockBatteryVoltage; + dockBatteryTemperature = other.dockBatteryTemperature; + dockBatteryTechnology = other.dockBatteryTechnology; } /* @@ -65,6 +86,27 @@ private BatteryProperties(Parcel p) { batteryVoltage = p.readInt(); batteryTemperature = p.readInt(); batteryTechnology = p.readString(); + + dockBatterySupported = p.readInt() == 1 ? true : false; + if (dockBatterySupported) { + chargerDockAcOnline = p.readInt() == 1 ? true : false; + dockBatteryStatus = p.readInt(); + dockBatteryHealth = p.readInt(); + dockBatteryPresent = p.readInt() == 1 ? true : false; + dockBatteryLevel = p.readInt(); + dockBatteryVoltage = p.readInt(); + dockBatteryTemperature = p.readInt(); + dockBatteryTechnology = p.readString(); + } else { + chargerDockAcOnline = false; + dockBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; + dockBatteryHealth = BatteryManager.BATTERY_HEALTH_UNKNOWN; + dockBatteryPresent = false; + dockBatteryLevel = 0; + dockBatteryVoltage = 0; + dockBatteryTemperature = 0; + dockBatteryTechnology = ""; + } } public void writeToParcel(Parcel p, int flags) { @@ -79,6 +121,18 @@ public void writeToParcel(Parcel p, int flags) { p.writeInt(batteryVoltage); p.writeInt(batteryTemperature); p.writeString(batteryTechnology); + + p.writeInt(dockBatterySupported ? 1 : 0); + if (dockBatterySupported) { + p.writeInt(chargerDockAcOnline ? 1 : 0); + p.writeInt(dockBatteryStatus); + p.writeInt(dockBatteryHealth); + p.writeInt(dockBatteryPresent ? 1 : 0); + p.writeInt(dockBatteryLevel); + p.writeInt(dockBatteryVoltage); + p.writeInt(dockBatteryTemperature); + p.writeString(dockBatteryTechnology); + } } public static final Parcelable.Creator CREATOR diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 862f4c447b349..2df9be21dcee1 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -23,7 +23,11 @@ import dalvik.system.VMRuntime; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Information about the current build, extracted from system properties. @@ -664,6 +668,7 @@ public static class VERSION_CODES { /** The type of build, like "user" or "eng". */ public static final String TYPE = getString("ro.build.type"); + private static String TYPE_FOR_APPS = parseBuildTypeFromFingerprint(); /** Comma-separated tags describing the build, like "unsigned,debug". */ public static final String TAGS = getString("ro.build.tags"); @@ -690,6 +695,42 @@ private static String deriveFingerprint() { return finger; } + // Some apps like to compare the build type embedded in fingerprint + // to the actual build type. As the fingerprint in our case is almost + // always hardcoded to the stock ROM fingerprint, provide that instead + // of the actual one if possible. + private static String parseBuildTypeFromFingerprint() { + final String fingerprint = SystemProperties.get("ro.build.fingerprint"); + if (TextUtils.isEmpty(fingerprint)) { + return null; + } + Pattern fingerprintPattern = + Pattern.compile("(.*)\\/(.*)\\/(.*):(.*)\\/(.*)\\/(.*):(.*)\\/(.*)"); + Matcher matcher = fingerprintPattern.matcher(fingerprint); + return matcher.matches() ? matcher.group(7) : null; + } + + /** @hide */ + public static void adjustBuildTypeIfNeeded() { + if (UserHandle.isApp(Process.myUid()) && !TextUtils.isEmpty(TYPE_FOR_APPS)) { + try { + // This is sick. TYPE is final (which can't be changed because it's an API + // guarantee), but we have to reassign it. Resort to reflection to unset the + // final modifier, change the value and restore the final modifier afterwards. + Field typeField = Build.class.getField("TYPE"); + Field accessFlagsField = Field.class.getDeclaredField("accessFlags"); + accessFlagsField.setAccessible(true); + int currentFlags = accessFlagsField.getInt(typeField); + accessFlagsField.setInt(typeField, currentFlags & ~Modifier.FINAL); + typeField.set(null, TYPE_FOR_APPS); + accessFlagsField.setInt(typeField, currentFlags); + accessFlagsField.setAccessible(false); + } catch (Exception e) { + // shouldn't happen, but we don't want to crash the app even if it does happen + } + } + } + /** * Ensure that raw fingerprint system property is defined. If it was derived * dynamically by {@link #deriveFingerprint()} this is where we push the diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 2567a419a1c2b..a800ed624091d 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -56,7 +56,7 @@ public class Environment { private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage"); private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem"); private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); - private static final File DIR_PREBUNDLED_ROOT = getDirectory(ENV_PREBUNDLED_ROOT, "/vendor/bundled-app"); + private static final File DIR_PREBUNDLED_ROOT = getDirectory(ENV_PREBUNDLED_ROOT, "/bundled-app"); private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; diff --git a/core/java/android/os/IBatteryPropertiesRegistrar.aidl b/core/java/android/os/IBatteryPropertiesRegistrar.aidl index fd01802a42168..43b9650c7b2e1 100644 --- a/core/java/android/os/IBatteryPropertiesRegistrar.aidl +++ b/core/java/android/os/IBatteryPropertiesRegistrar.aidl @@ -1,5 +1,6 @@ /* ** Copyright 2013, The Android Open Source Project +** Copyright 2016, The CyanogenMod Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -27,4 +28,5 @@ interface IBatteryPropertiesRegistrar { void registerListener(IBatteryPropertiesListener listener); void unregisterListener(IBatteryPropertiesListener listener); int getProperty(in int id, out BatteryProperty prop); + int getDockProperty(in int id, out BatteryProperty prop); } diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index cd84c8fbc9e49..aa3921a00679c 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -440,4 +440,7 @@ interface INetworkManagementService void addInterfaceToLocalNetwork(String iface, in List routes); void removeInterfaceFromLocalNetwork(String iface); + + void restrictAppOnData(int uid, boolean restrict); + void restrictAppOnWlan(int uid, boolean restrict); } diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 38037a6e8e0f3..39c12f01f5bb2 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -116,6 +116,12 @@ public static boolean isInteractive(int wakefulness) { */ public abstract void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis); + /** + * Used by the window manager to tell the power manager that the user is no longer actively + * using the device. + */ + public abstract void setUserInactiveOverrideFromWindowManager(); + /** * Used by device administration to set the maximum screen off timeout. * diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 65b09eb7addc9..02466cc231916 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -539,6 +539,15 @@ private static ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList args) throws ZygoteStartFailedEx { try { + // Throw early if any of the arguments are malformed. This means we can + // avoid writing a partial response to the zygote. + int sz = args.size(); + for (int i = 0; i < sz; i++) { + if (args.get(i).indexOf('\n') >= 0) { + throw new ZygoteStartFailedEx("embedded newlines not allowed"); + } + } + /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: @@ -555,13 +564,8 @@ private static ProcessStartResult zygoteSendArgsAndGetResult( writer.write(Integer.toString(args.size())); writer.newLine(); - int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); - if (arg.indexOf('\n') >= 0) { - throw new ZygoteStartFailedEx( - "embedded newlines not allowed"); - } writer.write(arg); writer.newLine(); } @@ -570,11 +574,16 @@ private static ProcessStartResult zygoteSendArgsAndGetResult( // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); + + // Always read the entire result from the input stream to avoid leaving + // bytes in the stream for future process starts to accidentally stumble + // upon. result.pid = inputStream.readInt(); + result.usingWrapper = inputStream.readBoolean(); + if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } - result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 4b6e6c18e0500..d277e65cb990f 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -335,22 +335,27 @@ public static void installPackage(Context context, File packageFile) throws IOException { String filename = packageFile.getCanonicalPath(); - FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE); - try { - uncryptFile.write(filename + "\n"); - } finally { - uncryptFile.close(); - } - // UNCRYPT_FILE needs to be readable by system server on bootup. - if (!UNCRYPT_FILE.setReadable(true, false)) { - Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath()); - } - Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!"); + final String cryptoStatus = SystemProperties.get("ro.crypto.state", "unsupported"); + final boolean isEncrypted = "encrypted".equalsIgnoreCase(cryptoStatus); - // If the package is on the /data partition, write the block map file - // into COMMAND_FILE instead. - if (filename.startsWith("/data/")) { - filename = "@/cache/recovery/block.map"; + if (isEncrypted) { + FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE); + try { + uncryptFile.write(filename + "\n"); + } finally { + uncryptFile.close(); + } + // UNCRYPT_FILE needs to be readable by system server on bootup. + if (!UNCRYPT_FILE.setReadable(true, false)) { + Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath()); + } + Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!"); + + // If the package is on the /data partition, write the block map file + // into COMMAND_FILE instead. + if (filename.startsWith("/data/")) { + filename = "@/cache/recovery/block.map"; + } } final String filenameArg = "--update_package=" + filename; @@ -372,18 +377,18 @@ public static void installPackage(Context context, File packageFile) * @throws SecurityException if the current user is not allowed to wipe data. */ public static void rebootWipeUserData(Context context) throws IOException { - rebootWipeUserData(context, false, context.getPackageName(), false); + rebootWipeUserData(context, false, context.getPackageName(), true); } /** {@hide} */ public static void rebootWipeUserData(Context context, String reason) throws IOException { - rebootWipeUserData(context, false, reason, false); + rebootWipeUserData(context, false, reason, true); } /** {@hide} */ public static void rebootWipeUserData(Context context, boolean shutdown) throws IOException { - rebootWipeUserData(context, shutdown, context.getPackageName(), false); + rebootWipeUserData(context, shutdown, context.getPackageName(), true); } /** diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index f10b982af750b..f76a7c242e8e5 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1928,9 +1928,9 @@ private static class LogStackTrace extends Exception {} // so we'll report it and bail on all of the current strict mode violations // we currently are maintaining for this thread. // First, drain the remaining violations from the parcel. - while (i < numViolations) { + i++; // Skip the current entry. + for (; i < numViolations; i++) { info = new ViolationInfo(p, !currentlyGathering); - i++; } // Next clear out all gathered violations. clearGatheredViolations(); diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java index 81c0595338e13..c730329bc76f0 100644 --- a/core/java/android/preference/RingtonePreference.java +++ b/core/java/android/preference/RingtonePreference.java @@ -51,6 +51,7 @@ public class RingtonePreference extends Preference implements private int mDialogStyle; private int mRequestCode; + private int mSubscriptionID = 0; /* Sub-1 by default */ public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -100,6 +101,28 @@ public void setRingtoneType(int type) { mRingtoneType = type; } + /** + * Returns the subscription ID. + * + * @return The current subscription ID. + * @see #setSubId(int) + * @hide + */ + public int getSubId() { + return mSubscriptionID; + } + + /** + * Sets the subscription ID. + * + * @param subId subscription ID. + * @see #getSubId(int) + * @hide + */ + public void setSubId(int subId) { + mSubscriptionID = subId; + } + /** * Returns whether to a show an item for the default sound/ringtone. * @@ -187,8 +210,13 @@ protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) { ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault); if (mShowDefault) { - ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, + if (getRingtoneType() == RingtoneManager.TYPE_RINGTONE) { + ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, + RingtoneManager.getActualRingtoneUriBySubId(getContext(), getSubId())); + } else { + ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(getRingtoneType())); + } } if (mDialogStyle != 0) { ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DIALOG_THEME, diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 2445bc28abd8b..e5f71a00f8a54 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -59,6 +59,7 @@ public interface Callback { private final NotificationManager mNotificationManager; private final int mStreamType; private final int mMaxStreamVolume; + private final boolean mVoiceCapable; private boolean mAffectedByRingerMode; private boolean mNotificationOrRing; private final Receiver mReceiver = new Receiver(); @@ -110,12 +111,19 @@ public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callbac } } mDefaultUri = defaultUri; + mVoiceCapable = context.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable); } private static boolean isNotificationOrRing(int stream) { return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION; } + private boolean isNotificationStreamLinked() { + return mVoiceCapable && Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1; + } + public void setSeekBar(SeekBar seekBar) { if (mSeekBar != null) { mSeekBar.setOnSeekBarChangeListener(null); @@ -139,13 +147,19 @@ protected void updateSeekBar() { mSeekBar.setProgress(mLastAudibleStreamVolume); } else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { mSeekBar.setProgress(0); + mSeekBar.setEnabled(mStreamType == AudioManager.STREAM_RING); } else if (mMuted) { mSeekBar.setProgress(0); } else { + mSeekBar.setEnabled(enableSeekBar()); mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume); } } + private boolean enableSeekBar() { + return !(mStreamType == AudioManager.STREAM_NOTIFICATION && isNotificationStreamLinked()); + } + @Override public boolean handleMessage(Message msg) { switch (msg.what) { @@ -250,7 +264,7 @@ public void revertVolume() { } public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { - if (fromTouch) { + if (fromTouch && enableSeekBar()) { postSetVolume(progress); } if (mCallback != null) { @@ -398,10 +412,11 @@ public void onReceive(Context context, Intent intent) { int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); updateVolumeSlider(streamType, streamValue); } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { + final int oldRingerMode = mRingerMode; if (mNotificationOrRing) { mRingerMode = mAudioManager.getRingerModeInternal(); } - if (mAffectedByRingerMode) { + if (mAffectedByRingerMode && oldRingerMode != mRingerMode) { updateSlider(); } } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) { @@ -415,7 +430,8 @@ public void onReceive(Context context, Intent intent) { } private void updateVolumeSlider(int streamType, int streamValue) { - final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType) + final boolean streamMatch = mNotificationOrRing && isNotificationStreamLinked() + ? isNotificationOrRing(streamType) : (streamType == mStreamType); if (mSeekBar != null && streamMatch && streamValue != -1) { final boolean muted = mAudioManager.isStreamMute(mStreamType) diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 3a3eca4417ce5..f6c68dde672eb 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -27,6 +27,7 @@ import android.location.Country; import android.location.CountryDetector; import android.net.Uri; +import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.CommonDataKinds.Callable; @@ -400,6 +401,12 @@ public static class Calls implements BaseColumns { */ private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10; + /** + * If a call has an origin inside of the OS, this column will be filled out. + *

Type: String

+ */ + private static final String ORIGIN = "origin"; + /** * Adds a call to the call log. * @@ -417,15 +424,16 @@ public static class Calls implements BaseColumns { * @param duration call duration in seconds * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for * the call. + * @param callExtras Bundle of extra data from the call. * @result The URI of the call log entry belonging to the user that made or received this * call. * {@hide} */ public static Uri addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, - long start, int duration, Long dataUsage) { + long start, int duration, Long dataUsage, Bundle callExtras) { return addCall(ci, context, number, presentation, callType, features, accountHandle, - start, duration, dataUsage, false, false); + start, duration, dataUsage, false, false, callExtras); } @@ -448,16 +456,17 @@ public static Uri addCall(CallerInfo ci, Context context, String number, * the call. * @param addForAllUsers If true, the call is added to the call log of all currently * running users. The caller must have the MANAGE_USERS permission if this is true. - * + * @param callExtras Bundle of extra data from the call. * @result The URI of the call log entry belonging to the user that made or received this * call. * {@hide} */ public static Uri addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, - long start, int duration, Long dataUsage, boolean addForAllUsers) { + long start, int duration, Long dataUsage, boolean addForAllUsers, + Bundle callExtras) { return addCall(ci, context, number, presentation, callType, features, accountHandle, - start, duration, dataUsage, addForAllUsers, false); + start, duration, dataUsage, addForAllUsers, false, callExtras); } /** @@ -481,6 +490,7 @@ public static Uri addCall(CallerInfo ci, Context context, String number, * running users. The caller must have the MANAGE_USERS permission if this is true. * @param is_read Flag to show if the missed call log has been read by the user or not. * Used for call log restore of missed calls. + * @param callExtras Bundle of extra data from the call. * * @result The URI of the call log entry belonging to the user that made or received this * call. @@ -488,7 +498,8 @@ public static Uri addCall(CallerInfo ci, Context context, String number, */ public static Uri addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, - long start, int duration, Long dataUsage, boolean addForAllUsers, boolean is_read) { + long start, int duration, Long dataUsage, boolean addForAllUsers, boolean is_read, + Bundle callExtras) { final ContentResolver resolver = context.getContentResolver(); int numberPresentation = PRESENTATION_ALLOWED; @@ -547,6 +558,9 @@ public static Uri addCall(CallerInfo ci, Context context, String number, if (dataUsage != null) { values.put(DATA_USAGE, dataUsage); } + if (callExtras != null && callExtras.containsKey(PhoneConstants.EXTRA_CALL_ORIGIN)) { + values.put(ORIGIN, callExtras.getString(PhoneConstants.EXTRA_CALL_ORIGIN)); + } values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString); values.put(PHONE_ACCOUNT_ID, accountId); values.put(PHONE_ACCOUNT_ADDRESS, accountAddress); diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java index b2d9b934d79b0..961eb19228c95 100644 --- a/core/java/android/provider/Downloads.java +++ b/core/java/android/provider/Downloads.java @@ -592,6 +592,11 @@ public static boolean isStatusCompleted(int status) { */ public static final int STATUS_QUEUED_FOR_WIFI = 196; + /** + * This download is paused by manual. + */ + public static final int STATUS_PAUSED_BY_MANUAL = 197; + /** * This download couldn't be completed due to insufficient storage * space. Typically, this is because the SD card is full. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e107fd1272660..3ab16fe7a39cf 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -658,6 +658,19 @@ public final class Settings { public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; + /** + * @hide + * Activity Action: Show the "app ops" details screen. + *

+ * Input: The Intent's data URI specifies the application package name + * to be shown, with the "package" scheme. That is "package:com.my.app". + *

+ * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_APP_OPS_DETAILS_SETTINGS = + "android.settings.APP_OPS_DETAILS_SETTINGS"; + /** * @hide * Activity Action: Show the "app ops" settings screen. @@ -1496,10 +1509,10 @@ public static interface Validator { // At one time in System, then Global, but now back in Secure MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS); - MOVED_TO_SECURE.add(System.DEV_FORCE_SHOW_NAVBAR); MOVED_TO_SECURE.add(System.KEYBOARD_BRIGHTNESS); MOVED_TO_SECURE.add(System.BUTTON_BRIGHTNESS); MOVED_TO_SECURE.add(System.BUTTON_BACKLIGHT_TIMEOUT); + MOVED_TO_SECURE.add(Secure.VOLUME_LINK_NOTIFICATION); } private static final HashSet MOVED_TO_GLOBAL; @@ -1694,9 +1707,8 @@ public static boolean putStringForUser(ContentResolver resolver, String name, St } if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" - + " to android.provider.Settings.Global."); - - return Global.putStringForUser(resolver, name, value, userHandle); + + " to android.provider.Settings.Global, value is unchanged."); + return false; } return sNameValueCache.putStringForUser(resolver, name, value, userHandle); } @@ -2766,6 +2778,30 @@ public boolean validate(String value) { private static final Validator RINGTONE_VALIDATOR = sUriValidator; + /** + * Persistent store for the SIM-2 ringtone URI. + *

+ * If you need to play SIM-2 ringtone at any given time, it is recommended + * you give {@link #DEFAULT_RINGTONE_URI_2} to the media player. It will resolve + * to the set default ringtone at the time of playing. + * + * @see #DEFAULT_RINGTONE_URI_2 + * @hide + */ + public static final String RINGTONE_2 = "ringtone_2"; + + /** + * Persistent store for the SIM-3 ringtone URI. + *

+ * If you need to play SIM-3 ringtone at any given time, it is recommended + * you give {@link #DEFAULT_RINGTONE_URI_3} to the media player. It will resolve + * to the set default ringtone at the time of playing. + * + * @see #DEFAULT_RINGTONE_URI_3 + * @hide + */ + public static final String RINGTONE_3 = "ringtone_3"; + /** * A {@link Uri} that will point to the current default ringtone at any * given time. @@ -2776,6 +2812,39 @@ public boolean validate(String value) { */ public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE); + /** + * A {@link Uri} that will point to the current SIM-2 ringtone at any + * given time. + *

+ * If the current default ringtone is in the DRM provider and the caller + * does not have permission, the exception will be a + * FileNotFoundException. + * + * @hide + */ + public static final Uri DEFAULT_RINGTONE_URI_2 = getUriFor(RINGTONE_2); + + /** + * A {@link Uri} that will point to the current SIM-3 ringtone at any + * given time. + *

+ * If the current default ringtone is in the DRM provider and the caller + * does not have permission, the exception will be a + * FileNotFoundException. + * + * @hide + */ + public static final Uri DEFAULT_RINGTONE_URI_3 = getUriFor(RINGTONE_3); + + /** + * Maximum number of ringtones supported. + *

+ * Maximum number of ringtones supported by settings. Increment this + * if a new URI needs to be added for ringtone. + * @hide + */ + public static final int MAX_NUM_RINGTONES = 3; + /** * Persistent store for the system-wide default notification sound. * @@ -3460,6 +3529,13 @@ public boolean validate(String value) { */ public static final String VOICE_LAUNCH_INTENT = "voice_launch_intent"; + /** + * Volume key controls ringtone or media sound stream + * @hide + */ + public static final String VOLUME_KEYS_CONTROL_RING_STREAM = + "volume_keys_control_ring_stream"; + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. @@ -6032,6 +6108,11 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val public static final String CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED = "camera_double_tap_power_gesture_disabled"; + /** + * Boolean value whether to link ringtone and notification volume + * @hide + */ + public static final String VOLUME_LINK_NOTIFICATION = "volume_link_notification"; /** * This are the settings to be backed up. @@ -6355,6 +6436,25 @@ public static final class Global extends NameValueTable { */ public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios"; + /** + * A Long representing a bitmap of profiles that should be disabled when bluetooth starts. + * See {@link android.bluetooth.BluetoothProfile}. + * {@hide} + */ + public static final String BLUETOOTH_DISABLED_PROFILES = "bluetooth_disabled_profiles"; + + /** + * A semi-colon separated list of Bluetooth interoperability workarounds. + * Each entry is a partial Bluetooth device address string and an integer representing + * the feature to be disabled, separated by a comma. The integer must correspond + * to a interoperability feature as defined in "interop.h" in /system/bt. + *

+ * Example:
+ * "00:11:22,0;01:02:03:04,2" + * @hide + */ + public static final String BLUETOOTH_INTEROPERABILITY_LIST = "bluetooth_interoperability_list"; + /** * The policy for deciding when Wi-Fi should go to sleep (which will in * turn switch to using the mobile data as an Internet connection). @@ -7611,10 +7711,12 @@ public static final class Global extends NameValueTable { * The following keys are supported: * *

-         * idle_duration        (long)
+         * idle_duration2       (long)
          * wallclock_threshold  (long)
          * parole_interval      (long)
          * parole_duration      (long)
+         *
+         * idle_duration        (long) // This is deprecated and used to circumvent b/26355386.
          * 
* *

@@ -8059,6 +8161,13 @@ public static final String getBluetoothSapPriorityKey(String address) { */ public static final String LTE_SERVICE_FORCED = "lte_service_forced"; + /** + * Whether to ignore the representation of outgoing calls set by the network. + * + * @hide + */ + public static final String CONNECTED_LINE_IDENTIFICATION = "connected_line_identification"; + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. @@ -8485,6 +8594,13 @@ public static boolean putFloat(ContentResolver cr, String name, float value) { * @hide */ public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync"; + + /** + * Whether to enable cellular on boot. + * The value 1 - enable, 0 - disable + * @hide + */ + public static final String ENABLE_CELLULAR_ON_BOOT = "enable_cellular_on_boot"; } /** diff --git a/core/java/android/provider/ThemesContract.java b/core/java/android/provider/ThemesContract.java deleted file mode 100644 index af7ab26890556..0000000000000 --- a/core/java/android/provider/ThemesContract.java +++ /dev/null @@ -1,731 +0,0 @@ -package android.provider; - -import android.net.Uri; - -/** - * @hide - */ -public class ThemesContract { - public static final String AUTHORITY = "com.cyanogenmod.themes"; - public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); - - public static class ThemesColumns { - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "themes"); - - /** - * The unique ID for a row. - *

Type: INTEGER (long)

- */ - public static final String _ID = "_id"; - - /** - * The user visible title. - *

Type: TEXT

- */ - public static final String TITLE = "title"; - - /** - * Unique text to identify the apk pkg. ie "com.foo.bar" - *

Type: TEXT

- */ - public static final String PKG_NAME = "pkg_name"; - - /** - * A 32 bit RRGGBB color representative of the themes color scheme - *

Type: INTEGER

- */ - public static final String PRIMARY_COLOR = "primary_color"; - - /** - * A 2nd 32 bit RRGGBB color representative of the themes color scheme - *

Type: INTEGER

- */ - public static final String SECONDARY_COLOR = "secondary_color"; - - /** - * Name of the author of the theme - *

Type: TEXT

- */ - public static final String AUTHOR = "author"; - - /** - * The time that this row was created on its originating client (msecs - * since the epoch). - *

Type: INTEGER

- */ - public static final String DATE_CREATED = "created"; - - /** - * URI to an image that shows the homescreen with the theme applied - * since the epoch). - *

Type: TEXT

- */ - public static final String HOMESCREEN_URI = "homescreen_uri"; - - /** - * URI to an image that shows the lockscreen with theme applied - *

Type: TEXT

- */ - public static final String LOCKSCREEN_URI = "lockscreen_uri"; - - /** - * URI to an image that shows the style (aka skin) with theme applied - *

Type: TEXT

- */ - public static final String STYLE_URI = "style_uri"; - - /** - * TODO: Figure structure for actual animation instead of static - * URI to an image of the boot_anim. - *

Type: TEXT

- */ - public static final String BOOT_ANIM_URI = "bootanim_uri"; - - /** - * URI to an image of the status bar for this theme. - *

Type: TEXT

- */ - public static final String STATUSBAR_URI = "status_uri"; - - /** - * URI to an image of the fonts in this theme. - *

Type: TEXT

- */ - public static final String FONT_URI = "font_uri"; - - /** - * URI to an image of the fonts in this theme. - *

Type: TEXT

- */ - public static final String ICON_URI = "icon_uri"; - - /** - * URI to an image of the fonts in this theme. - *

Type: TEXT

- */ - public static final String OVERLAYS_URI = "overlays_uri"; - - /** - * 1 if theme modifies the launcher/homescreen else 0 - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_LAUNCHER = "mods_homescreen"; - - /** - * 1 if theme modifies the lockscreen else 0 - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_LOCKSCREEN = "mods_lockscreen"; - - /** - * 1 if theme modifies icons else 0 - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_ICONS = "mods_icons"; - - /** - * 1 if theme modifies fonts - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_FONTS = "mods_fonts"; - - /** - * 1 if theme modifies boot animation - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_BOOT_ANIM = "mods_bootanim"; - - /** - * 1 if theme modifies notifications - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_NOTIFICATIONS = "mods_notifications"; - - /** - * 1 if theme modifies alarm sounds - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_ALARMS = "mods_alarms"; - - /** - * 1 if theme modifies ringtones - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_RINGTONES = "mods_ringtones"; - - /** - * 1 if theme has overlays - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_OVERLAYS = "mods_overlays"; - - /** - * 1 if theme has an overlay for SystemUI/StatusBar - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_STATUS_BAR = "mods_status_bar"; - - /** - * 1 if theme has an overlay for SystemUI/NavBar - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_NAVIGATION_BAR = "mods_navigation_bar"; - - /** - * 1 if theme has a live lock screen - *

Type: INTEGER

- *

Default: 0

- */ - public static final String MODIFIES_LIVE_LOCK_SCREEN = "mods_live_lock_screen"; - - /** - * URI to the theme's wallpaper. We should support multiple wallpaper - * but for now we will just have 1. - *

Type: TEXT

- */ - public static final String WALLPAPER_URI = "wallpaper_uri"; - - /** - * 1 if this row should actually be presented as a theme to the user. - * For example if a "theme" only modifies one component (ex icons) then - * we do not present it to the user under the themes table. - *

Type: INTEGER

- *

Default: 0

- */ - public static final String PRESENT_AS_THEME = "present_as_theme"; - - /** - * 1 if this theme is a legacy theme. - *

Type: INTEGER

- *

Default: 0

- */ - public static final String IS_LEGACY_THEME = "is_legacy_theme"; - - /** - * 1 if this theme is the system default theme. - *

Type: INTEGER

- *

Default: 0

- */ - public static final String IS_DEFAULT_THEME = "is_default_theme"; - - /** - * 1 if this theme is a legacy iconpack. A legacy icon pack is an APK that was written - * for Trebuchet or a 3rd party launcher. - *

Type: INTEGER

- *

Default: 0

- */ - public static final String IS_LEGACY_ICONPACK = "is_legacy_iconpack"; - - /** - * install/update time in millisecs. When the row is inserted this column - * is populated by the PackageInfo. It is used for syncing to PM - *

Type: INTEGER

- *

Default: 0

- */ - public static final String LAST_UPDATE_TIME = "updateTime"; - - /** - * install time in millisecs. When the row is inserted this column - * is populated by the PackageInfo. - *

Type: INTEGER

- *

Default: 0

- */ - public static final String INSTALL_TIME = "install_time"; - - /** - * The target API this theme supports - * is populated by the PackageInfo. - *

Type: INTEGER

- *

Default: 0

- */ - public static final String TARGET_API = "target_api"; - - /** - * The install state of the theme. - * Can be one of the following: - * {@link InstallState#UNKNOWN} - * {@link InstallState#INSTALLING} - * {@link InstallState#UPDATING} - * {@link InstallState#INSTALLED} - *

Type: INTEGER

- *

Default: 0

- */ - public static final String INSTALL_STATE = "install_state"; - - public static class InstallState { - public static final int UNKNOWN = 0; - public static final int INSTALLING = 1; - public static final int UPDATING = 2; - public static final int INSTALLED = 3; - } - } - - /** - * Key-value table which assigns a component (ex wallpaper) to a theme's package - */ - public static class MixnMatchColumns { - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "mixnmatch"); - - /** - * The unique key for a row. See the KEY_* constants - * for valid examples - *

Type: TEXT

- */ - public static final String COL_KEY = "key"; - - /** - * The package name that corresponds to a given component. - *

Type: String

- */ - public static final String COL_VALUE = "value"; - - /** - * The package name that corresponds to where this component was applied from previously - *

Type: String

- */ - public static final String COL_PREV_VALUE = "previous_value"; - - /** - * Time when this entry was last updated - *

Type: INTEGER

- */ - public static final String COL_UPDATE_TIME = "update_time"; - - /* - * The unique ID for the component within a theme. - * Always 0 unless multiples of a component exist. - *

Type: INTEGER (long)

- */ - public static final String COL_COMPONENT_ID = "component_id"; - - /** - * Valid keys - */ - public static final String KEY_HOMESCREEN = "mixnmatch_homescreen"; - public static final String KEY_LOCKSCREEN = "mixnmatch_lockscreen"; - public static final String KEY_ICONS = "mixnmatch_icons"; - public static final String KEY_STATUS_BAR = "mixnmatch_status_bar"; - public static final String KEY_BOOT_ANIM = "mixnmatch_boot_anim"; - public static final String KEY_FONT = "mixnmatch_font"; - public static final String KEY_ALARM = "mixnmatch_alarm"; - public static final String KEY_NOTIFICATIONS = "mixnmatch_notifications"; - public static final String KEY_RINGTONE = "mixnmatch_ringtone"; - public static final String KEY_OVERLAYS = "mixnmatch_overlays"; - public static final String KEY_NAVIGATION_BAR = "mixnmatch_navigation_bar"; - public static final String KEY_LIVE_LOCK_SCREEN = "mixnmatch_live_lock_screen"; - - public static final String[] ROWS = { KEY_HOMESCREEN, - KEY_LOCKSCREEN, - KEY_ICONS, - KEY_STATUS_BAR, - KEY_BOOT_ANIM, - KEY_FONT, - KEY_NOTIFICATIONS, - KEY_RINGTONE, - KEY_ALARM, - KEY_OVERLAYS, - KEY_NAVIGATION_BAR, - KEY_LIVE_LOCK_SCREEN - }; - - /** - * For a given key value in the MixNMatch table, return the column - * associated with it in the Themes Table. This is useful for URI based - * elements like wallpaper where the caller wishes to determine the - * wallpaper URI. - */ - public static String componentToImageColName(String component) { - if (component.equals(MixnMatchColumns.KEY_HOMESCREEN)) { - return ThemesColumns.HOMESCREEN_URI; - } else if (component.equals(MixnMatchColumns.KEY_LOCKSCREEN)) { - return ThemesColumns.LOCKSCREEN_URI; - } else if (component.equals(MixnMatchColumns.KEY_BOOT_ANIM)) { - return ThemesColumns.BOOT_ANIM_URI; - } else if (component.equals(MixnMatchColumns.KEY_FONT)) { - return ThemesColumns.FONT_URI; - } else if (component.equals(MixnMatchColumns.KEY_ICONS)) { - return ThemesColumns.ICON_URI; - } else if (component.equals(MixnMatchColumns.KEY_STATUS_BAR)) { - return ThemesColumns.STATUSBAR_URI; - } else if (component.equals(MixnMatchColumns.KEY_NOTIFICATIONS)) { - throw new IllegalArgumentException("Notifications mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_RINGTONE)) { - throw new IllegalArgumentException("Ringtone mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_OVERLAYS)) { - return ThemesColumns.OVERLAYS_URI; - } else if (component.equals(MixnMatchColumns.KEY_STATUS_BAR)) { - throw new IllegalArgumentException( - "Status bar mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_NAVIGATION_BAR)) { - throw new IllegalArgumentException( - "Navigation bar mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_LIVE_LOCK_SCREEN)) { - throw new IllegalArgumentException( - "Live lock screen mixnmatch component does not have a related column"); - } - return null; - } - - /** - * A component in the themes table (IE "mods_wallpaper") has an - * equivalent key in mixnmatch table - */ - public static String componentToMixNMatchKey(String component) { - if (component.equals(ThemesColumns.MODIFIES_LAUNCHER)) { - return MixnMatchColumns.KEY_HOMESCREEN; - } else if (component.equals(ThemesColumns.MODIFIES_ICONS)) { - return MixnMatchColumns.KEY_ICONS; - } else if (component.equals(ThemesColumns.MODIFIES_LOCKSCREEN)) { - return MixnMatchColumns.KEY_LOCKSCREEN; - } else if (component.equals(ThemesColumns.MODIFIES_FONTS)) { - return MixnMatchColumns.KEY_FONT; - } else if (component.equals(ThemesColumns.MODIFIES_BOOT_ANIM)) { - return MixnMatchColumns.KEY_BOOT_ANIM; - } else if (component.equals(ThemesColumns.MODIFIES_ALARMS)) { - return MixnMatchColumns.KEY_ALARM; - } else if (component.equals(ThemesColumns.MODIFIES_NOTIFICATIONS)) { - return MixnMatchColumns.KEY_NOTIFICATIONS; - } else if (component.equals(ThemesColumns.MODIFIES_RINGTONES)) { - return MixnMatchColumns.KEY_RINGTONE; - } else if (component.equals(ThemesColumns.MODIFIES_OVERLAYS)) { - return MixnMatchColumns.KEY_OVERLAYS; - } else if (component.equals(ThemesColumns.MODIFIES_STATUS_BAR)) { - return MixnMatchColumns.KEY_STATUS_BAR; - } else if (component.equals(ThemesColumns.MODIFIES_NAVIGATION_BAR)) { - return MixnMatchColumns.KEY_NAVIGATION_BAR; - } else if (component.equals(ThemesColumns.MODIFIES_LIVE_LOCK_SCREEN)) { - return MixnMatchColumns.KEY_LIVE_LOCK_SCREEN; - } - return null; - } - - /** - * A mixnmatch key in has an - * equivalent value in the themes table - */ - public static String mixNMatchKeyToComponent(String mixnmatchKey) { - if (mixnmatchKey.equals(MixnMatchColumns.KEY_HOMESCREEN)) { - return ThemesColumns.MODIFIES_LAUNCHER; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_ICONS)) { - return ThemesColumns.MODIFIES_ICONS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_LOCKSCREEN)) { - return ThemesColumns.MODIFIES_LOCKSCREEN; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_FONT)) { - return ThemesColumns.MODIFIES_FONTS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_BOOT_ANIM)) { - return ThemesColumns.MODIFIES_BOOT_ANIM; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_ALARM)) { - return ThemesColumns.MODIFIES_ALARMS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_NOTIFICATIONS)) { - return ThemesColumns.MODIFIES_NOTIFICATIONS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_RINGTONE)) { - return ThemesColumns.MODIFIES_RINGTONES; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_OVERLAYS)) { - return ThemesColumns.MODIFIES_OVERLAYS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_STATUS_BAR)) { - return ThemesColumns.MODIFIES_STATUS_BAR; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_NAVIGATION_BAR)) { - return ThemesColumns.MODIFIES_NAVIGATION_BAR; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_LIVE_LOCK_SCREEN)) { - return ThemesColumns.MODIFIES_LIVE_LOCK_SCREEN; - } - return null; - } - } - - /** - * Table containing cached preview files for a given theme - */ - public static class PreviewColumns { - /** - * Uri for retrieving the previews table. - * Querying the themes provider using this URI will return a cursor with a key and value - * columns, and a row for each component. - */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "previews"); - - /** - * Uri for retrieving the previews for the currently applied components. - * Querying the themes provider using this URI will return a cursor with a single row - * containing all the previews for the components that are currently applied. - */ - public static final Uri APPLIED_URI = Uri.withAppendedPath(AUTHORITY_URI, - "applied_previews"); - - /** - * Uri for retrieving the default previews for the theme. - * Querying the themes provider using this URI will return a cursor with a single row - * containing all the previews for the default components of the current theme. - */ - public static final Uri COMPONENTS_URI = Uri.withAppendedPath(AUTHORITY_URI, - "components_previews"); - - /** - * The unique ID for a row. - *

Type: INTEGER (long)

- */ - public static final String _ID = "_id"; - - /** - * The unique ID for the theme these previews belong to. - *

Type: INTEGER (long)

- */ - public static final String THEME_ID = "theme_id"; - - /** - * The unique ID for the component within a theme. - *

Type: INTEGER (long)

- */ - public static final String COMPONENT_ID = "component_id"; - - /** - * The unique key for a row. See the Valid key constants section below - * for valid examples - *

Type: TEXT

- */ - public static final String COL_KEY = "key"; - - /** - * The package name that corresponds to a given component. - *

Type: String

- */ - public static final String COL_VALUE = "value"; - - /** - * Valid keys - */ - - /** - * Cached image of the themed status bar background. - *

Type: String (file path)

- */ - public static final String STATUSBAR_BACKGROUND = "statusbar_background"; - - /** - * Cached image of the themed bluetooth status icon. - *

Type: String (file path)

- */ - public static final String STATUSBAR_BLUETOOTH_ICON = "statusbar_bluetooth_icon"; - - /** - * Cached image of the themed wifi status icon. - *

Type: String (file path)

- */ - public static final String STATUSBAR_WIFI_ICON = "statusbar_wifi_icon"; - - /** - * Cached image of the themed cellular signal status icon. - *

Type: String (file path)

- */ - public static final String STATUSBAR_SIGNAL_ICON = "statusbar_signal_icon"; - - /** - * Cached image of the themed battery using portrait style. - *

Type: String (file path)

- */ - public static final String STATUSBAR_BATTERY_PORTRAIT = "statusbar_battery_portrait"; - - /** - * Cached image of the themed battery using landscape style. - *

Type: String (file path)

- */ - public static final String STATUSBAR_BATTERY_LANDSCAPE = "statusbar_battery_landscape"; - - /** - * Cached image of the themed battery using circle style. - *

Type: String (file path)

- */ - public static final String STATUSBAR_BATTERY_CIRCLE = "statusbar_battery_circle"; - - /** - * The themed color used for clock text in the status bar. - *

Type: INTEGER (int)

- */ - public static final String STATUSBAR_CLOCK_TEXT_COLOR = "statusbar_clock_text_color"; - - /** - * The themed margin value between the wifi and rssi signal icons. - *

Type: INTEGER (int)

- */ - public static final String STATUSBAR_WIFI_COMBO_MARGIN_END = "wifi_combo_margin_end"; - - /** - * Cached image of the themed navigation bar background. - *

Type: String (file path)

- */ - public static final String NAVBAR_BACKGROUND = "navbar_background"; - - /** - * Cached image of the themed back button. - *

Type: String (file path)

- */ - public static final String NAVBAR_BACK_BUTTON = "navbar_back_button"; - - /** - * Cached image of the themed home button. - *

Type: String (file path)

- */ - public static final String NAVBAR_HOME_BUTTON = "navbar_home_button"; - - /** - * Cached image of the themed recents button. - *

Type: String (file path)

- */ - public static final String NAVBAR_RECENT_BUTTON = "navbar_recent_button"; - - /** - * Cached image of the 1/3 icons - *

Type: String (file path)

- */ - public static final String ICON_PREVIEW_1 = "icon_preview_1"; - - /** - * Cached image of the 2/3 icons - *

Type: String (file path)

- */ - public static final String ICON_PREVIEW_2 = "icon_preview_2"; - - /** - * Cached image of the 3/3 icons - *

Type: String (file path)

- */ - public static final String ICON_PREVIEW_3 = "icon_preview_3"; - - /** - * Full path to the theme's wallpaper asset. - *

Type: String (file path)

- */ - public static final String WALLPAPER_FULL = "wallpaper_full"; - - /** - * Cached preview of the theme's wallpaper which is larger than the thumbnail - * but smaller than the full sized wallpaper. - *

Type: String (file path)

- */ - public static final String WALLPAPER_PREVIEW = "wallpaper_preview"; - - /** - * Cached thumbnail of the theme's wallpaper - *

Type: String (file path)

- */ - public static final String WALLPAPER_THUMBNAIL = "wallpaper_thumbnail"; - - /** - * Cached preview of the theme's lockscreen wallpaper which is larger than the thumbnail - * but smaller than the full sized lockscreen wallpaper. - *

Type: String (file path)

- */ - public static final String LOCK_WALLPAPER_PREVIEW = "lock_wallpaper_preview"; - - /** - * Cached thumbnail of the theme's lockscreen wallpaper - *

Type: String (file path)

- */ - public static final String LOCK_WALLPAPER_THUMBNAIL = "lock_wallpaper_thumbnail"; - - /** - * Cached preview of UI controls representing the theme's style - *

Type: String (file path)

- */ - public static final String STYLE_PREVIEW = "style_preview"; - - /** - * Cached thumbnail preview of UI controls representing the theme's style - *

Type: String (file path)

- */ - public static final String STYLE_THUMBNAIL = "style_thumbnail"; - - /** - * Cached thumbnail of the theme's boot animation - *

Type: String (file path)

- */ - public static final String BOOTANIMATION_THUMBNAIL = "bootanimation_thumbnail"; - - /** - * Cached preview of live lock screen - *

Type: String (file path)

- */ - public static final String LIVE_LOCK_SCREEN_PREVIEW = "live_lock_screen_preview"; - - /** - * Cached thumbnail preview of live lock screen - *

Type: String (file path)

- */ - public static final String LIVE_LOCK_SCREEN_THUMBNAIL = "live_lock_screen_thumbnail"; - - public static final String[] VALID_KEYS = { - STATUSBAR_BACKGROUND, - STATUSBAR_BLUETOOTH_ICON, - STATUSBAR_WIFI_ICON, - STATUSBAR_SIGNAL_ICON, - STATUSBAR_BATTERY_PORTRAIT, - STATUSBAR_BATTERY_LANDSCAPE, - STATUSBAR_BATTERY_CIRCLE, - STATUSBAR_CLOCK_TEXT_COLOR, - STATUSBAR_WIFI_COMBO_MARGIN_END, - NAVBAR_BACKGROUND, - NAVBAR_BACK_BUTTON, - NAVBAR_HOME_BUTTON, - NAVBAR_RECENT_BUTTON, - ICON_PREVIEW_1, - ICON_PREVIEW_2, - ICON_PREVIEW_3, - WALLPAPER_FULL, - WALLPAPER_PREVIEW, - WALLPAPER_THUMBNAIL, - LOCK_WALLPAPER_PREVIEW, - LOCK_WALLPAPER_THUMBNAIL, - STYLE_PREVIEW, - STYLE_THUMBNAIL, - BOOTANIMATION_THUMBNAIL, - LIVE_LOCK_SCREEN_PREVIEW, - LIVE_LOCK_SCREEN_THUMBNAIL, - }; - } - - public static class Intent { - /** - * Action sent from the provider when a theme has been fully installed. Fully installed - * means that the apk was installed by PackageManager and the theme resources were - * processed and cached by {@link com.android.server.ThemeService} - * Requires the {@link android.Manifest.permission#READ_THEMES} permission to receive - * this broadcast. - */ - public static final String ACTION_THEME_INSTALLED = - "themescontract.intent.action.THEME_INSTALLED"; - - /** - * Action sent from the provider when a theme has been updated. - * Requires the {@link android.Manifest.permission#READ_THEMES} permission to receive - * this broadcast. - */ - public static final String ACTION_THEME_UPDATED = - "themescontract.intent.action.THEME_UPDATED"; - - /** - * Action sent from the provider when a theme has been removed. - * Requires the {@link android.Manifest.permission#READ_THEMES} permission to receive - * this broadcast. - */ - public static final String ACTION_THEME_REMOVED = - "themescontract.intent.action.THEME_REMOVED"; - - /** - * Uri scheme used to broadcast the theme's package name when broadcasting - * {@link android.provider.ThemesContract.Intent#ACTION_THEME_INSTALLED} or - * {@link android.provider.ThemesContract.Intent#ACTION_THEME_REMOVED} - */ - public static final String URI_SCHEME_PACKAGE = "package"; - } -} diff --git a/core/java/android/service/gesture/EdgeGestureManager.java b/core/java/android/service/gesture/EdgeGestureManager.java deleted file mode 100644 index 7c0ab2e2cc8c8..0000000000000 --- a/core/java/android/service/gesture/EdgeGestureManager.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.service.gesture; - -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.service.gesture.IEdgeGestureActivationListener; -import android.service.gesture.IEdgeGestureHostCallback; -import android.service.gesture.IEdgeGestureService; -import android.util.Slog; - -import com.android.internal.util.gesture.EdgeGesturePosition; - -/** - * This is a simple Manager class for edge gesture service on the application side. The application need - * {@code INJECT_EVENTS} permission to register {@code EdgeGestureActivationListener}s.
- * See {@link android.service.gesture.IEdgeGestureService} for more information. - * - * @see android.service.gesture.IEdgeGestureService - * @hide - */ -public class EdgeGestureManager { - public static final String TAG = "EdgeGestureManager"; - public static final boolean DEBUG = false; - - private static EdgeGestureManager sInstance; - - private final IEdgeGestureService mPs; - - public static abstract class EdgeGestureActivationListener { - private Handler mHandler; - private IEdgeGestureHostCallback mCallback; - - private class Delegator extends IEdgeGestureActivationListener.Stub { - public void onEdgeGestureActivation(final int touchX, final int touchY, final int positionIndex, final int flags) - throws RemoteException { - mHandler.post(new Runnable() { - public void run() { - EdgeGestureActivationListener.this.onEdgeGestureActivation(touchX, touchY, EdgeGesturePosition.values()[positionIndex], flags); - } - }); - } - } - private Delegator mDelegator; - - public EdgeGestureActivationListener() { - this(Looper.getMainLooper()); - } - - public EdgeGestureActivationListener(Looper looper) { - mHandler = new Handler(looper); - mDelegator = new Delegator(); - } - - /* package */ void setHostCallback(IEdgeGestureHostCallback hostCallback) { - mCallback = hostCallback; - } - - /** - * Override this to receive activations from the edge gesture service. - * - * @param touchX the last X position a touch event was registered. - * @param touchY the last Y position a touch event was registered. - * @param position the position of the activation. - * @param flags currently 0. - * @see IEdgeGestureActivationListener#onEdgeGestureActivation(int, int, int, int) - */ - public abstract void onEdgeGestureActivation(int touchX, int touchY, EdgeGesturePosition position, int flags); - - /** - * After being activated, this allows the edge gesture control to steal focus from the current - * window. - * - * @see IEdgeGestureHostCallback#gainTouchFocus(IBinder) - */ - public boolean gainTouchFocus(IBinder applicationWindowToken) { - try { - return mCallback.gainTouchFocus(applicationWindowToken); - } catch (RemoteException e) { - Slog.w(TAG, "gainTouchFocus failed: " + e.getMessage()); - /* fall through */ - } - return false; - } - - public boolean dropEventsUntilLift() { - try { - return mCallback.dropEventsUntilLift(); - } catch (RemoteException e) { - Slog.w(TAG, "dropNextEvents failed: " + e.getMessage()); - /* fall through */ - } - return false; - } - - /** - * Turns listening for edge gesture activation gestures on again, after it was disabled during - * the call to the listener. - * - * @see IEdgeGestureHostCallback#restoreListenerState() - */ - public void restoreListenerState() { - if (DEBUG) { - Slog.d(TAG, "restore listener state: " + Thread.currentThread().getName()); - } - try { - mCallback.restoreListenerState(); - } catch (RemoteException e) { - Slog.w(TAG, "restoreListenerState failed: " + e.getMessage()); - /* fall through */ - } - } - } - - private EdgeGestureManager(IEdgeGestureService ps) { - mPs = ps; - } - - /** - * Gets an instance of the edge gesture manager. - * - * @return The edge gesture manager instance. - * @hide - */ - public static EdgeGestureManager getInstance() { - synchronized (EdgeGestureManager.class) { - if (sInstance == null) { - IBinder b = ServiceManager.getService("edgegestureservice"); - sInstance = new EdgeGestureManager(IEdgeGestureService.Stub.asInterface(b)); - } - return sInstance; - } - } - - /** - * Checks if the edge gesture service is present. - *

- * Since the service is only started at boot time and is bound to the system server, this - * is constant for the devices up time. - * - * @return {@code true} when the edge gesture service is running on this device. - * @hide - */ - public boolean isPresent() { - return mPs != null; - } - - /** - * Register a listener for edge gesture activation gestures. Initially the listener - * is set to listen for no position. Use updateedge gestureActivationListener() to - * bind the listener to positions. - * - * @param listener is the activation listener. - * @return {@code true} if the registration was successful. - * @hide - */ - public boolean setEdgeGestureActivationListener(EdgeGestureActivationListener listener) { - if (DEBUG) { - Slog.d(TAG, "Set edge gesture activation listener"); - } - try { - IEdgeGestureHostCallback callback = mPs.registerEdgeGestureActivationListener(listener.mDelegator); - listener.setHostCallback(callback); - return true; - } catch (RemoteException e) { - Slog.e(TAG, "Failed to set edge gesture activation listener: " + e.getMessage()); - return false; - } - } - - /** - * Update the listener to react on gestures in the given positions. - * - * @param listener is a already registered listener. - * @param positions is a bit mask describing the positions to listen to. - * @hide - */ - public void updateEdgeGestureActivationListener(EdgeGestureActivationListener listener, int positions) { - if (DEBUG) { - Slog.d(TAG, "Update edge gesture activation listener: 0x" + Integer.toHexString(positions)); - } - try { - mPs.updateEdgeGestureActivationListener(listener.mDelegator.asBinder(), positions); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to update edge gesture activation listener: " + e.getMessage()); - } - } - -} diff --git a/core/java/android/service/gesture/IEdgeGestureActivationListener.aidl b/core/java/android/service/gesture/IEdgeGestureActivationListener.aidl deleted file mode 100644 index 0c9b24a8ae3d1..0000000000000 --- a/core/java/android/service/gesture/IEdgeGestureActivationListener.aidl +++ /dev/null @@ -1,14 +0,0 @@ - -package android.service.gesture; - -import android.view.InputEvent; - -/** @hide */ -interface IEdgeGestureActivationListener { - - /** Called when a gesture is detected that fits to the activation gesture. At this point in - * time gesture detection is disabled. Call IEdgeGestureHostCallback.restoreState() to - * recover from this. - */ - oneway void onEdgeGestureActivation(int touchX, int touchY, int positionIndex, int flags); -} \ No newline at end of file diff --git a/core/java/android/service/gesture/IEdgeGestureHostCallback.aidl b/core/java/android/service/gesture/IEdgeGestureHostCallback.aidl deleted file mode 100644 index c2615503e4fc3..0000000000000 --- a/core/java/android/service/gesture/IEdgeGestureHostCallback.aidl +++ /dev/null @@ -1,20 +0,0 @@ -package android.service.gesture; - -/** @hide */ -interface IEdgeGestureHostCallback { - - /** After being activated, this allows to steal focus from the current - * window - */ - boolean gainTouchFocus(IBinder windowToken); - - /** Turns listening for activation gestures on again, after it was disabled during - * the call to the listener. - */ - oneway void restoreListenerState(); - - /* - * Tells filter to drop all events till touch up - */ - boolean dropEventsUntilLift(); -} \ No newline at end of file diff --git a/core/java/android/service/gesture/IEdgeGestureService.aidl b/core/java/android/service/gesture/IEdgeGestureService.aidl deleted file mode 100644 index 342cf71aa32bf..0000000000000 --- a/core/java/android/service/gesture/IEdgeGestureService.aidl +++ /dev/null @@ -1,20 +0,0 @@ -package android.service.gesture; - -import android.service.gesture.IEdgeGestureActivationListener; -import android.service.gesture.IEdgeGestureHostCallback; - -/** @hide */ -interface IEdgeGestureService { - - /** Register a listener for activation gestures. Initially the listener - * is set to listen for no position. Use updateEdgeGestureActivationListener() to - * bind the listener to positions. - * Use the returned IEdgeGestureHostCallback to manipulate the state after activation. - */ - IEdgeGestureHostCallback registerEdgeGestureActivationListener(in IEdgeGestureActivationListener listener); - - /** Update the listener to react on gestures in the given positions. - */ - void updateEdgeGestureActivationListener(in IBinder listener, int positionFlags); - -} \ No newline at end of file diff --git a/core/java/android/service/gesture/package.html b/core/java/android/service/gesture/package.html deleted file mode 100644 index c9f96a66ab3bc..0000000000000 --- a/core/java/android/service/gesture/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -{@hide} - - diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java index 463eb5be46f61..8393f7ecd83a9 100644 --- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java +++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java @@ -58,6 +58,10 @@ public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp, int us } public VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si) { + if (si == null) { + mParseError = "Service not available"; + return; + } if (!Manifest.permission.BIND_VOICE_INTERACTION.equals(si.permission)) { mParseError = "Service does not require permission " + Manifest.permission.BIND_VOICE_INTERACTION; diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index fa347b9dece86..22ad63405770c 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1130,20 +1130,31 @@ public int getLineForOffset(int offset) { */ public int getOffsetForHorizontal(int line, float horiz) { // TODO: use Paint.getOffsetForAdvance to avoid binary search - int max = getLineEnd(line) - 1; - int min = getLineStart(line); + final int lineEndOffset = getLineEnd(line); + final int lineStartOffset = getLineStart(line); + Directions dirs = getLineDirections(line); - if (line == getLineCount() - 1) - max++; + TextLine tl = TextLine.obtain(); + // XXX: we don't care about tabs as we just use TextLine#getOffsetToLeftRightOf here. + tl.set(mPaint, mText, lineStartOffset, lineEndOffset, getParagraphDirection(line), dirs, + false, null); - int best = min; + final int max; + if (line == getLineCount() - 1) { + max = lineEndOffset; + } else { + max = tl.getOffsetToLeftRightOf(lineEndOffset - lineStartOffset, + !isRtlCharAt(lineEndOffset - 1)) + lineStartOffset; + } + int best = lineStartOffset; float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz); for (int i = 0; i < dirs.mDirections.length; i += 2) { - int here = min + dirs.mDirections[i]; + int here = lineStartOffset + dirs.mDirections[i]; int there = here + (dirs.mDirections[i+1] & RUN_LENGTH_MASK); - int swap = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0 ? -1 : 1; + boolean isRtl = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0; + int swap = isRtl ? -1 : 1; if (there > max) there = max; @@ -1163,23 +1174,23 @@ public int getOffsetForHorizontal(int line, float horiz) { low = here + 1; if (low < there) { - low = getOffsetAtStartOf(low); - - float dist = Math.abs(getPrimaryHorizontal(low) - horiz); - - int aft = TextUtils.getOffsetAfter(mText, low); - if (aft < there) { - float other = Math.abs(getPrimaryHorizontal(aft) - horiz); - - if (other < dist) { - dist = other; - low = aft; + int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset; + low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset; + if (low >= here && low < there) { + float dist = Math.abs(getPrimaryHorizontal(low) - horiz); + if (aft < there) { + float other = Math.abs(getPrimaryHorizontal(aft) - horiz); + + if (other < dist) { + dist = other; + low = aft; + } } - } - if (dist < bestdist) { - bestdist = dist; - best = low; + if (dist < bestdist) { + bestdist = dist; + best = low; + } } } @@ -1198,6 +1209,7 @@ public int getOffsetForHorizontal(int line, float horiz) { best = max; } + TextLine.recycle(tl); return best; } diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 39e86948d187f..3592187e9461e 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -718,13 +718,14 @@ static void updateMetrics(FontMetricsInt fmi, int previousTop, int previousAscen * @param bottom the bottom of the line * @param fmi receives metrics information, can be null * @param needWidth true if the width of the run is needed + * @param offset the offset for the purpose of measuring * @return the signed width of the run based on the run direction; only * valid if needWidth is true */ private float handleText(TextPaint wp, int start, int end, int contextStart, int contextEnd, boolean runIsRtl, Canvas c, float x, int top, int y, int bottom, - FontMetricsInt fmi, boolean needWidth) { + FontMetricsInt fmi, boolean needWidth, int offset) { // Get metrics first (even for empty strings or "0" width runs) if (fmi != null) { @@ -742,11 +743,11 @@ private float handleText(TextPaint wp, int start, int end, if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) { if (mCharsValid) { ret = wp.getRunAdvance(mChars, start, end, contextStart, contextEnd, - runIsRtl, end); + runIsRtl, offset); } else { int delta = mStart; ret = wp.getRunAdvance(mText, delta + start, delta + end, - delta + contextStart, delta + contextEnd, runIsRtl, delta + end); + delta + contextStart, delta + contextEnd, runIsRtl, delta + offset); } } @@ -895,8 +896,8 @@ private float handleRun(int start, int measureLimit, TextPaint wp = mWorkPaint; wp.set(mPaint); final int mlimit = measureLimit; - return handleText(wp, start, mlimit, start, limit, runIsRtl, c, x, top, - y, bottom, fmi, needWidth || mlimit < measureLimit); + return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top, + y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit); } mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit); @@ -940,13 +941,14 @@ private float handleRun(int start, int measureLimit, } for (int j = i, jnext; j < mlimit; j = jnext) { - jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) - + jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + inext) - mStart; + int offset = Math.min(jnext, mlimit); wp.set(mPaint); for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) { // Intentionally using >= and <= as explained above - if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) || + if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + offset) || (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue; CharacterStyle span = mCharacterStyleSpanSet.spans[k]; @@ -958,7 +960,7 @@ private float handleRun(int start, int measureLimit, wp.setHyphenEdit(0); } x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x, - top, y, bottom, fmi, needWidth || jnext < measureLimit); + top, y, bottom, fmi, needWidth || jnext < measureLimit, offset); } } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 2b654ad30e112..ee959e21256b0 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -251,6 +251,12 @@ public void setDensity(int inDensity) { xdpi = inDensity; ydpi = inDensity; + noncompatDensity = density; + noncompatDensityDpi = densityDpi; + noncompatScaledDensity = scaledDensity; + noncompatXdpi = xdpi; + noncompatYdpi = ydpi; + DENSITY_DEVICE = inDensity; Bitmap.setDefaultDensity(inDensity); } diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java index 2cc91b9dfe974..f1b3feb20b163 100644 --- a/core/java/android/util/Patterns.java +++ b/core/java/android/util/Patterns.java @@ -124,16 +124,36 @@ public class Patterns { + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" + "|[1-9][0-9]|[0-9]))"); + /** + * Match the characters without containing chinese characters + * @hide + */ + private static final String GOOD_IRI_HOST_CHAR = + "a-zA-Z0-9\u00A0-\u2FFF\u3040-\u4DFF\u9FA6-\uD7FF" + + "\uF900-\uFDCF\uFDF0-\uFEFF"; + /** * RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets. */ - private static final String IRI - = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}"; + private static final String IRI = + "[" + GOOD_IRI_HOST_CHAR + "]([" + GOOD_IRI_HOST_CHAR + "\\-_~]{0,61}[" + + GOOD_IRI_HOST_CHAR + "]){0,1}"; private static final String GOOD_GTLD_CHAR = - "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; + "a-zA-Z\u00A0-\u2FFF\u3040-\u4DFF\u9FA6-\uD7FF" + + "\uF900-\uFDCF\uFDF0-\uFEFF"; private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}"; private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD; + // Halfwidth and fullwidth forms + private static final String HALF_FULL_WIDTH_CHAR = "\uFF00-\uFFEF"; + // Symbols and punctuation + private static final String SYMBOLS_PUNCTUATION_CHAR = "\u3000-\u303F"; + // Chinese characters + private static final String CHINESE_CHAR = "\u4E00-\u9FA5"; + // Forbidden characters, should remove from URL, + private static final String FORBIDDEN_CHAR = + "[" + SYMBOLS_PUNCTUATION_CHAR + CHINESE_CHAR + + HALF_FULL_WIDTH_CHAR + "]"; public static final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")"); @@ -149,11 +169,15 @@ public class Patterns { + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?" + "(?:" + DOMAIN_NAME + ")" + "(?:\\:\\d{1,5})?)" // plus option port number - + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params - + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?" - + "(?:\\b|$)"); // and finally, a word boundary or end of - // input. This is to stop foo.sure from - // matching as foo.su + + "(\\/(?:(?:[" + GOOD_IRI_HOST_CHAR + + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params + + "\\-\\.\\+\\!\\*\\'\\(\\)\\_])|(?:\\,[" + GOOD_IRI_HOST_CHAR + + "])|(?:\\%[a-fA-F0-9]{2}))*)?" + + "(?:(?=" + FORBIDDEN_CHAR + + ")|\\b|$)"); + // and finally, a word boundary or end of input. This is to stop + // foo.sure from matching as foo.su + // also should remove forbidden characters from end of URL. public static final Pattern EMAIL_ADDRESS = Pattern.compile( diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index d43b962882810..85321f9ea6e53 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -567,6 +567,8 @@ private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo com } else if (type == Display.TYPE_BUILT_IN && (flags & Display.FLAG_PRESENTATION) == 0) { outMetrics.setDensity(DisplayMetrics.DENSITY_PREFERRED); + } else { + outMetrics.setDensity(logicalDensityDpi); } } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 55735c78f4f82..b3f40461fe86c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -287,4 +287,6 @@ interface IWindowManager * @return The frame statistics or null if the window does not exist. */ WindowContentFrameStats getWindowContentFrameStats(IBinder token); + + void setLiveLockscreenEdgeDetector(boolean enable); } diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 7642ed9ec3892..5f88c116e266e 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -256,16 +256,13 @@ public final class InputDevice implements Parcelable { public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE; /** - * The input source is a touch device whose motions should be interpreted as gestures. - * - * For example, an upward swipe should be treated the same as a swipe of the touchscreen. - * The same should apply for left, right, down swipes. Complex gestures may also be input. + * The input source is a rotating encoder device whose motions should be interpreted as akin to + * those of a scroll wheel. * * @see #SOURCE_CLASS_NONE - * - * @hide + * {@hide} */ - public static final int SOURCE_GESTURE_SENSOR = 0x00400000 | SOURCE_CLASS_NONE; + public static final int SOURCE_ROTARY_ENCODER = 0x00400000 | SOURCE_CLASS_NONE; /** * The input source is a joystick. @@ -283,6 +280,18 @@ public final class InputDevice implements Parcelable { */ public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON; + /** + * The input source is a touch device whose motions should be interpreted as gestures. + * + * For example, an upward swipe should be treated the same as a swipe of the touchscreen. + * The same should apply for left, right, down swipes. Complex gestures may also be input. + * + * @see #SOURCE_CLASS_NONE + * + * @hide + */ + public static final int SOURCE_GESTURE_SENSOR = 0x10000000 | SOURCE_CLASS_NONE; + /** * A special input source constant that is used when filtering input devices * to match devices that provide any type of input source. diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index d5847be3b4f76..d128288831cf2 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -761,6 +761,19 @@ public class KeyEvent extends InputEvent implements Parcelable { * Backs out one level of a navigation hierarchy or collapses the item that currently has * focus. */ public static final int KEYCODE_NAVIGATE_OUT = 263; + /** Key code constant: Primary stem key for Wear + * Main power/reset button on watch. + * @hide */ + public static final int KEYCODE_STEM_PRIMARY = 264; + /** Key code constant: Generic stem key 1 for Wear + * @hide */ + public static final int KEYCODE_STEM_1 = 265; + /** Key code constant: Generic stem key 2 for Wear + * @hide */ + public static final int KEYCODE_STEM_2 = 266; + /** Key code constant: Generic stem key 3 for Wear + * @hide */ + public static final int KEYCODE_STEM_3 = 267; /** Key code constant: Skip forward media key. */ public static final int KEYCODE_MEDIA_SKIP_FORWARD = 272; /** Key code constant: Skip backward media key. */ @@ -771,8 +784,11 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Step backward media key. * Steps media backward, one frame at a time. */ public static final int KEYCODE_MEDIA_STEP_BACKWARD = 275; + /** Key code constant: put device to sleep unless a wakelock is held. + * @hide */ + public static final int KEYCODE_SOFT_SLEEP = 276; - private static final int LAST_KEYCODE = KEYCODE_MEDIA_STEP_BACKWARD; + private static final int LAST_KEYCODE = KEYCODE_SOFT_SLEEP; // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -1836,6 +1852,9 @@ public static final boolean isWakeKey(int keyCode) { case KeyEvent.KEYCODE_VOLUME_MUTE: case KeyEvent.KEYCODE_CAMERA: case KeyEvent.KEYCODE_FOCUS: + case KeyEvent.KEYCODE_STEM_1: + case KeyEvent.KEYCODE_STEM_2: + case KeyEvent.KEYCODE_STEM_3: return true; } return false; diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 6026d04a1f21b..e0c9d596cc9ab 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -416,6 +416,21 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public static final int FLAG_WINDOW_IS_OBSCURED = 0x1; + /** + * This flag indicates that the window that received this motion event is partly + * or wholly obscured by another visible window above it. This flag is set to true + * even if the event did not directly pass through the obscured area. + * A security sensitive application can check this flag to identify situations in which + * a malicious application may have covered up part of its content for the purpose + * of misleading the user or hijacking touches. An appropriate response might be + * to drop the suspect touches or to take additional precautions to confirm the user's + * actual intent. + * + * Unlike FLAG_WINDOW_IS_OBSCURED, this is actually true. + * @hide + */ + public static final int FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2; + /** * Private flag that indicates when the system has detected that this motion event * may be inconsistent with respect to the sequence of previously delivered motion events, @@ -961,6 +976,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public static final int AXIS_TILT = 25; + /** + * Axis constant: Generic scroll axis of a motion event. + *

+ *

    + *
  • Reports the relative movement of the generic scrolling device. + *
+ *

+ * This axis should be used for scroll events that are neither strictly vertical nor horizontal. + * A good example would be the rotation of a rotary encoder input device. + *

+ * + * @see #getAxisValue(int, int) + * {@hide} + */ + public static final int AXIS_SCROLL = 26; + /** * Axis constant: Generic 1 axis of a motion event. * The interpretation of a generic axis is device-specific. @@ -1171,6 +1202,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { names.append(AXIS_BRAKE, "AXIS_BRAKE"); names.append(AXIS_DISTANCE, "AXIS_DISTANCE"); names.append(AXIS_TILT, "AXIS_TILT"); + names.append(AXIS_SCROLL, "AXIS_SCROLL"); names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1"); names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2"); names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3"); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 93345c2a7b59d..4b5635210f399 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16940,8 +16940,10 @@ void resetResolvedDrawablesInternal() { */ @CallSuper protected boolean verifyDrawable(Drawable who) { - return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who) - || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); + // Avoid verifying the scroll bar drawable so that we don't end up in + // an invalidation loop. This effectively prevents the scroll bar + // drawable from triggering invalidations and scheduling runnables. + return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 42402ebdc7462..9569422f880ce 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -174,6 +174,10 @@ public final class ViewRootImpl implements ViewParent, // so the window should no longer be active. boolean mStopped = false; + // Set to true if the owner of this window is in ambient mode, + // which means it won't receive input events. + boolean mIsAmbientMode = false; + // Set to true to stop input during an Activity Transition. boolean mPausedForTransition = false; @@ -990,6 +994,10 @@ private void invalidateRectOnScreen(Rect dirty) { } } + public void setIsAmbientMode(boolean ambient) { + mIsAmbientMode = ambient; + } + void setWindowStopped(boolean stopped) { if (mStopped != stopped) { mStopped = stopped; @@ -3704,7 +3712,7 @@ protected boolean shouldDropInputEvent(QueuedInputEvent q) { return true; } else if ((!mAttachInfo.mHasWindowFocus && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped - || (mPausedForTransition && !isBack(q.mEvent))) { + || mIsAmbientMode || (mPausedForTransition && !isBack(q.mEvent))) { // This is a focus event and the window doesn't currently have input focus or // has stopped. This could be an event that came back from the previous stage // but the window has lost focus or stopped in the meantime. @@ -5514,6 +5522,8 @@ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] writer.println(mProcessInputEventsScheduled); writer.print(innerPrefix); writer.print("mTraversalScheduled="); writer.print(mTraversalScheduled); + writer.print(innerPrefix); writer.print("mIsAmbientMode="); + writer.print(mIsAmbientMode); if (mTraversalScheduled) { writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")"); } else { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 3616622ed5bff..50a926f73c0ef 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -869,10 +869,6 @@ public void setFlags(int flags, int mask) { } private void setPrivateFlags(int flags, int mask) { - if ((flags & mask & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0){ - mContext.enforceCallingOrSelfPermission("android.permission.PREVENT_POWER_KEY", - "No permission to prevent power key"); - } final WindowManager.LayoutParams attrs = getAttributes(); attrs.privateFlags = (attrs.privateFlags & ~mask) | (flags & mask); dispatchWindowAttributesChanged(attrs); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 3ff88444cda99..36f593e44c48a 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -186,6 +186,7 @@ public static class LayoutParams extends ViewGroup.LayoutParams * @see #TYPE_SYSTEM_ERROR * @see #TYPE_INPUT_METHOD * @see #TYPE_INPUT_METHOD_DIALOG + * @see #TYPE_KEYGUARD_PANEL */ @ViewDebug.ExportedProperty(mapping = { @ViewDebug.IntToString(from = TYPE_BASE_APPLICATION, to = "TYPE_BASE_APPLICATION"), @@ -226,6 +227,7 @@ public static class LayoutParams extends ViewGroup.LayoutParams @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"), @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"), @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"), + @ViewDebug.IntToString(from = TYPE_KEYGUARD_PANEL, to = "TYPE_KEYGUARD_PANEL"), }) public int type; @@ -564,6 +566,13 @@ public static class LayoutParams extends ViewGroup.LayoutParams */ public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33; + /** + * Window type: Windows that are layered within the keyguard + * This type is LAST_SYSTEM_WINDOW-1 to avoid future conflicts with AOSP + * @hide + */ + public static final int TYPE_KEYGUARD_PANEL = FIRST_SYSTEM_WINDOW+998; + /** * End of types of system windows. */ @@ -1145,7 +1154,13 @@ public static class LayoutParams extends ViewGroup.LayoutParams public static final int PRIVATE_FLAG_WAS_NOT_FULLSCREEN = 0x02000000; /** - * Window flag: Overrides default power key behavior + * Window flag: Overrides default system key behavior. + * {@hide} + */ + public static final int PRIVATE_FLAG_PREVENT_SYSTEM_KEYS = 0x10000000; + + /** + * Window flag: Overrides default system key behavior. * {@hide} */ public static final int PRIVATE_FLAG_PREVENT_POWER_KEY = 0x20000000; diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index a962f2a2f3380..9d7c7419f3af7 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -20,6 +20,7 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Rect; @@ -664,6 +665,11 @@ public void adjustConfigurationLw(Configuration config, int keyboardPresence, */ public WindowState getWinShowWhenLockedLw(); + /** + * Returns the current keyguard panel, if such a thing exists. + */ + public WindowState getWinKeyguardPanelLw(); + /** * Called when the system would like to show a UI to indicate that an * application is starting. You can use this to add a @@ -1166,9 +1172,10 @@ public boolean rotationHasCompatibleMetricsLw(@ActivityInfo.ScreenOrientation in public void systemBooted(); /** - * Show boot time message to the user. + * Update UI for boot-up progress. */ - public void showBootMessage(final CharSequence msg, final boolean always); + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount); /** * Hide the UI for showing boot messages, never to be displayed again. @@ -1320,4 +1327,6 @@ public boolean rotationHasCompatibleMetricsLw(@ActivityInfo.ScreenOrientation in * @param fadeoutDuration the duration of the exit animation, in milliseconds */ public void startKeyguardExitAnimation(long startTime, long fadeoutDuration); + + public void setLiveLockscreenEdgeDetector(boolean enable); } diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index b5e08ca5caa0d..df3d8506e8a05 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -348,7 +348,6 @@ void drawDividersVertical(Canvas canvas) { final int count = getVirtualChildCount(); for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); @@ -377,7 +376,7 @@ void drawDividersVertical(Canvas canvas) { */ private View getLastNonGoneChild() { for (int i = getVirtualChildCount() - 1; i >= 0; i--) { - View child = getVirtualChildAt(i); + final View child = getVirtualChildAt(i); if (child != null && child.getVisibility() != GONE) { return child; } @@ -390,7 +389,6 @@ void drawDividersHorizontal(Canvas canvas) { final boolean isLayoutRtl = isLayoutRtl(); for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); @@ -577,8 +575,9 @@ public void setBaselineAlignedChildIndex(int i) { * for an example.

* * @param index the child's index - * @return the child at the specified index + * @return the child at the specified index, may be {@code null} */ + @Nullable View getVirtualChildAt(int index) { return getChildAt(index); } @@ -659,7 +658,7 @@ protected boolean hasDividerBeforeChildAt(int childIndex) { */ private boolean allViewsAreGoneBefore(int childIndex) { for (int i = childIndex - 1; i >= 0; i--) { - View child = getVirtualChildAt(i); + final View child = getVirtualChildAt(i); if (child != null && child.getVisibility() != GONE) { return false; } @@ -703,7 +702,6 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { // See how tall everyone is. Also remember max width. for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -822,7 +820,6 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -938,7 +935,6 @@ void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { if (useLargestChild && heightMode != MeasureSpec.EXACTLY) { for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child == null || child.getVisibility() == View.GONE) { continue; } @@ -981,7 +977,7 @@ private void forceUniformWidth(int count, int heightMeasureSpec) { MeasureSpec.EXACTLY); for (int i = 0; i< count; ++i) { final View child = getVirtualChildAt(i); - if (child.getVisibility() != GONE) { + if (child != null && child.getVisibility() != GONE) { LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams()); if (lp.width == LayoutParams.MATCH_PARENT) { @@ -1047,7 +1043,6 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { // See how wide everyone is. Also remember max height. for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -1203,7 +1198,6 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -1361,7 +1355,6 @@ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { if (useLargestChild && widthMode != MeasureSpec.EXACTLY) { for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child == null || child.getVisibility() == View.GONE) { continue; } @@ -1406,7 +1399,7 @@ private void forceUniformHeight(int count, int widthMeasureSpec) { MeasureSpec.EXACTLY); for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child.getVisibility() != GONE) { + if (child != null && child.getVisibility() != GONE) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); if (lp.height == LayoutParams.MATCH_PARENT) { @@ -1666,9 +1659,8 @@ void layoutHorizontal(int left, int top, int right, int bottom) { } for (int i = 0; i < count; i++) { - int childIndex = start + dir * i; + final int childIndex = start + dir * i; final View child = getVirtualChildAt(childIndex); - if (child == null) { childLeft += measureNullChild(childIndex); } else if (child.getVisibility() != GONE) { diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 9130d9ae3bc3b..50569d7e8f720 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -18,7 +18,6 @@ import android.content.Context; import android.hardware.SensorManager; -import android.os.PowerManager; import android.util.Log; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; @@ -600,8 +599,6 @@ static class SplineOverScroller { private static final int CUBIC = 1; private static final int BALLISTIC = 2; - private final PowerManager mPm; - static { float x_min = 0.0f; float y_min = 0.0f; @@ -646,7 +643,6 @@ void setFriction(float friction) { * 39.37f // inch/meter * ppi * 0.84f; // look and feel tuning - mPm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); } void updateScroll(float q) { @@ -764,7 +760,6 @@ void fling(int start, int velocity, int min, int max, int over) { if (velocity != 0) { mDuration = mSplineDuration = getSplineFlingDuration(velocity); totalDistance = getSplineFlingDistance(velocity); - mPm.cpuBoost(mDuration * 1000); } mSplineDistance = (int) (totalDistance * Math.signum(velocity)); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index e9ae071fba940..6a272e5229b62 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -31,6 +31,7 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.graphics.Rect; @@ -55,6 +56,8 @@ import android.widget.AdapterView.OnItemClickListener; import libcore.util.Objects; +import com.android.internal.R; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -206,14 +209,22 @@ public ActionException(String message) { /** @hide */ public static class OnClickHandler { + + private int mEnterAnimationId; + public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { try { // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? Context context = view.getContext(); - ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view, - 0, 0, - view.getMeasuredWidth(), view.getMeasuredHeight()); + ActivityOptions opts; + if (mEnterAnimationId != 0) { + opts = ActivityOptions.makeCustomAnimation(context, mEnterAnimationId, 0); + } else { + opts = ActivityOptions.makeScaleUpAnimation(view, + 0, 0, + view.getMeasuredWidth(), view.getMeasuredHeight()); + } context.startIntentSender( pendingIntent.getIntentSender(), fillInIntent, Intent.FLAG_ACTIVITY_NEW_TASK, @@ -228,6 +239,10 @@ public boolean onClickHandler(View view, PendingIntent pendingIntent, } return true; } + + public void setEnterAnimationId(int enterAnimationId) { + mEnterAnimationId = enterAnimationId; + } } /** @@ -2767,11 +2782,31 @@ public String getPackageName() { inflater.setFilter(this); result = inflater.inflate(rvToApply.getLayoutId(), parent, false); + loadTransitionOverride(context, handler); + rvToApply.performApply(result, parent, handler); return result; } + private static void loadTransitionOverride(Context context, + RemoteViews.OnClickHandler handler) { + if (handler != null && context.getResources().getBoolean( + com.android.internal.R.bool.config_overrideRemoteViewsActivityTransition)) { + TypedArray windowStyle = context.getTheme().obtainStyledAttributes( + com.android.internal.R.styleable.Window); + int windowAnimations = windowStyle.getResourceId( + com.android.internal.R.styleable.Window_windowAnimationStyle, 0); + TypedArray windowAnimationStyle = context.obtainStyledAttributes( + windowAnimations, com.android.internal.R.styleable.WindowAnimation); + handler.setEnterAnimationId(windowAnimationStyle.getResourceId( + com.android.internal.R.styleable. + WindowAnimation_activityOpenRemoteViewsEnterAnimation, 0)); + windowStyle.recycle(); + windowAnimationStyle.recycle(); + } + } + /** * Applies all of the actions to the provided view. * @@ -2815,7 +2850,8 @@ private void performApply(View v, ViewGroup parent, OnClickHandler handler) { private Context getContextForResources(Context context, String themePackageName) { if (mApplication != null) { if (context.getUserId() == UserHandle.getUserId(mApplication.uid) - && context.getPackageName().equals(mApplication.packageName)) { + && context.getPackageName().equals(mApplication.packageName) + && themePackageName == null) { return context; } try { diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java index a968eae4a5407..357c9c36936bd 100644 --- a/core/java/android/widget/Scroller.java +++ b/core/java/android/widget/Scroller.java @@ -19,7 +19,6 @@ import android.content.Context; import android.hardware.SensorManager; import android.os.Build; -import android.os.PowerManager; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -109,8 +108,6 @@ public class Scroller { private float mDeceleration; private final float mPpi; - private final PowerManager mPm; - // A context-specific coefficient adjusted to physical values. private float mPhysicalCoeff; @@ -181,8 +178,6 @@ public Scroller(Context context, Interpolator interpolator, boolean flywheel) { mFlywheel = flywheel; mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning - - mPm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); } /** @@ -400,8 +395,6 @@ public void startScroll(int startX, int startY, int dx, int dy, int duration) { mDeltaX = dx; mDeltaY = dy; mDurationReciprocal = 1.0f / (float) mDuration; - - mPm.cpuBoost(duration * 1000); } /** diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java index f7f9c91770340..22931fcb3e976 100644 --- a/core/java/android/widget/TableRow.java +++ b/core/java/android/widget/TableRow.java @@ -98,7 +98,7 @@ public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { * {@hide} */ void setColumnCollapsed(int columnIndex, boolean collapsed) { - View child = getVirtualChildAt(columnIndex); + final View child = getVirtualChildAt(columnIndex); if (child != null) { child.setVisibility(collapsed ? GONE : VISIBLE); } diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 4b31af05cbddf..e8dccab273bb9 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -18,6 +18,7 @@ import android.annotation.IntDef; import android.annotation.StringRes; +import android.app.ActivityManager; import android.app.INotificationManager; import android.app.ITransientNotification; import android.content.Context; @@ -405,14 +406,18 @@ public void handleShow() { ImageView appIcon = (ImageView) mView.findViewById(android.R.id.icon); if (appIcon != null) { - PackageManager pm = context.getPackageManager(); - Drawable icon = null; - try { - icon = pm.getApplicationIcon(packageName); - } catch (PackageManager.NameNotFoundException e) { - // nothing to do + ActivityManager am = + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + if (!am.isPackageInForeground(packageName)) { + PackageManager pm = context.getPackageManager(); + Drawable icon = null; + try { + icon = pm.getApplicationIcon(packageName); + } catch (PackageManager.NameNotFoundException e) { + // nothing to do + } + appIcon.setImageDrawable(icon); } - appIcon.setImageDrawable(icon); } mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); // We can resolve the Gravity here by using the Locale for getting diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 7699673701f0d..e137f9407a3d1 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -656,7 +656,19 @@ public boolean startAsCaller(Activity activity, Bundle options, int userId) { } intent.setComponent(mChooserTarget.getComponentName()); intent.putExtras(mChooserTarget.getIntentExtras()); - activity.startActivityAsCaller(intent, options, true, userId); + + // Important: we will ignore the target security checks in ActivityManager + // if and only if the ChooserTarget's target package is the same package + // where we got the ChooserTargetService that provided it. This lets a + // ChooserTargetService provide a non-exported or permission-guarded target + // to the chooser for the user to pick. + // + // If mSourceInfo is null, we got this ChooserTarget from the caller or elsewhere + // so we'll obey the caller's normal security checks. + final boolean ignoreTargetSecurity = mSourceInfo != null + && mSourceInfo.getResolvedComponentName().getPackageName() + .equals(mChooserTarget.getComponentName().getPackageName()); + activity.startActivityAsCaller(intent, options, ignoreTargetSecurity, userId); return true; } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 3cddbf6b6a560..ba92f4871d13a 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -121,4 +122,18 @@ interface IBatteryStats { void setBatteryState(int status, int health, int plugType, int level, int temp, int volt); long getAwakeTimeBattery(); long getAwakeTimePlugged(); + + + /** @hide */ + byte[] getDockStatistics(); + /** @hide */ + ParcelFileDescriptor getDockStatisticsStream(); + /** @hide **/ + void resetStatistics(); + /** @hide **/ + void setDockBatteryState(int status, int health, int plugType, int level, int temp, int volt); + /** @hide **/ + long getAwakeTimeDockBattery(); + /** @hide **/ + long getAwakeTimeDockPlugged(); } diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java index 4efefa943947d..83160cddf85e6 100644 --- a/core/java/com/android/internal/app/LocalePicker.java +++ b/core/java/com/android/internal/app/LocalePicker.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,6 +44,7 @@ import java.util.List; import java.util.Locale; import java.util.ArrayList; +import java.util.Arrays; public class LocalePicker extends ListFragment { private static final String TAG = "LocalePicker"; @@ -83,12 +87,23 @@ public int compareTo(LocaleInfo another) { } } + public static ArrayList getLocaleArray(String[] locales, Resources resources) { + String locale_codes = resources.getString(R.string.locale_codes); + String[] localeCodesArray = null; + if (locale_codes != null && !"".equals(locale_codes.trim())) { + localeCodesArray = locale_codes.split(","); + } + ArrayList localeList = new ArrayList( + Arrays.asList((localeCodesArray == null || localeCodesArray.length == 0) ? locales + : localeCodesArray)); + return localeList; + } + public static List getAllAssetLocales(Context context, boolean isInDeveloperMode) { final Resources resources = context.getResources(); - final String[] locales = Resources.getSystem().getAssets().getLocales(); - List localeList = new ArrayList(locales.length); - Collections.addAll(localeList, locales); + String[] locales = Resources.getSystem().getAssets().getLocales(); + ArrayList localeList = getLocaleArray(locales, resources); // Don't show the pseudolocales unless we're in developer mode. http://b/17190407. if (!isInDeveloperMode) { diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 00e250bce3de0..4c3cc4d99d330 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -91,7 +91,7 @@ public class ResolverActivity extends Activity { private ResolveListAdapter mAdapter; private PackageManager mPm; private boolean mSafeForwardingMode; - private boolean mAlwaysUseOption; + /*package*/ boolean mAlwaysUseOption; private AbsListView mAdapterView; private ViewGroup mFilteredItemContainer; private Button mAlwaysButton; @@ -1571,7 +1571,7 @@ protected DisplayResolveInfo getDisplayResolveInfo(int index) { return mDisplayList.get(index); } - public final View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = createView(parent); diff --git a/core/java/com/android/internal/app/ResolverProxy.java b/core/java/com/android/internal/app/ResolverProxy.java new file mode 100644 index 0000000000000..f59fd11f45718 --- /dev/null +++ b/core/java/com/android/internal/app/ResolverProxy.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import java.util.List; +import android.content.pm.ResolveInfo; +import android.content.Context; +import android.content.Intent; +import android.widget.AbsListView; +import android.app.VoiceInteractor.PickOptionRequest.Option; +import com.android.internal.app.ResolverActivity.TargetInfo; + +/** Relax access modifiers on key ResolverActivity extension methods to allow + them to be overridden from a different package/classloader. + Used by CMResolver */ +public class ResolverProxy extends ResolverActivity { + private static final String TAG = "ResolverProxy"; + + /** If the superclass may set up adapter entries after onCreate completes, + This method should be overridden to do nothing, and + sendVoiceChoicesIfNeeded should be called once the adapter setup is + complete. */ + @Override + protected void onSetupVoiceInteraction() { + super.onSetupVoiceInteraction(); + } + + /** see onSetupVoiceInteraction */ + @Override + protected void sendVoiceChoicesIfNeeded() { + super.sendVoiceChoicesIfNeeded(); + } + + @Override + protected int getLayoutResource() { + return super.getLayoutResource(); + } + + @Override + protected void bindProfileView() { + super.bindProfileView(); + } + + @Override + protected Option optionForChooserTarget(TargetInfo target, int index) { + return super.optionForChooserTarget(target, index); + } + + @Override + protected boolean shouldGetActivityMetadata() { + return super.shouldGetActivityMetadata(); + } + + @Override + protected boolean shouldAutoLaunchSingleChoice(TargetInfo target) { + return super.shouldAutoLaunchSingleChoice(target); + } + + @Override + protected void showAppDetails(ResolveInfo ri) { + super.showAppDetails(ri); + } + + @Override + void startSelected(int which, boolean always, boolean filtered) { + super.startSelected(which, always, filtered); + } + + @Override + protected void onActivityStarted(TargetInfo cti) { + super.onActivityStarted(cti); + } + + @Override + protected boolean configureContentView( + List payloadIntents, Intent[] initialIntents, + List rList, boolean alwaysUseOption) { + return super.configureContentView( + payloadIntents, initialIntents, rList, alwaysUseOption); + } + + @Override + protected void onPrepareAdapterView( + AbsListView adapterView, ResolveListAdapter adapter, boolean alwaysUseOption) { + super.onPrepareAdapterView(adapterView, adapter, alwaysUseOption); + } + + /** subclasses cannot override this because ResolveListAdapter is an inaccessible + type. Override createProxyAdapter(...) instead */ + @Override + ResolveListAdapter createAdapter(Context context, List payloadIntents, + Intent[] initialIntents, List rList, int launchedFromUid, + boolean filterLastUsed) { + ProxyListAdapter adapter = createProxyAdapter( + context, payloadIntents, initialIntents, rList, launchedFromUid, filterLastUsed); + return (adapter != null) + ? adapter + : super.createAdapter(context, payloadIntents, initialIntents, + rList, launchedFromUid, filterLastUsed); + } + + /** Subclasses should override this instead of createAdapter to avoid issues + with ResolveListAdapter being an inaccessible type */ + protected ProxyListAdapter createProxyAdapter(Context context, List payloadIntents, + Intent[] initialIntents, List rList, int launchedFromUid, + boolean filterLastUsed) { + return null; + } + + protected void setAlwaysUseOption(boolean alwaysUse) { + mAlwaysUseOption = alwaysUse; + } + + /** Provides a visible type for exending ResolveListAdapter - fortunately the key + methods one would need to override in ResolveListAdapter are all public or protected */ + public class ProxyListAdapter extends ResolveListAdapter { + public ProxyListAdapter( + Context context, List payloadIntents, Intent[] initialIntents, + List rList, int launchedFromUid, boolean filterLastUsed) { + super(context, payloadIntents, initialIntents, rList, launchedFromUid, filterLastUsed); + } + + /** complements getDisplayInfoCount and getDisplayInfoAt */ + public TargetInfo removeDisplayInfoAt(int index) { + if (index >= 0 && index < mDisplayList.size()) { + return mDisplayList.remove(index); + } else { + return null; + } + } + } +} diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index f479f4feca353..f5b948f42e00e 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -62,6 +62,8 @@ public class NativeLibraryHelper { // that the cpuAbiOverride must be clear. public static final String CLEAR_ABI_OVERRIDE = "-"; + private static final Object mRestoreconSync = new Object(); + /** * A handle to an opened package, consisting of one or more APKs. Used as * input to the various NativeLibraryHelper methods. Allows us to scan and @@ -275,8 +277,12 @@ private static void createNativeLibrarySubdir(File path) throws IOException { throw new IOException("Cannot chmod native library directory " + path.getPath(), e); } - } else if (!SELinux.restorecon(path)) { - throw new IOException("Cannot set SELinux context for " + path.getPath()); + } else { + synchronized (mRestoreconSync) { + if (!SELinux.restorecon(path)) { + throw new IOException("Cannot set SELinux context for " + path.getPath()); + } + } } } diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index b04ddf4eab8e4..0611401d38516 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -378,15 +378,6 @@ public static String resolveInstallVolume(Context context, String packageName, installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; } - // If app expresses strong desire for internal space, honor it - if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { - if (fitsOnInternal) { - return null; - } else { - throw new IOException("Requested internal only, but not enough space"); - } - } - // If app already exists somewhere, prefer to stay on that volume if (existingInfo != null) { if (existingInfo.volumeUuid == null && fitsOnInternal) { @@ -397,6 +388,15 @@ public static String resolveInstallVolume(Context context, String packageName, } } + // If app expresses strong desire for internal space, honor it + if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { + if (fitsOnInternal) { + return null; + } else { + throw new IOException("Requested internal only, but not enough space"); + } + } + // We're left with either preferring external or auto, so just pick // volume with most space if (bestCandidate != null) { diff --git a/core/java/com/android/internal/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java index 0e0d0bb883f4c..b90cb364defaf 100644 --- a/core/java/com/android/internal/logging/MetricsConstants.java +++ b/core/java/com/android/internal/logging/MetricsConstants.java @@ -21,7 +21,6 @@ * @hide */ public interface MetricsConstants { - public static final int DONT_TRACK_ME_BRO = -Integer.MAX_VALUE + 1; // These constants must match those in the analytic pipeline, do not edit. // Add temporary values to the top of MetricsLogger instead. public static final int VIEW_UNKNOWN = 0; diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index f178c8cf7ece7..54a4e86a4ef5f 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -21,6 +21,7 @@ import android.content.IntentFilter; import android.hardware.SensorManager; import android.net.ConnectivityManager; +import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStats.Uid; import android.os.Bundle; @@ -61,15 +62,18 @@ public final class BatteryStatsHelper { private static final String TAG = BatteryStatsHelper.class.getSimpleName(); private static BatteryStats sStatsXfer; + private static BatteryStats sDockStatsXfer; private static Intent sBatteryBroadcastXfer; private static ArrayMap sFileXfer = new ArrayMap<>(); final private Context mContext; + final private BatteryManager mBatteryService; final private boolean mCollectBatteryBroadcast; final private boolean mWifiOnly; private IBatteryStats mBatteryInfo; private BatteryStats mStats; + private BatteryStats mDockStats; private Intent mBatteryBroadcast; private PowerProfile mPowerProfile; @@ -160,19 +164,28 @@ public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast) { public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly) { mContext = context; + mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE)); mCollectBatteryBroadcast = collectBatteryBroadcast; mWifiOnly = wifiOnly; } public void storeStatsHistoryInFile(String fname) { + internalStoreStatsHistoryInFile(getStats(), fname); + } + + public void storeDockStatsHistoryInFile(String fname) { + internalStoreStatsHistoryInFile(getDockStats(), fname); + } + + public void internalStoreStatsHistoryInFile(BatteryStats stats, String fname) { synchronized (sFileXfer) { File path = makeFilePath(mContext, fname); - sFileXfer.put(path, this.getStats()); + sFileXfer.put(path, stats); FileOutputStream fout = null; try { fout = new FileOutputStream(path); Parcel hist = Parcel.obtain(); - getStats().writeToParcelWithoutUids(hist, 0); + stats.writeToParcelWithoutUids(hist, 0); byte[] histData = hist.marshall(); fout.write(histData); } catch (IOException e) { @@ -229,18 +242,38 @@ private static File makeFilePath(Context context, String fname) { /** Clears the current stats and forces recreating for future use. */ public void clearStats() { mStats = null; + mDockStats = null; + } + + private void clearAllStats() { + clearStats(); + sStatsXfer = null; + sDockStatsXfer = null; + sBatteryBroadcastXfer = null; + for (File f : sFileXfer.keySet()) { + f.delete(); + } + sFileXfer.clear(); } public BatteryStats getStats() { if (mStats == null) { - load(); + loadStats(); } return mStats; } + public BatteryStats getDockStats() { + if (mDockStats == null) { + loadDockStats(); + } + return mDockStats; + } + public Intent getBatteryBroadcast() { if (mBatteryBroadcast == null && mCollectBatteryBroadcast) { - load(); + loadStats(); + loadDockStats(); } return mBatteryBroadcast; } @@ -257,6 +290,7 @@ public void create(BatteryStats stats) { public void create(Bundle icicle) { if (icicle != null) { mStats = sStatsXfer; + mDockStats = sDockStatsXfer; mBatteryBroadcast = sBatteryBroadcastXfer; } mBatteryInfo = IBatteryStats.Stub.asInterface( @@ -266,6 +300,7 @@ public void create(Bundle icicle) { public void storeState() { sStatsXfer = mStats; + sDockStatsXfer = mDockStats; sBatteryBroadcastXfer = mBatteryBroadcast; } @@ -321,6 +356,7 @@ public void refreshStats(int statsType, SparseArray asUsers, long ra long rawUptimeUs) { // Initialize mStats if necessary. getStats(); + getDockStats(); mMaxPower = 0; mMaxRealPower = 0; @@ -739,7 +775,7 @@ public static byte[] readFully(FileInputStream stream, int avail) throws java.io } } - private void load() { + private void loadStats() { if (mBatteryInfo == null) { return; } @@ -750,6 +786,26 @@ private void load() { } } + private void loadDockStats() { + if (mBatteryInfo == null) { + return; + } + if (mBatteryService.isDockBatterySupported()) { + mDockStats = getDockStats(mBatteryInfo); + } else { + mDockStats = null; + } + } + + public void resetStatistics() { + try { + clearAllStats(); + mBatteryInfo.resetStatistics(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException:", e); + } + } + private static BatteryStatsImpl getStats(IBatteryStats service) { try { ParcelFileDescriptor pfd = service.getStatisticsStream(); @@ -772,4 +828,27 @@ private static BatteryStatsImpl getStats(IBatteryStats service) { } return new BatteryStatsImpl(); } + + private static BatteryStatsImpl getDockStats(IBatteryStats service) { + try { + ParcelFileDescriptor pfd = service.getDockStatisticsStream(); + if (pfd != null) { + FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + try { + byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor())); + Parcel parcel = Parcel.obtain(); + parcel.unmarshall(data, 0, data.length); + parcel.setDataPosition(0); + BatteryStatsImpl stats = com.android.internal.os.DockBatteryStatsImpl.CREATOR + .createFromParcel(parcel); + return stats; + } catch (IOException e) { + Log.w(TAG, "Unable to read statistics stream", e); + } + } + } catch (RemoteException e) { + Log.w(TAG, "RemoteException:", e); + } + return new BatteryStatsImpl(); + } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 64b7768c8337b..d0a169e60f37e 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006-2007 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,7 +92,7 @@ * battery life. All times are represented in microseconds except where indicated * otherwise. */ -public final class BatteryStatsImpl extends BatteryStats { +public class BatteryStatsImpl extends BatteryStats { private static final String TAG = "BatteryStatsImpl"; private static final boolean DEBUG = false; public static final boolean DEBUG_ENERGY = false; @@ -105,7 +106,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 132 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 133 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -1968,8 +1969,14 @@ public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) { private int buildBatteryLevelInt(HistoryItem h) { return ((((int)h.batteryLevel)<<25)&0xfe000000) - | ((((int)h.batteryTemperature)<<14)&0x01ff8000) - | ((((int)h.batteryVoltage)<<1)&0x00007fff); + | ((((int)h.batteryTemperature)<<15)&0x01ff8000) + | ((((int)h.batteryVoltage)<<1)&0x00007ffe); + } + + private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) { + out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25); + out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15); + out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1); } private int buildStateInt(HistoryItem h) { @@ -2110,9 +2117,7 @@ public void readHistoryDelta(Parcel src, HistoryItem cur) { final int batteryLevelInt; if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) { batteryLevelInt = src.readInt(); - cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f); - cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21); - cur.batteryVoltage = (char)(batteryLevelInt&0x3fff); + readBatteryLevelInt(batteryLevelInt, cur); cur.numReadInts += 1; if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x" + Integer.toHexString(batteryLevelInt) @@ -6839,13 +6844,13 @@ public BatteryStatsImpl getBatteryStats() { public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) { if (systemDir != null) { - mFile = new JournaledFile(new File(systemDir, "batterystats.bin"), - new File(systemDir, "batterystats.bin.tmp")); + mFile = new JournaledFile(new File(systemDir, getStatsName() + ".bin"), + new File(systemDir, getStatsName() + ".bin.tmp")); } else { mFile = null; } - mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin")); - mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml")); + mCheckinFile = new AtomicFile(new File(systemDir, getStatsName() + "-checkin.bin")); + mDailyFile = new AtomicFile(new File(systemDir, getStatsName () + "-daily.xml")); mExternalSync = externalSync; mHandler = new MyHandler(handler.getLooper()); mStartCount++; @@ -6921,6 +6926,16 @@ public BatteryStatsImpl(Parcel p) { readFromParcel(p); } + /** @hide */ + protected String getStatsName() { + return "batterystats"; + } + + /** @hide */ + protected String getLogName() { + return "BatteryStats"; + } + public void setPowerProfile(PowerProfile profile) { synchronized (this) { mPowerProfile = profile; @@ -7699,26 +7714,35 @@ public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) { } final Uid u = getUidStatsLocked(mapUid(entry.uid)); - u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, - entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, - entry.txPackets); - rxPackets.put(u.getUid(), entry.rxPackets); - txPackets.put(u.getUid(), entry.txPackets); + if (entry.rxBytes != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, + entry.rxPackets); + mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxPackets); - // Sum the total number of packets so that the Rx Power and Tx Power can - // be evenly distributed amongst the apps. - totalRxPackets += entry.rxPackets; - totalTxPackets += entry.txPackets; + rxPackets.put(u.getUid(), entry.rxPackets); - mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxPackets); - mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txPackets); + // Sum the total number of packets so that the Rx Power can + // be evenly distributed amongst the apps. + totalRxPackets += entry.rxPackets; + } + + if (entry.txBytes != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, + entry.txPackets); + mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txPackets); + + txPackets.put(u.getUid(), entry.txPackets); + + // Sum the total number of packets so that the Tx Power can + // be evenly distributed amongst the apps. + totalTxPackets += entry.txPackets; + } } } @@ -8434,7 +8458,13 @@ private void scheduleSyncExternalWifiStatsLocked(String reason) { public void setBatteryStateLocked(int status, int health, int plugType, int level, int temp, int volt) { - final boolean onBattery = plugType == BATTERY_PLUGGED_NONE; + // We need to add a extra check over the status because of dock batteries + // PlugType doesn't means that the dock battery is charging (some devices + // doesn't charge under dock usb) + boolean onBattery = plugType == BATTERY_PLUGGED_NONE && + (status != BatteryManager.BATTERY_STATUS_CHARGING || + status != BatteryManager.BATTERY_STATUS_FULL); + final long uptime = SystemClock.uptimeMillis(); final long elapsedRealtime = SystemClock.elapsedRealtime(); if (!mHaveBatteryLevel) { diff --git a/core/java/com/android/internal/os/DockBatteryStatsImpl.java b/core/java/com/android/internal/os/DockBatteryStatsImpl.java new file mode 100644 index 0000000000000..6099ad279fe6a --- /dev/null +++ b/core/java/com/android/internal/os/DockBatteryStatsImpl.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.os; + +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.File; + +public final class DockBatteryStatsImpl extends BatteryStatsImpl { + public DockBatteryStatsImpl() { + super(); + } + + public DockBatteryStatsImpl(Parcel p) { + super(p); + } + + public DockBatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) { + super(systemDir, handler, externalSync); + } + + protected String getStatsName() { + return "dockbatterystats"; + } + + protected String getLogName() { + return "DockBatteryStats"; + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public DockBatteryStatsImpl createFromParcel(Parcel in) { + return new DockBatteryStatsImpl(in); + } + + public DockBatteryStatsImpl[] newArray(int size) { + return new DockBatteryStatsImpl[size]; + } + }; +} diff --git a/core/java/com/android/internal/os/KernelCpuSpeedReader.java b/core/java/com/android/internal/os/KernelCpuSpeedReader.java index 5b776acf0cc84..3f6ebb9cccff1 100644 --- a/core/java/com/android/internal/os/KernelCpuSpeedReader.java +++ b/core/java/com/android/internal/os/KernelCpuSpeedReader.java @@ -16,8 +16,11 @@ package com.android.internal.os; import android.text.TextUtils; +import android.system.OsConstants; import android.util.Slog; +import libcore.io.Libcore; + import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -29,7 +32,7 @@ * * freq time * - * where time is measured in 1/100 seconds. + * where time is measured in jiffies. */ public class KernelCpuSpeedReader { private static final String TAG = "KernelCpuSpeedReader"; @@ -38,6 +41,9 @@ public class KernelCpuSpeedReader { private final long[] mLastSpeedTimes; private final long[] mDeltaSpeedTimes; + // How long a CPU jiffy is in milliseconds. + private final long mJiffyMillis; + /** * @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read. */ @@ -46,6 +52,8 @@ public KernelCpuSpeedReader(int cpuNumber, int numSpeedSteps) { cpuNumber); mLastSpeedTimes = new long[numSpeedSteps]; mDeltaSpeedTimes = new long[numSpeedSteps]; + long jiffyHz = Libcore.os.sysconf(OsConstants._SC_CLK_TCK); + mJiffyMillis = 1000/jiffyHz; } /** @@ -62,8 +70,7 @@ public long[] readDelta() { splitter.setString(line); Long.parseLong(splitter.next()); - // The proc file reports time in 1/100 sec, so convert to milliseconds. - long time = Long.parseLong(splitter.next()) * 10; + long time = Long.parseLong(splitter.next()) * mJiffyMillis; if (time < mLastSpeedTimes[speedIndex]) { // The stats reset when the cpu hotplugged. That means that the time // we read is offset from 0, so the time is the delta. diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java index bf97f1f3e2ed9..d8319022f4312 100644 --- a/core/java/com/android/internal/os/ProcessCpuTracker.java +++ b/core/java/com/android/internal/os/ProcessCpuTracker.java @@ -67,10 +67,10 @@ public class ProcessCpuTracker { static final int PROCESS_STAT_UTIME = 2; static final int PROCESS_STAT_STIME = 3; - /** Stores user time and system time in 100ths of a second. */ + /** Stores user time and system time in jiffies. */ private final long[] mProcessStatsData = new long[4]; - /** Stores user time and system time in 100ths of a second. Used for + /** Stores user time and system time in jiffies. Used for * public API to retrieve CPU use for a process. Must lock while in use. */ private final long[] mSinglePidStatsData = new long[4]; diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index f81658e013442..45dac2fc42a8d 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -19,6 +19,7 @@ import android.app.ActivityManagerNative; import android.app.ActivityThread; import android.app.ApplicationErrorReport; +import android.content.res.ThemeConfig; import android.os.Build; import android.os.Debug; import android.os.IBinder; @@ -83,6 +84,10 @@ public void uncaughtException(Thread t, Throwable e) { message.append("Process: ").append(processName).append(", "); } message.append("PID: ").append(Process.myPid()); + final ThemeConfig themeConfig = + ActivityManagerNative.getDefault().getConfiguration().themeConfig; + message.append("\nTheme: ").append(themeConfig == null ? + ThemeConfig.SYSTEM_DEFAULT : themeConfig); Clog_e(TAG, message.toString(), e); } @@ -109,6 +114,8 @@ private static final void commonInit() { /* set default handler; this applies to all threads in the VM */ Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); + Build.adjustBuildTypeIfNeeded(); + /* * Install a TimezoneGetter subclass for ZoneInfo.db */ diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl index e330de24f6d60..6f47f70f2230b 100644 --- a/core/java/com/android/internal/policy/IKeyguardService.aidl +++ b/core/java/com/android/internal/policy/IKeyguardService.aidl @@ -94,4 +94,5 @@ oneway interface IKeyguardService { * to start the keyguard dismiss sequence. */ void onActivityDrawn(); + void showKeyguard(); } diff --git a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl index db3b40b29903e..3468764ce1392 100644 --- a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl +++ b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl @@ -19,4 +19,5 @@ interface IKeyguardStateCallback { void onShowingStateChanged(boolean showing); void onSimSecureStateChanged(boolean simSecure); void onInputRestrictedStateChanged(boolean inputRestricted); + void onKeyguardPanelFocusChanged(boolean focused); } \ No newline at end of file diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java index 447292c9f3575..be78a129aada1 100644 --- a/core/java/com/android/internal/util/StateMachine.java +++ b/core/java/com/android/internal/util/StateMachine.java @@ -1878,6 +1878,33 @@ protected final void removeDeferredMessages(int what) { } } + /** + * Check if there are any pending messages with code 'what' in deferred messages queue. + */ + protected final boolean hasDeferredMessages(int what) { + SmHandler smh = mSmHandler; + if (smh == null) return false; + + Iterator iterator = smh.mDeferredMessages.iterator(); + while (iterator.hasNext()) { + Message msg = iterator.next(); + if (msg.what == what) return true; + } + + return false; + } + + /** + * Check if there are any pending posts of messages with code 'what' in + * the message queue. This does NOT check messages in deferred message queue. + */ + protected final boolean hasMessages(int what) { + SmHandler smh = mSmHandler; + if (smh == null) return false; + + return smh.hasMessages(what); + } + /** * Validate that the message was sent by * {@link StateMachine#quit} or {@link StateMachine#quitNow}. diff --git a/core/java/com/android/internal/util/cm/ImageUtils.java b/core/java/com/android/internal/util/cm/ImageUtils.java deleted file mode 100644 index 73189a3953f25..0000000000000 --- a/core/java/com/android/internal/util/cm/ImageUtils.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2013-2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util.cm; - -import android.app.WallpaperManager; -import android.content.Context; -import android.content.pm.ThemeUtils; -import android.content.res.AssetManager; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.net.Uri; -import android.provider.ThemesContract; -import android.provider.ThemesContract.ThemesColumns; -import android.text.TextUtils; -import android.util.Log; -import android.webkit.URLUtil; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; - -import libcore.io.IoUtils; - -public class ImageUtils { - private static final String TAG = ImageUtils.class.getSimpleName(); - - private static final String ASSET_URI_PREFIX = "file:///android_asset/"; - private static final int DEFAULT_IMG_QUALITY = 100; - - /** - * Gets the Width and Height of the image - * - * @param inputStream The input stream of the image - * - * @return A point structure that holds the Width and Height (x and y)/*" - */ - public static Point getImageDimension(InputStream inputStream) { - if (inputStream == null) { - throw new IllegalArgumentException("'inputStream' cannot be null!"); - } - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(inputStream, null, options); - Point point = new Point(options.outWidth,options.outHeight); - return point; - } - - /** - * Crops the input image and returns a new InputStream of the cropped area - * - * @param inputStream The input stream of the image - * @param imageWidth Width of the input image - * @param imageHeight Height of the input image - * @param inputStream Desired Width - * @param inputStream Desired Width - * - * @return a new InputStream of the cropped area/*" - */ - public static InputStream cropImage(InputStream inputStream, int imageWidth, int imageHeight, - int outWidth, int outHeight) throws IllegalArgumentException { - if (inputStream == null){ - throw new IllegalArgumentException("inputStream cannot be null"); - } - - if (imageWidth <= 0 || imageHeight <= 0) { - throw new IllegalArgumentException( - String.format("imageWidth and imageHeight must be > 0: imageWidth=%d" + - " imageHeight=%d", imageWidth, imageHeight)); - } - - if (outWidth <= 0 || outHeight <= 0) { - throw new IllegalArgumentException( - String.format("outWidth and outHeight must be > 0: outWidth=%d" + - " outHeight=%d", imageWidth, outHeight)); - } - - int scaleDownSampleSize = Math.min(imageWidth / outWidth, imageHeight / outHeight); - if (scaleDownSampleSize > 0) { - imageWidth /= scaleDownSampleSize; - imageHeight /= scaleDownSampleSize; - } else { - float ratio = (float) outWidth / outHeight; - if (imageWidth < imageHeight * ratio) { - outWidth = imageWidth; - outHeight = (int) (outWidth / ratio); - } else { - outHeight = imageHeight; - outWidth = (int) (outHeight * ratio); - } - } - int left = (imageWidth - outWidth) / 2; - int top = (imageHeight - outHeight) / 2; - InputStream compressed = null; - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - if (scaleDownSampleSize > 1) { - options.inSampleSize = scaleDownSampleSize; - } - Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); - if (bitmap == null) { - return null; - } - Bitmap cropped = Bitmap.createBitmap(bitmap, left, top, outWidth, outHeight); - ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); - if (cropped.compress(Bitmap.CompressFormat.PNG, DEFAULT_IMG_QUALITY, tmpOut)) { - byte[] outByteArray = tmpOut.toByteArray(); - compressed = new ByteArrayInputStream(outByteArray); - } - } catch (Exception e) { - Log.e(TAG, "Exception " + e); - } - return compressed; - } - - /** - * Crops the lock screen image and returns a new InputStream of the cropped area - * - * @param pkgName Name of the theme package - * @param context The context - * - * @return a new InputStream of the cropped image/*" - */ - public static InputStream getCroppedKeyguardStream(String pkgName, Context context) - throws IllegalArgumentException { - if (TextUtils.isEmpty(pkgName)) { - throw new IllegalArgumentException("'pkgName' cannot be null or empty!"); - } - if (context == null) { - throw new IllegalArgumentException("'context' cannot be null!"); - } - - InputStream cropped = null; - InputStream stream = null; - try { - stream = getOriginalKeyguardStream(pkgName, context); - if (stream == null) { - return null; - } - Point point = getImageDimension(stream); - IoUtils.closeQuietly(stream); - if (point == null || point.x == 0 || point.y == 0) { - return null; - } - WallpaperManager wm = WallpaperManager.getInstance(context); - int outWidth = wm.getDesiredMinimumWidth(); - int outHeight = wm.getDesiredMinimumHeight(); - stream = getOriginalKeyguardStream(pkgName, context); - if (stream == null) { - return null; - } - cropped = cropImage(stream, point.x, point.y, outWidth, outHeight); - } catch (Exception e) { - Log.e(TAG, "Exception " + e); - } finally { - IoUtils.closeQuietly(stream); - } - return cropped; - } - - /** - * Crops the wallpaper image and returns a new InputStream of the cropped area - * - * @param pkgName Name of the theme package - * @param context The context - * - * @return a new InputStream of the cropped image/*" - */ - public static InputStream getCroppedWallpaperStream(String pkgName, long wallpaperId, - Context context) { - if (TextUtils.isEmpty(pkgName)) { - throw new IllegalArgumentException("'pkgName' cannot be null or empty!"); - } - if (context == null) { - throw new IllegalArgumentException("'context' cannot be null!"); - } - - InputStream cropped = null; - InputStream stream = null; - try { - stream = getOriginalWallpaperStream(pkgName, wallpaperId, context); - if (stream == null) { - return null; - } - Point point = getImageDimension(stream); - IoUtils.closeQuietly(stream); - if (point == null || point.x == 0 || point.y == 0) { - return null; - } - WallpaperManager wm = WallpaperManager.getInstance(context); - int outWidth = wm.getDesiredMinimumWidth(); - int outHeight = wm.getDesiredMinimumHeight(); - stream = getOriginalWallpaperStream(pkgName, wallpaperId, context); - if (stream == null) { - return null; - } - cropped = cropImage(stream, point.x, point.y, outWidth, outHeight); - } catch (Exception e) { - Log.e(TAG, "Exception " + e); - } finally { - IoUtils.closeQuietly(stream); - } - return cropped; - } - - private static InputStream getOriginalKeyguardStream(String pkgName, Context context) { - if (TextUtils.isEmpty(pkgName) || context == null) { - return null; - } - - InputStream inputStream = null; - try { - //Get input WP stream from the theme - Context themeCtx = context.createPackageContext(pkgName, - Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - String wpPath = ThemeUtils.getLockscreenWallpaperPath(assetManager); - if (wpPath == null) { - Log.w(TAG, "Not setting lockscreen wp because wallpaper file was not found."); - } else { - inputStream = ThemeUtils.getInputStreamFromAsset(themeCtx, - ASSET_URI_PREFIX + wpPath); - } - } catch (Exception e) { - Log.e(TAG, "There was an error setting lockscreen wp for pkg " + pkgName, e); - } - return inputStream; - } - - private static InputStream getOriginalWallpaperStream(String pkgName, long componentId, - Context context) { - String wpPath; - if (TextUtils.isEmpty(pkgName) || context == null) { - return null; - } - - InputStream inputStream = null; - String selection = ThemesContract.ThemesColumns.PKG_NAME + "= ?"; - String[] selectionArgs = {pkgName}; - Cursor c = context.getContentResolver().query(ThemesColumns.CONTENT_URI, - null, selection, - selectionArgs, null); - if (c == null || c.getCount() < 1) { - if (c != null) c.close(); - return null; - } else { - c.moveToFirst(); - } - - try { - Context themeContext = context.createPackageContext(pkgName, - Context.CONTEXT_IGNORE_SECURITY); - boolean isLegacyTheme = c.getInt( - c.getColumnIndex(ThemesColumns.IS_LEGACY_THEME)) == 1; - String wallpaper = c.getString( - c.getColumnIndex(ThemesColumns.WALLPAPER_URI)); - if (wallpaper != null) { - if (URLUtil.isAssetUrl(wallpaper)) { - inputStream = ThemeUtils.getInputStreamFromAsset(themeContext, wallpaper); - } else { - inputStream = context.getContentResolver().openInputStream( - Uri.parse(wallpaper)); - } - } else { - // try and get the wallpaper directly from the apk if the URI was null - Context themeCtx = context.createPackageContext(pkgName, - Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - wpPath = queryWpPathFromComponentId(context, pkgName, componentId); - if (wpPath == null) wpPath = ThemeUtils.getWallpaperPath(assetManager); - if (wpPath == null) { - Log.e(TAG, "Not setting wp because wallpaper file was not found."); - } else { - inputStream = ThemeUtils.getInputStreamFromAsset(themeCtx, - ASSET_URI_PREFIX + wpPath); - } - } - } catch (Exception e) { - Log.e(TAG, "getWallpaperStream: " + e); - } finally { - c.close(); - } - - return inputStream; - } - - private static String queryWpPathFromComponentId(Context context, String pkgName, - long componentId) { - String wpPath = null; - String[] projection = new String[] { ThemesContract.PreviewColumns.COL_VALUE }; - String selection = ThemesColumns.PKG_NAME + "=? AND " + - ThemesContract.PreviewColumns.COMPONENT_ID + "=? AND " + - ThemesContract.PreviewColumns.COL_KEY + "=?"; - String[] selectionArgs = new String[] { - pkgName, - Long.toString(componentId), - ThemesContract.PreviewColumns.WALLPAPER_FULL - }; - - Cursor c = context.getContentResolver() - .query(ThemesContract.PreviewColumns.COMPONENTS_URI, - projection, selection, selectionArgs, null); - if (c != null) { - try { - if (c.moveToFirst()) { - int valIdx = c.getColumnIndex(ThemesContract.PreviewColumns.COL_VALUE); - wpPath = c.getString(valIdx); - } - } catch(Exception e) { - Log.e(TAG, "Could not get wallpaper path", e); - } finally { - c.close(); - } - } - return wpPath; - } -} - diff --git a/core/java/com/android/internal/util/cm/SpamFilter.java b/core/java/com/android/internal/util/cm/SpamFilter.java index 9de44896fa956..c261009de0d34 100644 --- a/core/java/com/android/internal/util/cm/SpamFilter.java +++ b/core/java/com/android/internal/util/cm/SpamFilter.java @@ -46,10 +46,21 @@ public static String getNormalizedNotificationContent(Notification notification) } public static String getNotificationContent(Notification notification) { + CharSequence notificationTitle = getNotificationTitle(notification); + CharSequence notificationMessage = getNotificationMessage(notification); + return notificationTitle + "\n" + notificationMessage; + } + + private static CharSequence getNotificationTitle(Notification notification) { Bundle extras = notification.extras; String titleExtra = extras.containsKey(Notification.EXTRA_TITLE_BIG) ? Notification.EXTRA_TITLE_BIG : Notification.EXTRA_TITLE; CharSequence notificationTitle = extras.getCharSequence(titleExtra); + return notificationTitle; + } + + private static CharSequence getNotificationMessage(Notification notification) { + Bundle extras = notification.extras; CharSequence notificationMessage = extras.getCharSequence(Notification.EXTRA_TEXT); if (TextUtils.isEmpty(notificationMessage)) { @@ -60,6 +71,12 @@ public static String getNotificationContent(Notification notification) { notificationMessage = TextUtils.join("\n", inboxLines); } } - return notificationTitle + "\n" + notificationMessage; + return notificationMessage; + } + + public static boolean hasFilterableContent(Notification notification) { + CharSequence notificationTitle = getNotificationTitle(notification); + CharSequence notificationMessage = getNotificationMessage(notification); + return !(TextUtils.isEmpty(notificationTitle) && TextUtils.isEmpty(notificationMessage)); } } diff --git a/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java b/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java index ab5aef780dac1..a24dff81831dc 100644 --- a/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java +++ b/core/java/com/android/internal/util/cm/palette/ColorCutQuantizer.java @@ -16,11 +16,9 @@ package com.android.internal.util.cm.palette; -import android.graphics.Bitmap; import android.graphics.Color; -import android.util.SparseIntArray; - import com.android.internal.util.cm.palette.Palette.Swatch; +import android.util.TimingLogger; import java.util.ArrayList; import java.util.Arrays; @@ -46,74 +44,97 @@ */ final class ColorCutQuantizer { - private static final String LOG_TAG = ColorCutQuantizer.class.getSimpleName(); - - private final float[] mTempHsl = new float[3]; - - private static final float BLACK_MAX_LIGHTNESS = 0.05f; - private static final float WHITE_MIN_LIGHTNESS = 0.95f; + private static final String LOG_TAG = "ColorCutQuantizer"; + private static final boolean LOG_TIMINGS = false; private static final int COMPONENT_RED = -3; private static final int COMPONENT_GREEN = -2; private static final int COMPONENT_BLUE = -1; - private final int[] mColors; - private final SparseIntArray mColorPopulations; + private static final int QUANTIZE_WORD_WIDTH = 5; + private static final int QUANTIZE_WORD_MASK = (1 << QUANTIZE_WORD_WIDTH) - 1; - private final List mQuantizedColors; + final int[] mColors; + final int[] mHistogram; + final List mQuantizedColors; + final TimingLogger mTimingLogger; + final Palette.Filter[] mFilters; + + private final float[] mTempHsl = new float[3]; /** - * Factory-method to generate a {@link ColorCutQuantizer} from a {@link Bitmap} object. + * Constructor. * - * @param bitmap Bitmap to extract the pixel data from + * @param pixels histogram representing an image's pixel data * @param maxColors The maximum number of colors that should be in the result palette. + * @param filters Set of filters to use in the quantization stage */ - static ColorCutQuantizer fromBitmap(Bitmap bitmap, int maxColors) { - final int width = bitmap.getWidth(); - final int height = bitmap.getHeight(); + ColorCutQuantizer(final int[] pixels, final int maxColors, final Palette.Filter[] filters) { + mTimingLogger = LOG_TIMINGS ? new TimingLogger(LOG_TAG, "Creation") : null; + mFilters = filters; + + final int[] hist = mHistogram = new int[1 << (QUANTIZE_WORD_WIDTH * 3)]; + for (int i = 0; i < pixels.length; i++) { + final int quantizedColor = quantizeFromRgb888(pixels[i]); + // Now update the pixel value to the quantized value + pixels[i] = quantizedColor; + // And update the histogram + hist[quantizedColor]++; + } - final int[] pixels = new int[width * height]; - bitmap.getPixels(pixels, 0, width, 0, 0, width, height); + if (LOG_TIMINGS) { + mTimingLogger.addSplit("Histogram created"); + } - return new ColorCutQuantizer(new com.android.internal.util.cm.palette.ColorHistogram(pixels), maxColors); - } + // Now let's count the number of distinct colors + int distinctColorCount = 0; + for (int color = 0; color < hist.length; color++) { + if (hist[color] > 0 && shouldIgnoreColor(color)) { + // If we should ignore the color, set the population to 0 + hist[color] = 0; + } + if (hist[color] > 0) { + // If the color has population, increase the distinct color count + distinctColorCount++; + } + } - /** - * Private constructor. - * - * @param colorHistogram histogram representing an image's pixel data - * @param maxColors The maximum number of colors that should be in the result palette. - */ - private ColorCutQuantizer(com.android.internal.util.cm.palette.ColorHistogram colorHistogram, int maxColors) { - final int rawColorCount = colorHistogram.getNumberOfColors(); - final int[] rawColors = colorHistogram.getColors(); - final int[] rawColorCounts = colorHistogram.getColorCounts(); - - // First, lets pack the populations into a SparseIntArray so that they can be easily - // retrieved without knowing a color's index - mColorPopulations = new SparseIntArray(rawColorCount); - for (int i = 0; i < rawColors.length; i++) { - mColorPopulations.append(rawColors[i], rawColorCounts[i]); + if (LOG_TIMINGS) { + mTimingLogger.addSplit("Filtered colors and distinct colors counted"); } - // Now go through all of the colors and keep those which we do not want to ignore - mColors = new int[rawColorCount]; - int validColorCount = 0; - for (int color : rawColors) { - if (!shouldIgnoreColor(color)) { - mColors[validColorCount++] = color; + // Now lets go through create an array consisting of only distinct colors + final int[] colors = mColors = new int[distinctColorCount]; + int distinctColorIndex = 0; + for (int color = 0; color < hist.length; color++) { + if (hist[color] > 0) { + colors[distinctColorIndex++] = color; } } - if (validColorCount <= maxColors) { + if (LOG_TIMINGS) { + mTimingLogger.addSplit("Distinct colors copied into array"); + } + + if (distinctColorCount <= maxColors) { // The image has fewer colors than the maximum requested, so just return the colors - mQuantizedColors = new ArrayList(); - for (final int color : mColors) { - mQuantizedColors.add(new Swatch(color, mColorPopulations.get(color))); + mQuantizedColors = new ArrayList<>(); + for (int color : colors) { + mQuantizedColors.add(new Swatch(approximateToRgb888(color), hist[color])); + } + + if (LOG_TIMINGS) { + mTimingLogger.addSplit("Too few colors present. Copied to Swatches"); + mTimingLogger.dumpToLog(); } } else { // We need use quantization to reduce the number of colors - mQuantizedColors = quantizePixels(validColorCount - 1, maxColors); + mQuantizedColors = quantizePixels(maxColors); + + if (LOG_TIMINGS) { + mTimingLogger.addSplit("Quantized colors computed"); + mTimingLogger.dumpToLog(); + } } } @@ -124,13 +145,13 @@ List getQuantizedColors() { return mQuantizedColors; } - private List quantizePixels(int maxColorIndex, int maxColors) { + private List quantizePixels(int maxColors) { // Create the priority queue which is sorted by volume descending. This means we always // split the largest box in the queue - final PriorityQueue pq = new PriorityQueue(maxColors, VBOX_COMPARATOR_VOLUME); + final PriorityQueue pq = new PriorityQueue<>(maxColors, VBOX_COMPARATOR_VOLUME); // To start, offer a box which contains all of the colors - pq.offer(new Vbox(0, maxColorIndex)); + pq.offer(new Vbox(0, mColors.length - 1)); // Now go through the boxes, splitting them until we have reached maxColors or there are no // more boxes to split @@ -146,7 +167,7 @@ private List quantizePixels(int maxColorIndex, int maxColors) { * and splitting them. Once split, the new box and the remaining box are offered back to the * queue. * - * @param queue {@link PriorityQueue} to poll for boxes + * @param queue {@link java.util.PriorityQueue} to poll for boxes * @param maxSize Maximum amount of boxes to split */ private void splitBoxes(final PriorityQueue queue, final int maxSize) { @@ -156,9 +177,16 @@ private void splitBoxes(final PriorityQueue queue, final int maxSize) { if (vbox != null && vbox.canSplit()) { // First split the box, and offer the result queue.offer(vbox.splitBox()); + + if (LOG_TIMINGS) { + mTimingLogger.addSplit("Box split"); + } // Then offer the box back queue.offer(vbox); } else { + if (LOG_TIMINGS) { + mTimingLogger.addSplit("All boxes split"); + } // If we get here then there are no more boxes to split, so return return; } @@ -166,13 +194,13 @@ private void splitBoxes(final PriorityQueue queue, final int maxSize) { } private List generateAverageColors(Collection vboxes) { - ArrayList colors = new ArrayList(vboxes.size()); + ArrayList colors = new ArrayList<>(vboxes.size()); for (Vbox vbox : vboxes) { - Swatch color = vbox.getAverageColor(); - if (!shouldIgnoreColor(color)) { + Swatch swatch = vbox.getAverageColor(); + if (!shouldIgnoreColor(swatch)) { // As we're averaging a color box, we can still get colors which we do not want, so // we check again here - colors.add(color); + colors.add(swatch); } } return colors; @@ -185,6 +213,8 @@ private class Vbox { // lower and upper index are inclusive private int mLowerIndex; private int mUpperIndex; + // Population of colors within this box + private int mPopulation; private int mMinRed, mMaxRed; private int mMinGreen, mMaxGreen; @@ -196,51 +226,67 @@ private class Vbox { fitBox(); } - int getVolume() { + final int getVolume() { return (mMaxRed - mMinRed + 1) * (mMaxGreen - mMinGreen + 1) * (mMaxBlue - mMinBlue + 1); } - boolean canSplit() { + final boolean canSplit() { return getColorCount() > 1; } - int getColorCount() { - return mUpperIndex - mLowerIndex + 1; + final int getColorCount() { + return 1 + mUpperIndex - mLowerIndex; } /** * Recomputes the boundaries of this box to tightly fit the colors within the box. */ - void fitBox() { + final void fitBox() { + final int[] colors = mColors; + final int[] hist = mHistogram; + // Reset the min and max to opposite values - mMinRed = mMinGreen = mMinBlue = 0xFF; - mMaxRed = mMaxGreen = mMaxBlue = 0x0; + int minRed, minGreen, minBlue; + minRed = minGreen = minBlue = Integer.MAX_VALUE; + int maxRed, maxGreen, maxBlue; + maxRed = maxGreen = maxBlue = Integer.MIN_VALUE; + int count = 0; for (int i = mLowerIndex; i <= mUpperIndex; i++) { - final int color = mColors[i]; - final int r = Color.red(color); - final int g = Color.green(color); - final int b = Color.blue(color); - if (r > mMaxRed) { - mMaxRed = r; + final int color = colors[i]; + count += hist[color]; + + final int r = quantizedRed(color); + final int g = quantizedGreen(color); + final int b = quantizedBlue(color); + if (r > maxRed) { + maxRed = r; } - if (r < mMinRed) { - mMinRed = r; + if (r < minRed) { + minRed = r; } - if (g > mMaxGreen) { - mMaxGreen = g; + if (g > maxGreen) { + maxGreen = g; } - if (g < mMinGreen) { - mMinGreen = g; + if (g < minGreen) { + minGreen = g; } - if (b > mMaxBlue) { - mMaxBlue = b; + if (b > maxBlue) { + maxBlue = b; } - if (b < mMinBlue) { - mMinBlue = b; + if (b < minBlue) { + minBlue = b; } } + + mMinRed = minRed; + mMaxRed = maxRed; + mMinGreen = minGreen; + mMaxGreen = maxGreen; + mMinBlue = minBlue; + mMaxBlue = maxBlue; + mPopulation = count; } /** @@ -248,7 +294,7 @@ void fitBox() { * * @return the new ColorBox */ - Vbox splitBox() { + final Vbox splitBox() { if (!canSplit()) { throw new IllegalStateException("Can not split a box with only 1 color"); } @@ -268,7 +314,7 @@ Vbox splitBox() { /** * @return the dimension which this box is largest in */ - int getLongestColorDimension() { + final int getLongestColorDimension() { final int redLength = mMaxRed - mMinRed; final int greenLength = mMaxGreen - mMinGreen; final int blueLength = mMaxBlue - mMinBlue; @@ -291,41 +337,27 @@ int getLongestColorDimension() { * * @return the index of the colors array to split from */ - int findSplitPoint() { + final int findSplitPoint() { final int longestDimension = getLongestColorDimension(); + final int[] colors = mColors; + final int[] hist = mHistogram; // We need to sort the colors in this box based on the longest color dimension. // As we can't use a Comparator to define the sort logic, we modify each color so that // it's most significant is the desired dimension - modifySignificantOctet(longestDimension, mLowerIndex, mUpperIndex); + modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex); // Now sort... Arrays.sort uses a exclusive toIndex so we need to add 1 - Arrays.sort(mColors, mLowerIndex, mUpperIndex + 1); + Arrays.sort(colors, mLowerIndex, mUpperIndex + 1); // Now revert all of the colors so that they are packed as RGB again - modifySignificantOctet(longestDimension, mLowerIndex, mUpperIndex); - - final int dimensionMidPoint = midPoint(longestDimension); - - for (int i = mLowerIndex; i <= mUpperIndex; i++) { - final int color = mColors[i]; - - switch (longestDimension) { - case COMPONENT_RED: - if (Color.red(color) >= dimensionMidPoint) { - return i; - } - break; - case COMPONENT_GREEN: - if (Color.green(color) >= dimensionMidPoint) { - return i; - } - break; - case COMPONENT_BLUE: - if (Color.blue(color) > dimensionMidPoint) { - return i; - } - break; + modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex); + + final int midPoint = mPopulation / 2; + for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++) { + count += hist[colors[i]]; + if (count >= midPoint) { + return i; } } @@ -335,115 +367,150 @@ int findSplitPoint() { /** * @return the average color of this box. */ - Swatch getAverageColor() { + final Swatch getAverageColor() { + final int[] colors = mColors; + final int[] hist = mHistogram; int redSum = 0; int greenSum = 0; int blueSum = 0; int totalPopulation = 0; for (int i = mLowerIndex; i <= mUpperIndex; i++) { - final int color = mColors[i]; - final int colorPopulation = mColorPopulations.get(color); + final int color = colors[i]; + final int colorPopulation = hist[color]; totalPopulation += colorPopulation; - redSum += colorPopulation * Color.red(color); - greenSum += colorPopulation * Color.green(color); - blueSum += colorPopulation * Color.blue(color); + redSum += colorPopulation * quantizedRed(color); + greenSum += colorPopulation * quantizedGreen(color); + blueSum += colorPopulation * quantizedBlue(color); } - final int redAverage = Math.round(redSum / (float) totalPopulation); - final int greenAverage = Math.round(greenSum / (float) totalPopulation); - final int blueAverage = Math.round(blueSum / (float) totalPopulation); + final int redMean = Math.round(redSum / (float) totalPopulation); + final int greenMean = Math.round(greenSum / (float) totalPopulation); + final int blueMean = Math.round(blueSum / (float) totalPopulation); - return new Swatch(redAverage, greenAverage, blueAverage, totalPopulation); - } - - /** - * @return the midpoint of this box in the given {@code dimension} - */ - int midPoint(int dimension) { - switch (dimension) { - case COMPONENT_RED: - default: - return (mMinRed + mMaxRed) / 2; - case COMPONENT_GREEN: - return (mMinGreen + mMaxGreen) / 2; - case COMPONENT_BLUE: - return (mMinBlue + mMaxBlue) / 2; - } + return new Swatch(approximateToRgb888(redMean, greenMean, blueMean), totalPopulation); } } /** * Modify the significant octet in a packed color int. Allows sorting based on the value of a - * single color component. + * single color component. This relies on all components being the same word size. * * @see Vbox#findSplitPoint() */ - private void modifySignificantOctet(final int dimension, int lowerIndex, int upperIndex) { + private static void modifySignificantOctet(final int[] a, final int dimension, + final int lower, final int upper) { switch (dimension) { case COMPONENT_RED: // Already in RGB, no need to do anything break; case COMPONENT_GREEN: // We need to do a RGB to GRB swap, or vice-versa - for (int i = lowerIndex; i <= upperIndex; i++) { - final int color = mColors[i]; - mColors[i] = Color.rgb((color >> 8) & 0xFF, (color >> 16) & 0xFF, color & 0xFF); + for (int i = lower; i <= upper; i++) { + final int color = a[i]; + a[i] = quantizedGreen(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH) + | quantizedRed(color) << QUANTIZE_WORD_WIDTH + | quantizedBlue(color); } break; case COMPONENT_BLUE: // We need to do a RGB to BGR swap, or vice-versa - for (int i = lowerIndex; i <= upperIndex; i++) { - final int color = mColors[i]; - mColors[i] = Color.rgb(color & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF); + for (int i = lower; i <= upper; i++) { + final int color = a[i]; + a[i] = quantizedBlue(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH) + | quantizedGreen(color) << QUANTIZE_WORD_WIDTH + | quantizedRed(color); } break; } } - private boolean shouldIgnoreColor(int color) { - com.android.internal.util.cm.palette.ColorUtils.RGBtoHSL(Color.red(color), Color.green(color), Color.blue(color), mTempHsl); - return shouldIgnoreColor(mTempHsl); + private boolean shouldIgnoreColor(int color565) { + final int rgb = approximateToRgb888(color565); + ColorUtils.colorToHSL(rgb, mTempHsl); + return shouldIgnoreColor(rgb, mTempHsl); } - private static boolean shouldIgnoreColor(Swatch color) { - return shouldIgnoreColor(color.getHsl()); + private boolean shouldIgnoreColor(Swatch color) { + return shouldIgnoreColor(color.getRgb(), color.getHsl()); } - private static boolean shouldIgnoreColor(float[] hslColor) { - return isWhite(hslColor) || isBlack(hslColor) || isNearRedILine(hslColor); + private boolean shouldIgnoreColor(int rgb, float[] hsl) { + if (mFilters != null && mFilters.length > 0) { + for (int i = 0, count = mFilters.length; i < count; i++) { + if (!mFilters[i].isAllowed(rgb, hsl)) { + return true; + } + } + } + return false; } /** - * @return true if the color represents a color which is close to black. + * Comparator which sorts {@link Vbox} instances based on their volume, in descending order + */ + private static final Comparator VBOX_COMPARATOR_VOLUME = new Comparator() { + @Override + public int compare(Vbox lhs, Vbox rhs) { + return rhs.getVolume() - lhs.getVolume(); + } + }; + + /** + * Quantized a RGB888 value to have a word width of {@value #QUANTIZE_WORD_WIDTH}. */ - private static boolean isBlack(float[] hslColor) { - return hslColor[2] <= BLACK_MAX_LIGHTNESS; + private static int quantizeFromRgb888(int color) { + int r = modifyWordWidth(Color.red(color), 8, QUANTIZE_WORD_WIDTH); + int g = modifyWordWidth(Color.green(color), 8, QUANTIZE_WORD_WIDTH); + int b = modifyWordWidth(Color.blue(color), 8, QUANTIZE_WORD_WIDTH); + return r << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH) | g << QUANTIZE_WORD_WIDTH | b; } /** - * @return true if the color represents a color which is close to white. + * Quantized RGB888 values to have a word width of {@value #QUANTIZE_WORD_WIDTH}. */ - private static boolean isWhite(float[] hslColor) { - return hslColor[2] >= WHITE_MIN_LIGHTNESS; + private static int approximateToRgb888(int r, int g, int b) { + return Color.rgb(modifyWordWidth(r, QUANTIZE_WORD_WIDTH, 8), + modifyWordWidth(g, QUANTIZE_WORD_WIDTH, 8), + modifyWordWidth(b, QUANTIZE_WORD_WIDTH, 8)); + } + + private static int approximateToRgb888(int color) { + return approximateToRgb888(quantizedRed(color), quantizedGreen(color), quantizedBlue(color)); } /** - * @return true if the color lies close to the red side of the I line. + * @return red component of the quantized color */ - private static boolean isNearRedILine(float[] hslColor) { - return hslColor[0] >= 10f && hslColor[0] <= 37f && hslColor[1] <= 0.82f; + private static int quantizedRed(int color) { + return (color >> (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)) & QUANTIZE_WORD_MASK; } /** - * Comparator which sorts {@link Vbox} instances based on their volume, in descending order + * @return green component of a quantized color */ - private static final Comparator VBOX_COMPARATOR_VOLUME = new Comparator() { - @Override - public int compare(Vbox lhs, Vbox rhs) { - return rhs.getVolume() - lhs.getVolume(); + private static int quantizedGreen(int color) { + return (color >> QUANTIZE_WORD_WIDTH) & QUANTIZE_WORD_MASK; + } + + /** + * @return blue component of a quantized color + */ + private static int quantizedBlue(int color) { + return color & QUANTIZE_WORD_MASK; + } + + private static int modifyWordWidth(int value, int currentWidth, int targetWidth) { + final int newValue; + if (targetWidth > currentWidth) { + // If we're approximating up in word width, we'll shift up + newValue = value << (targetWidth - currentWidth); + } else { + // Else, we will just shift and keep the MSB + newValue = value >> (currentWidth - targetWidth); } - }; + return newValue & ((1 << targetWidth) - 1); + } } diff --git a/core/java/com/android/internal/util/cm/palette/ColorHistogram.java b/core/java/com/android/internal/util/cm/palette/ColorHistogram.java deleted file mode 100644 index 741982d53f879..0000000000000 --- a/core/java/com/android/internal/util/cm/palette/ColorHistogram.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util.cm.palette; - -import java.util.Arrays; - -/** - * Class which provides a histogram for RGB values. - * - * @hide - */ -final class ColorHistogram { - - private final int[] mColors; - private final int[] mColorCounts; - private final int mNumberColors; - - /** - * A new {@link ColorHistogram} instance. - * - * @param pixels array of image contents - */ - ColorHistogram(final int[] pixels) { - // Sort the pixels to enable counting below - Arrays.sort(pixels); - - // Count number of distinct colors - mNumberColors = countDistinctColors(pixels); - - // Create arrays - mColors = new int[mNumberColors]; - mColorCounts = new int[mNumberColors]; - - // Finally count the frequency of each color - countFrequencies(pixels); - } - - /** - * @return number of distinct colors in the image. - */ - int getNumberOfColors() { - return mNumberColors; - } - - /** - * @return an array containing all of the distinct colors in the image. - */ - int[] getColors() { - return mColors; - } - - /** - * @return an array containing the frequency of a distinct colors within the image. - */ - int[] getColorCounts() { - return mColorCounts; - } - - private static int countDistinctColors(final int[] pixels) { - if (pixels.length < 2) { - // If we have less than 2 pixels we can stop here - return pixels.length; - } - - // If we have at least 2 pixels, we have a minimum of 1 color... - int colorCount = 1; - int currentColor = pixels[0]; - - // Now iterate from the second pixel to the end, counting distinct colors - for (int i = 1; i < pixels.length; i++) { - // If we encounter a new color, increase the population - if (pixels[i] != currentColor) { - currentColor = pixels[i]; - colorCount++; - } - } - - return colorCount; - } - - private void countFrequencies(final int[] pixels) { - if (pixels.length == 0) { - return; - } - - int currentColorIndex = 0; - int currentColor = pixels[0]; - - mColors[currentColorIndex] = currentColor; - mColorCounts[currentColorIndex] = 1; - - if (pixels.length == 1) { - // If we only have one pixel, we can stop here - return; - } - - // Now iterate from the second pixel to the end, population distinct colors - for (int i = 1; i < pixels.length; i++) { - if (pixels[i] == currentColor) { - // We've hit the same color as before, increase population - mColorCounts[currentColorIndex]++; - } else { - // We've hit a new color, increase index - currentColor = pixels[i]; - - currentColorIndex++; - mColors[currentColorIndex] = currentColor; - mColorCounts[currentColorIndex] = 1; - } - } - } - -} diff --git a/core/java/com/android/internal/util/cm/palette/ColorUtils.java b/core/java/com/android/internal/util/cm/palette/ColorUtils.java index c081cf6c94034..8dcf750a2742e 100644 --- a/core/java/com/android/internal/util/cm/palette/ColorUtils.java +++ b/core/java/com/android/internal/util/cm/palette/ColorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * 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. @@ -18,8 +18,12 @@ import android.graphics.Color; -/** @hide */ -final class ColorUtils { +/** + * A set of color-related utility methods, building upon those available in {@code Color}. + * + * @hide + */ +public class ColorUtils { private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10; private static final int MIN_ALPHA_SEARCH_PRECISION = 10; @@ -29,16 +33,28 @@ private ColorUtils() {} /** * Composite two potentially translucent colors over each other and returns the result. */ - private static int compositeColors(int fg, int bg) { - final float alpha1 = Color.alpha(fg) / 255f; - final float alpha2 = Color.alpha(bg) / 255f; + public static int compositeColors(int foreground, int background) { + int bgAlpha = Color.alpha(background); + int fgAlpha = Color.alpha(foreground); + int a = compositeAlpha(fgAlpha, bgAlpha); + + int r = compositeComponent(Color.red(foreground), fgAlpha, + Color.red(background), bgAlpha, a); + int g = compositeComponent(Color.green(foreground), fgAlpha, + Color.green(background), bgAlpha, a); + int b = compositeComponent(Color.blue(foreground), fgAlpha, + Color.blue(background), bgAlpha, a); + + return Color.argb(a, r, g, b); + } - float a = (alpha1 + alpha2) * (1f - alpha1); - float r = (Color.red(fg) * alpha1) + (Color.red(bg) * alpha2 * (1f - alpha1)); - float g = (Color.green(fg) * alpha1) + (Color.green(bg) * alpha2 * (1f - alpha1)); - float b = (Color.blue(fg) * alpha1) + (Color.blue(bg) * alpha2 * (1f - alpha1)); + private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) { + return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF); + } - return Color.argb((int) a, (int) r, (int) g, (int) b); + private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) { + if (a == 0) return 0; + return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF); } /** @@ -46,7 +62,7 @@ private static int compositeColors(int fg, int bg) { * * Formula defined here: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef */ - private static double calculateLuminance(int color) { + public static double calculateLuminance(int color) { double red = Color.red(color) / 255d; red = red < 0.03928 ? red / 12.92 : Math.pow((red + 0.055) / 1.055, 2.4); @@ -60,11 +76,13 @@ private static double calculateLuminance(int color) { } /** - * Returns the contrast ratio between two colors. - * - * Formula defined here: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef + * Returns the contrast ratio between {@code foreground} and {@code background}. + * {@code background} must be opaque. + *
    + *
  • hsl[0] is Hue [0 .. 360)
  • + *
  • hsl[1] is Saturation [0...1]
  • + *
  • hsl[2] is Lightness [0...1]
  • + *
+ * + * @param r red component value [0..255] + * @param g green component value [0..255] + * @param b blue component value [0..255] + * @param hsl 3 element array which holds the resulting HSL components. + */ + public static void RGBToHSL(int r, int g, int b, float[] hsl) { final float rf = r / 255f; final float gf = g / 255f; final float bf = b / 255f; @@ -160,15 +184,47 @@ static void RGBtoHSL(int r, int g, int b, float[] hsl) { h = ((rf - gf) / deltaMaxMin) + 4f; } - s = deltaMaxMin / (1f - Math.abs(2f * l - 1f)); + s = deltaMaxMin / (1f - Math.abs(2f * l - 1f)); + } + + h = (h * 60f) % 360f; + if (h < 0) { + h += 360f; } - hsl[0] = (h * 60f) % 360f; - hsl[1] = s; - hsl[2] = l; + hsl[0] = constrain(h, 0f, 360f); + hsl[1] = constrain(s, 0f, 1f); + hsl[2] = constrain(l, 0f, 1f); } - static int HSLtoRGB (float[] hsl) { + /** + * Convert the ARGB color to its HSL (hue-saturation-lightness) components. + *
    + *
  • hsl[0] is Hue [0 .. 360)
  • + *
  • hsl[1] is Saturation [0...1]
  • + *
  • hsl[2] is Lightness [0...1]
  • + *
+ * + * @param color the ARGB color to convert. The alpha component is ignored. + * @param hsl 3 element array which holds the resulting HSL components. + */ + public static void colorToHSL(int color, float[] hsl) { + RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl); + } + + /** + * Convert HSL (hue-saturation-lightness) components to a RGB color. + *
    + *
  • hsl[0] is Hue [0 .. 360)
  • + *
  • hsl[1] is Saturation [0...1]
  • + *
  • hsl[2] is Lightness [0...1]
  • + *
+ * If hsv values are out of range, they are pinned. + * + * @param hsl 3 element array which holds the input HSL components. + * @return the resulting RGB color + */ + public static int HSLToColor(float[] hsl) { final float h = hsl[0]; final float s = hsl[1]; final float l = hsl[2]; @@ -215,9 +271,9 @@ static int HSLtoRGB (float[] hsl) { break; } - r = Math.max(0, Math.min(255, r)); - g = Math.max(0, Math.min(255, g)); - b = Math.max(0, Math.min(255, b)); + r = constrain(r, 0, 255); + g = constrain(g, 0, 255); + b = constrain(b, 0, 255); return Color.rgb(r, g, b); } @@ -225,8 +281,19 @@ static int HSLtoRGB (float[] hsl) { /** * Set the alpha component of {@code color} to be {@code alpha}. */ - static int modifyAlpha(int color, int alpha) { + public static int setAlphaComponent(int color, int alpha) { + if (alpha < 0 || alpha > 255) { + throw new IllegalArgumentException("alpha must be between 0 and 255."); + } return (color & 0x00ffffff) | (alpha << 24); } + private static float constrain(float amount, float low, float high) { + return amount < low ? low : (amount > high ? high : amount); + } + + private static int constrain(int amount, int low, int high) { + return amount < low ? low : (amount > high ? high : amount); + } + } diff --git a/core/java/com/android/internal/util/cm/palette/DefaultGenerator.java b/core/java/com/android/internal/util/cm/palette/DefaultGenerator.java new file mode 100644 index 0000000000000..407f01d57fa97 --- /dev/null +++ b/core/java/com/android/internal/util/cm/palette/DefaultGenerator.java @@ -0,0 +1,244 @@ +/* + * 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. + */ + +package com.android.internal.util.cm.palette; + +import com.android.internal.util.cm.palette.Palette.Swatch; + +import java.util.List; + +/** + * @hide + */ +class DefaultGenerator extends Palette.Generator { + + private static final float TARGET_DARK_LUMA = 0.26f; + private static final float MAX_DARK_LUMA = 0.45f; + + private static final float MIN_LIGHT_LUMA = 0.55f; + private static final float TARGET_LIGHT_LUMA = 0.74f; + + private static final float MIN_NORMAL_LUMA = 0.3f; + private static final float TARGET_NORMAL_LUMA = 0.5f; + private static final float MAX_NORMAL_LUMA = 0.7f; + + private static final float TARGET_MUTED_SATURATION = 0.3f; + private static final float MAX_MUTED_SATURATION = 0.4f; + + private static final float TARGET_VIBRANT_SATURATION = 1f; + private static final float MIN_VIBRANT_SATURATION = 0.35f; + + private static final float WEIGHT_SATURATION = 3f; + private static final float WEIGHT_LUMA = 6f; + private static final float WEIGHT_POPULATION = 1f; + + private List mSwatches; + + private int mHighestPopulation; + + private Swatch mVibrantSwatch; + private Swatch mMutedSwatch; + private Swatch mDarkVibrantSwatch; + private Swatch mDarkMutedSwatch; + private Swatch mLightVibrantSwatch; + private Swatch mLightMutedSwatch; + + @Override + public void generate(final List swatches) { + mSwatches = swatches; + + mHighestPopulation = findMaxPopulation(); + + generateVariationColors(); + + // Now try and generate any missing colors + generateEmptySwatches(); + } + + @Override + public Swatch getVibrantSwatch() { + return mVibrantSwatch; + } + + @Override + public Swatch getLightVibrantSwatch() { + return mLightVibrantSwatch; + } + + @Override + public Swatch getDarkVibrantSwatch() { + return mDarkVibrantSwatch; + } + + @Override + public Swatch getMutedSwatch() { + return mMutedSwatch; + } + + @Override + public Swatch getLightMutedSwatch() { + return mLightMutedSwatch; + } + + @Override + public Swatch getDarkMutedSwatch() { + return mDarkMutedSwatch; + } + + private void generateVariationColors() { + mVibrantSwatch = findColorVariation(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA, + TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f); + + mLightVibrantSwatch = findColorVariation(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f, + TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f); + + mDarkVibrantSwatch = findColorVariation(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA, + TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f); + + mMutedSwatch = findColorVariation(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA, + TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION); + + mLightMutedSwatch = findColorVariation(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f, + TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION); + + mDarkMutedSwatch = findColorVariation(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA, + TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION); + } + + /** + * Try and generate any missing swatches from the swatches we did find. + */ + private void generateEmptySwatches() { + if (mVibrantSwatch == null) { + // If we do not have a vibrant color... + if (mDarkVibrantSwatch != null) { + // ...but we do have a dark vibrant, generate the value by modifying the luma + final float[] newHsl = copyHslValues(mDarkVibrantSwatch); + newHsl[2] = TARGET_NORMAL_LUMA; + mVibrantSwatch = new Swatch(ColorUtils.HSLToColor(newHsl), 0); + } + } + + if (mDarkVibrantSwatch == null) { + // If we do not have a dark vibrant color... + if (mVibrantSwatch != null) { + // ...but we do have a vibrant, generate the value by modifying the luma + final float[] newHsl = copyHslValues(mVibrantSwatch); + newHsl[2] = TARGET_DARK_LUMA; + mDarkVibrantSwatch = new Swatch(ColorUtils.HSLToColor(newHsl), 0); + } + } + } + + /** + * Find the {@link Palette.Swatch} with the highest population value and return the population. + */ + private int findMaxPopulation() { + int population = 0; + for (Swatch swatch : mSwatches) { + population = Math.max(population, swatch.getPopulation()); + } + return population; + } + + private Swatch findColorVariation(float targetLuma, float minLuma, float maxLuma, + float targetSaturation, float minSaturation, float maxSaturation) { + Swatch max = null; + float maxValue = 0f; + + for (Swatch swatch : mSwatches) { + final float sat = swatch.getHsl()[1]; + final float luma = swatch.getHsl()[2]; + + if (sat >= minSaturation && sat <= maxSaturation && + luma >= minLuma && luma <= maxLuma && + !isAlreadySelected(swatch)) { + float value = createComparisonValue(sat, targetSaturation, luma, targetLuma, + swatch.getPopulation(), mHighestPopulation); + if (max == null || value > maxValue) { + max = swatch; + maxValue = value; + } + } + } + + return max; + } + + /** + * @return true if we have already selected {@code swatch} + */ + private boolean isAlreadySelected(Swatch swatch) { + return mVibrantSwatch == swatch || mDarkVibrantSwatch == swatch || + mLightVibrantSwatch == swatch || mMutedSwatch == swatch || + mDarkMutedSwatch == swatch || mLightMutedSwatch == swatch; + } + + private static float createComparisonValue(float saturation, float targetSaturation, + float luma, float targetLuma, + int population, int maxPopulation) { + return createComparisonValue(saturation, targetSaturation, WEIGHT_SATURATION, + luma, targetLuma, WEIGHT_LUMA, + population, maxPopulation, WEIGHT_POPULATION); + } + + private static float createComparisonValue( + float saturation, float targetSaturation, float saturationWeight, + float luma, float targetLuma, float lumaWeight, + int population, int maxPopulation, float populationWeight) { + return weightedMean( + invertDiff(saturation, targetSaturation), saturationWeight, + invertDiff(luma, targetLuma), lumaWeight, + population / (float) maxPopulation, populationWeight + ); + } + + /** + * Copy a {@link Swatch}'s HSL values into a new float[]. + */ + private static float[] copyHslValues(Swatch color) { + final float[] newHsl = new float[3]; + System.arraycopy(color.getHsl(), 0, newHsl, 0, 3); + return newHsl; + } + + /** + * Returns a value in the range 0-1. 1 is returned when {@code value} equals the + * {@code targetValue} and then decreases as the absolute difference between {@code value} and + * {@code targetValue} increases. + * + * @param value the item's value + * @param targetValue the value which we desire + */ + private static float invertDiff(float value, float targetValue) { + return 1f - Math.abs(value - targetValue); + } + + private static float weightedMean(float... values) { + float sum = 0f; + float sumWeight = 0f; + + for (int i = 0; i < values.length; i += 2) { + float value = values[i]; + float weight = values[i + 1]; + + sum += (value * weight); + sumWeight += weight; + } + + return sum / sumWeight; + } +} diff --git a/core/java/com/android/internal/util/cm/palette/Palette.java b/core/java/com/android/internal/util/cm/palette/Palette.java index d0a62f030b5a8..2cbd2b8e1bd66 100644 --- a/core/java/com/android/internal/util/cm/palette/Palette.java +++ b/core/java/com/android/internal/util/cm/palette/Palette.java @@ -19,7 +19,11 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.os.AsyncTask; +import android.annotation.ColorInt; +import android.annotation.Nullable; +import android.util.TimingLogger; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -39,18 +43,21 @@ * These can be retrieved from the appropriate getter method. * *

- * Instances can be created with the synchronous factory methods {@link #generate(Bitmap)} and - * {@link #generate(Bitmap, int)}. + * Instances are created with a {@link Builder} which supports several options to tweak the + * generated Palette. See that class' documentation for more information. *

- * These should be called on a background thread, ideally the one in - * which you load your images on. Sometimes that is not possible, so asynchronous factory methods - * have also been provided: {@link #generateAsync(Bitmap, PaletteAsyncListener)} and - * {@link #generateAsync(Bitmap, int, PaletteAsyncListener)}. These can be used as so: + * Generation should always be completed on a background thread, ideally the one in + * which you load your image on. {@link Builder} supports both synchronous and asynchronous + * generation: * *

- * Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
- *     public void onGenerated(Palette palette) {
- *         // Do something with colors...
+ * // Synchronous
+ * Palette p = Palette.from(bitmap).generate();
+ *
+ * // Asynchronous
+ * Palette.from(bitmap).generate(new PaletteAsyncListener() {
+ *     public void onGenerated(Palette p) {
+ *         // Use generated instance
  *     }
  * });
  * 
@@ -71,160 +78,71 @@ public interface PaletteAsyncListener { void onGenerated(Palette palette); } - private static final int CALCULATE_BITMAP_MIN_DIMENSION = 100; + private static final int DEFAULT_RESIZE_BITMAP_MAX_DIMENSION = 192; private static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16; - private static final float TARGET_DARK_LUMA = 0.26f; - private static final float MAX_DARK_LUMA = 0.45f; - - private static final float MIN_LIGHT_LUMA = 0.55f; - private static final float TARGET_LIGHT_LUMA = 0.74f; - - private static final float MIN_NORMAL_LUMA = 0.3f; - private static final float TARGET_NORMAL_LUMA = 0.5f; - private static final float MAX_NORMAL_LUMA = 0.7f; - - private static final float TARGET_MUTED_SATURATION = 0.3f; - private static final float MAX_MUTED_SATURATION = 0.4f; - - private static final float TARGET_VIBRANT_SATURATION = 1f; - private static final float MIN_VIBRANT_SATURATION = 0.35f; - - private static final float WEIGHT_SATURATION = 3f; - private static final float WEIGHT_LUMA = 6f; - private static final float WEIGHT_POPULATION = 1f; - private static final float MIN_CONTRAST_TITLE_TEXT = 3.0f; private static final float MIN_CONTRAST_BODY_TEXT = 4.5f; - private final List mSwatches; - private final int mHighestPopulation; - - private Swatch mVibrantSwatch; - private Swatch mMutedSwatch; + private static final String LOG_TAG = "Palette"; + private static final boolean LOG_TIMINGS = false; - private Swatch mDarkVibrantSwatch; - private Swatch mDarkMutedSwatch; + /** + * Start generating a {@link Palette} with the returned {@link Builder} instance. + */ + public static Builder from(Bitmap bitmap) { + return new Builder(bitmap); + } - private Swatch mLightVibrantSwatch; - private Swatch mLightMutedColor; + /** + * Generate a {@link Palette} from the pre-generated list of {@link Palette.Swatch} swatches. + * This is useful for testing, or if you want to resurrect a {@link Palette} instance from a + * list of swatches. Will return null if the {@code swatches} is null. + */ + public static Palette from(List swatches) { + return new Builder(swatches).generate(); + } /** - * Generate a {@link Palette} from a {@link Bitmap} using the default number of colors. + * @deprecated Use {@link Builder} to generate the Palette. */ + @Deprecated public static Palette generate(Bitmap bitmap) { - return generate(bitmap, DEFAULT_CALCULATE_NUMBER_COLORS); + return from(bitmap).generate(); } /** - * Generate a {@link Palette} from a {@link Bitmap} using the specified {@code numColors}. - * Good values for {@code numColors} depend on the source image type. - * For landscapes, a good values are in the range 12-16. For images which are largely made up - * of people's faces then this value should be increased to 24-32. - * - * @param numColors The maximum number of colors in the generated palette. Increasing this - * number will increase the time needed to compute the values. + * @deprecated Use {@link Builder} to generate the Palette. */ + @Deprecated public static Palette generate(Bitmap bitmap, int numColors) { - checkBitmapParam(bitmap); - checkNumberColorsParam(numColors); - - // First we'll scale down the bitmap so it's shortest dimension is 100px - final Bitmap scaledBitmap = scaleBitmapDown(bitmap); - - // Now generate a quantizer from the Bitmap - ColorCutQuantizer quantizer = ColorCutQuantizer.fromBitmap(scaledBitmap, numColors); - - // If created a new bitmap, recycle it - if (scaledBitmap != bitmap) { - scaledBitmap.recycle(); - } - - // Now return a ColorExtractor instance - return new Palette(quantizer.getQuantizedColors()); + return from(bitmap).maximumColorCount(numColors).generate(); } /** - * Generate a {@link Palette} asynchronously. {@link PaletteAsyncListener#onGenerated(Palette)} - * will be called with the created instance. The resulting {@link Palette} is the same as - * what would be created by calling {@link #generate(Bitmap)}. - * - * @param listener Listener to be invoked when the {@link Palette} has been generated. - * - * @return the {@link AsyncTask} used to asynchronously generate the instance. + * @deprecated Use {@link Builder} to generate the Palette. */ + @Deprecated public static AsyncTask generateAsync( Bitmap bitmap, PaletteAsyncListener listener) { - return generateAsync(bitmap, DEFAULT_CALCULATE_NUMBER_COLORS, listener); + return from(bitmap).generate(listener); } /** - * Generate a {@link Palette} asynchronously. {@link PaletteAsyncListener#onGenerated(Palette)} - * will be called with the created instance. The resulting {@link Palette} is the same as what - * would be created by calling {@link #generate(Bitmap, int)}. - * - * @param listener Listener to be invoked when the {@link Palette} has been generated. - * - * @return the {@link AsyncTask} used to asynchronously generate the instance. + * @deprecated Use {@link Builder} to generate the Palette. */ + @Deprecated public static AsyncTask generateAsync( final Bitmap bitmap, final int numColors, final PaletteAsyncListener listener) { - checkBitmapParam(bitmap); - checkNumberColorsParam(numColors); - checkAsyncListenerParam(listener); - - AsyncTask task = new AsyncTask() { - @Override - protected Palette doInBackground(Bitmap... params) { - return generate(params[0], numColors); - } - - @Override - protected void onPostExecute(Palette colorExtractor) { - listener.onGenerated(colorExtractor); - } - }; - task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, bitmap); - - return task; + return from(bitmap).maximumColorCount(numColors).generate(listener); } - /** - * Generate a {@link Palette} from the pre-generated list of {@link Palette.Swatch} swatches. - * This is useful for testing, or if you want to resurrect a {@link Palette} instance from a - * list of swatches. Will return null if the {@code swatches} is null. - */ - public static Palette from(List swatches) { - if (swatches == null) { - return null; - } - return new Palette(swatches); - } + private final List mSwatches; + private final Generator mGenerator; - private Palette(List swatches) { + private Palette(List swatches, Generator generator) { mSwatches = swatches; - mHighestPopulation = findMaxPopulation(); - - mVibrantSwatch = findColor(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA, - TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f); - - mLightVibrantSwatch = findColor(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f, - TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f); - - mDarkVibrantSwatch = findColor(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA, - TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f); - - mMutedSwatch = findColor(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA, - TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION); - - mLightMutedColor = findColor(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f, - TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION); - - mDarkMutedSwatch = findColor(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA, - TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION); - - // Now try and generate any missing colors - generateEmptySwatches(); + mGenerator = generator; } /** @@ -237,43 +155,49 @@ public List getSwatches() { /** * Returns the most vibrant swatch in the palette. Might be null. */ + @Nullable public Swatch getVibrantSwatch() { - return mVibrantSwatch; + return mGenerator.getVibrantSwatch(); } /** * Returns a light and vibrant swatch from the palette. Might be null. */ + @Nullable public Swatch getLightVibrantSwatch() { - return mLightVibrantSwatch; + return mGenerator.getLightVibrantSwatch(); } /** * Returns a dark and vibrant swatch from the palette. Might be null. */ + @Nullable public Swatch getDarkVibrantSwatch() { - return mDarkVibrantSwatch; + return mGenerator.getDarkVibrantSwatch(); } /** * Returns a muted swatch from the palette. Might be null. */ + @Nullable public Swatch getMutedSwatch() { - return mMutedSwatch; + return mGenerator.getMutedSwatch(); } /** * Returns a muted and light swatch from the palette. Might be null. */ + @Nullable public Swatch getLightMutedSwatch() { - return mLightMutedColor; + return mGenerator.getLightMutedSwatch(); } /** * Returns a muted and dark swatch from the palette. Might be null. */ + @Nullable public Swatch getDarkMutedSwatch() { - return mDarkMutedSwatch; + return mGenerator.getDarkMutedSwatch(); } /** @@ -281,8 +205,10 @@ public Swatch getDarkMutedSwatch() { * * @param defaultColor value to return if the swatch isn't available */ - public int getVibrantColor(int defaultColor) { - return mVibrantSwatch != null ? mVibrantSwatch.getRgb() : defaultColor; + @ColorInt + public int getVibrantColor(@ColorInt int defaultColor) { + Swatch swatch = getVibrantSwatch(); + return swatch != null ? swatch.getRgb() : defaultColor; } /** @@ -290,8 +216,10 @@ public int getVibrantColor(int defaultColor) { * * @param defaultColor value to return if the swatch isn't available */ - public int getLightVibrantColor(int defaultColor) { - return mLightVibrantSwatch != null ? mLightVibrantSwatch.getRgb() : defaultColor; + @ColorInt + public int getLightVibrantColor(@ColorInt int defaultColor) { + Swatch swatch = getLightVibrantSwatch(); + return swatch != null ? swatch.getRgb() : defaultColor; } /** @@ -299,8 +227,10 @@ public int getLightVibrantColor(int defaultColor) { * * @param defaultColor value to return if the swatch isn't available */ - public int getDarkVibrantColor(int defaultColor) { - return mDarkVibrantSwatch != null ? mDarkVibrantSwatch.getRgb() : defaultColor; + @ColorInt + public int getDarkVibrantColor(@ColorInt int defaultColor) { + Swatch swatch = getDarkVibrantSwatch(); + return swatch != null ? swatch.getRgb() : defaultColor; } /** @@ -308,8 +238,10 @@ public int getDarkVibrantColor(int defaultColor) { * * @param defaultColor value to return if the swatch isn't available */ - public int getMutedColor(int defaultColor) { - return mMutedSwatch != null ? mMutedSwatch.getRgb() : defaultColor; + @ColorInt + public int getMutedColor(@ColorInt int defaultColor) { + Swatch swatch = getMutedSwatch(); + return swatch != null ? swatch.getRgb() : defaultColor; } /** @@ -317,8 +249,10 @@ public int getMutedColor(int defaultColor) { * * @param defaultColor value to return if the swatch isn't available */ - public int getLightMutedColor(int defaultColor) { - return mLightMutedColor != null ? mLightMutedColor.getRgb() : defaultColor; + @ColorInt + public int getLightMutedColor(@ColorInt int defaultColor) { + Swatch swatch = getLightMutedSwatch(); + return swatch != null ? swatch.getRgb() : defaultColor; } /** @@ -326,220 +260,31 @@ public int getLightMutedColor(int defaultColor) { * * @param defaultColor value to return if the swatch isn't available */ - public int getDarkMutedColor(int defaultColor) { - return mDarkMutedSwatch != null ? mDarkMutedSwatch.getRgb() : defaultColor; + @ColorInt + public int getDarkMutedColor(@ColorInt int defaultColor) { + Swatch swatch = getDarkMutedSwatch(); + return swatch != null ? swatch.getRgb() : defaultColor; } /** - * @return true if we have already selected {@code swatch} + * Scale the bitmap down so that it's largest dimension is {@code targetMaxDimension}. + * If {@code bitmap} is smaller than this, then it is returned. */ - private boolean isAlreadySelected(Swatch swatch) { - return mVibrantSwatch == swatch || mDarkVibrantSwatch == swatch || - mLightVibrantSwatch == swatch || mMutedSwatch == swatch || - mDarkMutedSwatch == swatch || mLightMutedColor == swatch; - } - - private Swatch findColor(float targetLuma, float minLuma, float maxLuma, - float targetSaturation, float minSaturation, float maxSaturation) { - Swatch max = null; - float maxValue = 0f; - - for (Swatch swatch : mSwatches) { - final float sat = swatch.getHsl()[1]; - final float luma = swatch.getHsl()[2]; - - if (sat >= minSaturation && sat <= maxSaturation && - luma >= minLuma && luma <= maxLuma && - !isAlreadySelected(swatch)) { - float thisValue = createComparisonValue(sat, targetSaturation, luma, targetLuma, - swatch.getPopulation(), mHighestPopulation); - if (max == null || thisValue > maxValue) { - max = swatch; - maxValue = thisValue; - } - } - } + private static Bitmap scaleBitmapDown(Bitmap bitmap, final int targetMaxDimension) { + final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight()); - return max; - } - - /** - * Try and generate any missing swatches from the swatches we did find. - */ - private void generateEmptySwatches() { - if (mVibrantSwatch == null) { - // If we do not have a vibrant color... - if (mDarkVibrantSwatch != null) { - // ...but we do have a dark vibrant, generate the value by modifying the luma - final float[] newHsl = copyHslValues(mDarkVibrantSwatch); - newHsl[2] = TARGET_NORMAL_LUMA; - mVibrantSwatch = new Swatch(ColorUtils.HSLtoRGB(newHsl), 0); - } - } - - if (mDarkVibrantSwatch == null) { - // If we do not have a dark vibrant color... - if (mVibrantSwatch != null) { - // ...but we do have a vibrant, generate the value by modifying the luma - final float[] newHsl = copyHslValues(mVibrantSwatch); - newHsl[2] = TARGET_DARK_LUMA; - mDarkVibrantSwatch = new Swatch(ColorUtils.HSLtoRGB(newHsl), 0); - } - } - } - - /** - * Find the {@link Swatch} with the highest population value and return the population. - */ - private int findMaxPopulation() { - int population = 0; - for (Swatch swatch : mSwatches) { - population = Math.max(population, swatch.getPopulation()); - } - return population; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Palette palette = (Palette) o; - - if (mSwatches != null ? !mSwatches.equals(palette.mSwatches) : palette.mSwatches != null) { - return false; - } - if (mDarkMutedSwatch != null ? !mDarkMutedSwatch.equals(palette.mDarkMutedSwatch) - : palette.mDarkMutedSwatch != null) { - return false; - } - if (mDarkVibrantSwatch != null ? !mDarkVibrantSwatch.equals(palette.mDarkVibrantSwatch) - : palette.mDarkVibrantSwatch != null) { - return false; - } - if (mLightMutedColor != null ? !mLightMutedColor.equals(palette.mLightMutedColor) - : palette.mLightMutedColor != null) { - return false; - } - if (mLightVibrantSwatch != null ? !mLightVibrantSwatch.equals(palette.mLightVibrantSwatch) - : palette.mLightVibrantSwatch != null) { - return false; - } - if (mMutedSwatch != null ? !mMutedSwatch.equals(palette.mMutedSwatch) - : palette.mMutedSwatch != null) { - return false; - } - if (mVibrantSwatch != null ? !mVibrantSwatch.equals(palette.mVibrantSwatch) - : palette.mVibrantSwatch != null) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = mSwatches != null ? mSwatches.hashCode() : 0; - result = 31 * result + (mVibrantSwatch != null ? mVibrantSwatch.hashCode() : 0); - result = 31 * result + (mMutedSwatch != null ? mMutedSwatch.hashCode() : 0); - result = 31 * result + (mDarkVibrantSwatch != null ? mDarkVibrantSwatch.hashCode() : 0); - result = 31 * result + (mDarkMutedSwatch != null ? mDarkMutedSwatch.hashCode() : 0); - result = 31 * result + (mLightVibrantSwatch != null ? mLightVibrantSwatch.hashCode() : 0); - result = 31 * result + (mLightMutedColor != null ? mLightMutedColor.hashCode() : 0); - return result; - } - - /** - * Scale the bitmap down so that it's smallest dimension is - * {@value #CALCULATE_BITMAP_MIN_DIMENSION}px. If {@code bitmap} is smaller than this, than it - * is returned. - */ - private static Bitmap scaleBitmapDown(Bitmap bitmap) { - final int minDimension = Math.min(bitmap.getWidth(), bitmap.getHeight()); - - if (minDimension <= CALCULATE_BITMAP_MIN_DIMENSION) { + if (maxDimension <= targetMaxDimension) { // If the bitmap is small enough already, just return it return bitmap; } - final float scaleRatio = CALCULATE_BITMAP_MIN_DIMENSION / (float) minDimension; + final float scaleRatio = targetMaxDimension / (float) maxDimension; return Bitmap.createScaledBitmap(bitmap, Math.round(bitmap.getWidth() * scaleRatio), Math.round(bitmap.getHeight() * scaleRatio), false); } - private static float createComparisonValue(float saturation, float targetSaturation, - float luma, float targetLuma, - int population, int highestPopulation) { - return weightedMean( - invertDiff(saturation, targetSaturation), WEIGHT_SATURATION, - invertDiff(luma, targetLuma), WEIGHT_LUMA, - population / (float) highestPopulation, WEIGHT_POPULATION - ); - } - - /** - * Copy a {@link Swatch}'s HSL values into a new float[]. - */ - private static float[] copyHslValues(Swatch color) { - final float[] newHsl = new float[3]; - System.arraycopy(color.getHsl(), 0, newHsl, 0, 3); - return newHsl; - } - - /** - * Returns a value in the range 0-1. 1 is returned when {@code value} equals the - * {@code targetValue} and then decreases as the absolute difference between {@code value} and - * {@code targetValue} increases. - * - * @param value the item's value - * @param targetValue the value which we desire - */ - private static float invertDiff(float value, float targetValue) { - return 1f - Math.abs(value - targetValue); - } - - private static float weightedMean(float... values) { - float sum = 0f; - float sumWeight = 0f; - - for (int i = 0; i < values.length; i += 2) { - float value = values[i]; - float weight = values[i + 1]; - - sum += (value * weight); - sumWeight += weight; - } - - return sum / sumWeight; - } - - private static void checkBitmapParam(Bitmap bitmap) { - if (bitmap == null) { - throw new IllegalArgumentException("bitmap can not be null"); - } - if (bitmap.isRecycled()) { - throw new IllegalArgumentException("bitmap can not be recycled"); - } - } - - private static void checkNumberColorsParam(int numColors) { - if (numColors < 1) { - throw new IllegalArgumentException("numColors must be 1 of greater"); - } - } - - private static void checkAsyncListenerParam(PaletteAsyncListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener can not be null"); - } - } - /** * Represents a color swatch generated from an image's palette. The RGB color can be retrieved * by calling {@link #getRgb()}. @@ -555,7 +300,7 @@ public static final class Swatch { private float[] mHsl; - public Swatch(int color, int population) { + public Swatch(@ColorInt int color, int population) { mRed = Color.red(color); mGreen = Color.green(color); mBlue = Color.blue(color); @@ -574,6 +319,7 @@ public Swatch(int color, int population) { /** * @return this swatch's RGB color value */ + @ColorInt public int getRgb() { return mRgb; } @@ -586,9 +332,8 @@ public int getRgb() { */ public float[] getHsl() { if (mHsl == null) { - // Lazily generate HSL values from RGB mHsl = new float[3]; - ColorUtils.RGBtoHSL(mRed, mGreen, mBlue, mHsl); + ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl); } return mHsl; } @@ -604,6 +349,7 @@ public int getPopulation() { * Returns an appropriate color to use for any 'title' text which is displayed over this * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast. */ + @ColorInt public int getTitleTextColor() { ensureTextColorsGenerated(); return mTitleTextColor; @@ -613,6 +359,7 @@ public int getTitleTextColor() { * Returns an appropriate color to use for any 'body' text which is displayed over this * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast. */ + @ColorInt public int getBodyTextColor() { ensureTextColorsGenerated(); return mBodyTextColor; @@ -621,36 +368,40 @@ public int getBodyTextColor() { private void ensureTextColorsGenerated() { if (!mGeneratedTextColors) { // First check white, as most colors will be dark - final int lightBody = ColorUtils.getTextColorForBackground( - mRgb, Color.WHITE, MIN_CONTRAST_BODY_TEXT); - final int lightTitle = ColorUtils.getTextColorForBackground( - mRgb, Color.WHITE, MIN_CONTRAST_TITLE_TEXT); + final int lightBodyAlpha = ColorUtils.calculateMinimumAlpha( + Color.WHITE, mRgb, MIN_CONTRAST_BODY_TEXT); + final int lightTitleAlpha = ColorUtils.calculateMinimumAlpha( + Color.WHITE, mRgb, MIN_CONTRAST_TITLE_TEXT); - if (lightBody != -1 && lightTitle != -1) { + if (lightBodyAlpha != -1 && lightTitleAlpha != -1) { // If we found valid light values, use them and return - mBodyTextColor = lightBody; - mTitleTextColor = lightTitle; + mBodyTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha); + mTitleTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha); mGeneratedTextColors = true; return; } - final int darkBody = ColorUtils.getTextColorForBackground( - mRgb, Color.BLACK, MIN_CONTRAST_BODY_TEXT); - final int darkTitle = ColorUtils.getTextColorForBackground( - mRgb, Color.BLACK, MIN_CONTRAST_TITLE_TEXT); + final int darkBodyAlpha = ColorUtils.calculateMinimumAlpha( + Color.BLACK, mRgb, MIN_CONTRAST_BODY_TEXT); + final int darkTitleAlpha = ColorUtils.calculateMinimumAlpha( + Color.BLACK, mRgb, MIN_CONTRAST_TITLE_TEXT); - if (darkBody != -1 && darkBody != -1) { + if (darkBodyAlpha != -1 && darkBodyAlpha != -1) { // If we found valid dark values, use them and return - mBodyTextColor = darkBody; - mTitleTextColor = darkTitle; + mBodyTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha); + mTitleTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha); mGeneratedTextColors = true; return; } // If we reach here then we can not find title and body values which use the same // lightness, we need to use mismatched values - mBodyTextColor = lightBody != -1 ? lightBody : darkBody; - mTitleTextColor = lightTitle != -1 ? lightTitle : darkTitle; + mBodyTextColor = lightBodyAlpha != -1 + ? ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha) + : ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha); + mTitleTextColor = lightTitleAlpha != -1 + ? ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha) + : ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha); mGeneratedTextColors = true; } } @@ -661,9 +412,10 @@ public String toString() { .append(" [RGB: #").append(Integer.toHexString(getRgb())).append(']') .append(" [HSL: ").append(Arrays.toString(getHsl())).append(']') .append(" [Population: ").append(mPopulation).append(']') - .append(" [Title Text: #").append(Integer.toHexString(mTitleTextColor)).append(']') - .append(" [Body Text: #").append(Integer.toHexString(mBodyTextColor)).append(']') - .toString(); + .append(" [Title Text: #").append(Integer.toHexString(getTitleTextColor())) + .append(']') + .append(" [Body Text: #").append(Integer.toHexString(getBodyTextColor())) + .append(']').toString(); } @Override @@ -685,4 +437,304 @@ public int hashCode() { } } + /** + * Builder class for generating {@link Palette} instances. + */ + public static final class Builder { + private List mSwatches; + private Bitmap mBitmap; + private int mMaxColors = DEFAULT_CALCULATE_NUMBER_COLORS; + private int mResizeMaxDimension = DEFAULT_RESIZE_BITMAP_MAX_DIMENSION; + private final List mFilters = new ArrayList<>(); + + private Generator mGenerator; + + /** + * Construct a new {@link Builder} using a source {@link Bitmap} + */ + public Builder(Bitmap bitmap) { + this(); + if (bitmap == null || bitmap.isRecycled()) { + throw new IllegalArgumentException("Bitmap is not valid"); + } + mBitmap = bitmap; + } + + /** + * Construct a new {@link Builder} using a list of {@link Swatch} instances. + * Typically only used for testing. + */ + public Builder(List swatches) { + this(); + if (swatches == null || swatches.isEmpty()) { + throw new IllegalArgumentException("List of Swatches is not valid"); + } + mSwatches = swatches; + } + + private Builder() { + mFilters.add(DEFAULT_FILTER); + } + + /** + * Set the {@link Generator} to use when generating the {@link Palette}. If this is called + * with {@code null} then the default generator will be used. + */ + Builder generator(Generator generator) { + mGenerator = generator; + return this; + } + + /** + * Set the maximum number of colors to use in the quantization step when using a + * {@link android.graphics.Bitmap} as the source. + *

+ * Good values for depend on the source image type. For landscapes, good values are in + * the range 10-16. For images which are largely made up of people's faces then this + * value should be increased to ~24. + */ + public Builder maximumColorCount(int colors) { + mMaxColors = colors; + return this; + } + + /** + * Set the resize value when using a {@link android.graphics.Bitmap} as the source. + * If the bitmap's largest dimension is greater than the value specified, then the bitmap + * will be resized so that it's largest dimension matches {@code maxDimension}. If the + * bitmap is smaller or equal, the original is used as-is. + *

+ * This value has a large effect on the processing time. The larger the resized image is, + * the greater time it will take to generate the palette. The smaller the image is, the + * more detail is lost in the resulting image and thus less precision for color selection. + */ + public Builder resizeBitmapSize(int maxDimension) { + mResizeMaxDimension = maxDimension; + return this; + } + + /** + * Clear all added filters. This includes any default filters added automatically by + * {@link Palette}. + */ + public Builder clearFilters() { + mFilters.clear(); + return this; + } + + /** + * Add a filter to be able to have fine grained controlled over the colors which are + * allowed in the resulting palette. + * + * @param filter filter to add. + */ + public Builder addFilter(Filter filter) { + if (filter != null) { + mFilters.add(filter); + } + return this; + } + + /** + * Generate and return the {@link Palette} synchronously. + */ + public Palette generate() { + final TimingLogger logger = LOG_TIMINGS + ? new TimingLogger(LOG_TAG, "Generation") + : null; + + List swatches; + + if (mBitmap != null) { + // We have a Bitmap so we need to quantization to reduce the number of colors + + if (mResizeMaxDimension <= 0) { + throw new IllegalArgumentException( + "Minimum dimension size for resizing should should be >= 1"); + } + + // First we'll scale down the bitmap so it's largest dimension is as specified + final Bitmap scaledBitmap = scaleBitmapDown(mBitmap, mResizeMaxDimension); + + if (logger != null) { + logger.addSplit("Processed Bitmap"); + } + + // Now generate a quantizer from the Bitmap + final int width = scaledBitmap.getWidth(); + final int height = scaledBitmap.getHeight(); + final int[] pixels = new int[width * height]; + scaledBitmap.getPixels(pixels, 0, width, 0, 0, width, height); + + final ColorCutQuantizer quantizer = new ColorCutQuantizer(pixels, mMaxColors, + mFilters.isEmpty() ? null : mFilters.toArray(new Filter[mFilters.size()])); + + // If created a new bitmap, recycle it + if (scaledBitmap != mBitmap) { + scaledBitmap.recycle(); + } + swatches = quantizer.getQuantizedColors(); + + if (logger != null) { + logger.addSplit("Color quantization completed"); + } + } else { + // Else we're using the provided swatches + swatches = mSwatches; + } + + // If we haven't been provided with a generator, use the default + if (mGenerator == null) { + mGenerator = new DefaultGenerator(); + } + + // Now call let the Generator do it's thing + mGenerator.generate(swatches); + + if (logger != null) { + logger.addSplit("Generator.generate() completed"); + } + + // Now create a Palette instance + Palette p = new Palette(swatches, mGenerator); + + if (logger != null) { + logger.addSplit("Created Palette"); + logger.dumpToLog(); + } + + return p; + } + + /** + * Generate the {@link Palette} asynchronously. The provided listener's + * {@link PaletteAsyncListener#onGenerated} method will be called with the palette when + * generated. + */ + public AsyncTask generate(final PaletteAsyncListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener can not be null"); + } + + AsyncTask task = new AsyncTask() { + @Override + protected Palette doInBackground(Bitmap... params) { + return generate(); + } + + @Override + protected void onPostExecute(Palette colorExtractor) { + listener.onGenerated(colorExtractor); + } + }; + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap); + return task; + } + } + + static abstract class Generator { + + /** + * This method will be called with the {@link Palette.Swatch} that represent an image. + * You should process this list so that you have appropriate values when the other methods in + * class are called. + *

+ * This method will probably be called on a background thread. + */ + public abstract void generate(List swatches); + + /** + * Return the most vibrant {@link Palette.Swatch} + */ + public Palette.Swatch getVibrantSwatch() { + return null; + } + + /** + * Return a light and vibrant {@link Palette.Swatch} + */ + public Palette.Swatch getLightVibrantSwatch() { + return null; + } + + /** + * Return a dark and vibrant {@link Palette.Swatch} + */ + public Palette.Swatch getDarkVibrantSwatch() { + return null; + } + + /** + * Return a muted {@link Palette.Swatch} + */ + public Palette.Swatch getMutedSwatch() { + return null; + } + + /** + * Return a muted and light {@link Palette.Swatch} + */ + public Palette.Swatch getLightMutedSwatch() { + return null; + } + + /** + * Return a muted and dark {@link Palette.Swatch} + */ + public Palette.Swatch getDarkMutedSwatch() { + return null; + } + } + + /** + * A Filter provides a mechanism for exercising fine-grained control over which colors + * are valid within a resulting {@link Palette}. + */ + public interface Filter { + /** + * Hook to allow clients to be able filter colors from resulting palette. + * + * @param rgb the color in RGB888. + * @param hsl HSL representation of the color. + * + * @return true if the color is allowed, false if not. + * + * @see Builder#addFilter(Filter) + */ + boolean isAllowed(int rgb, float[] hsl); + } + + /** + * The default filter. + */ + private static final Filter DEFAULT_FILTER = new Filter() { + private static final float BLACK_MAX_LIGHTNESS = 0.05f; + private static final float WHITE_MIN_LIGHTNESS = 0.95f; + + @Override + public boolean isAllowed(int rgb, float[] hsl) { + return !isWhite(hsl) && !isBlack(hsl) && !isNearRedILine(hsl); + } + + /** + * @return true if the color represents a color which is close to black. + */ + private boolean isBlack(float[] hslColor) { + return hslColor[2] <= BLACK_MAX_LIGHTNESS; + } + + /** + * @return true if the color represents a color which is close to white. + */ + private boolean isWhite(float[] hslColor) { + return hslColor[2] >= WHITE_MIN_LIGHTNESS; + } + + /** + * @return true if the color lies close to the red side of the I line. + */ + private boolean isNearRedILine(float[] hslColor) { + return hslColor[0] >= 10f && hslColor[0] <= 37f && hslColor[1] <= 0.82f; + } + }; } diff --git a/core/java/com/android/internal/util/gesture/EdgeGesturePosition.java b/core/java/com/android/internal/util/gesture/EdgeGesturePosition.java deleted file mode 100644 index 01cfdeae54fbe..0000000000000 --- a/core/java/com/android/internal/util/gesture/EdgeGesturePosition.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.android.internal.util.gesture; - -/** - * Defines the positions in which gestures may be recognized by the - * edge gesture service. - * This defines an index and an flag for each position. - */ -public enum EdgeGesturePosition { - LEFT(0, 0), - BOTTOM(1, 1), - RIGHT(2, 1), - TOP(3, 0); - - EdgeGesturePosition(int index, int factor) { - INDEX = index; - FLAG = (0x01< - * Positions are specified by {@code EdgeGesturePosition.FLAG}. - */ - public static final int POSITION_MASK = 0x0000001f; - - /** - * Mask for coding sensitivity within the flags of - * {@code updateEdgeGestureActivationListener()}. - *

- * Sensitivity influences the speed of the swipe, the trigger area, and trigger distance that - * is needed to activate the edge gesture. - */ - public static final int SENSITIVITY_MASK = 0x70000000; - - /** - * Number of bits to shift left, to get a integer within the {@link #SENSITIVITY_MASK}. - */ - public static final int SENSITIVITY_SHIFT = 28; - - /** - * No sensitivity specified at all, the service may choose a sensitivity level on its own. - */ - public static final int SENSITIVITY_NONE = 0; - - /** - * Default sensitivity, picked by the edge gesture service automatically. - */ - public static final int SENSITIVITY_DEFAULT = 2; - - /** - * Lowest valid sensitivity value. - */ - public static final int SENSITIVITY_LOWEST = 1; - - /** - * Highest sensitivity value. - */ - public static final int SENSITIVITY_HIGHEST = 4; - - /** - * Do not cut 10% area on th edges - */ - public static final int UNRESTRICTED = 0x10; - - /** - * This listener does not likes enabling/disabling filter - * because it interrupt in motion events. - */ - public static final int LONG_LIVING = 0x20; - -} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index ae22b50287bb7..5dc91d2745212 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -63,6 +63,11 @@ public class LockPatternUtils { private static final String TAG = "LockPatternUtils"; private static final boolean DEBUG = false; + /** + * The key to identify when the lock pattern enabled flag is being acccessed for legacy reasons. + */ + public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled"; + /** * The number of incorrect attempts before which we fall back on an alternative * method of verifying the user, and resetting their lock pattern. @@ -258,7 +263,7 @@ public byte[] verifyPattern(List pattern, long challenge, throws RequestThrottledException { try { VerifyCredentialResponse response = - getLockSettings().verifyPattern(patternToString(pattern), challenge, userId); + getLockSettings().verifyPattern(patternToString(pattern, userId), challenge, userId); if (response == null) { // Shouldn't happen return null; @@ -286,7 +291,7 @@ public boolean checkPattern(List pattern, int userId) throws RequestThrottledException { try { VerifyCredentialResponse response = - getLockSettings().checkPattern(patternToString(pattern), userId); + getLockSettings().checkPattern(patternToString(pattern, userId), userId); if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { return true; @@ -296,7 +301,7 @@ public boolean checkPattern(List pattern, int userId) return false; } } catch (RemoteException re) { - return true; + return false; } } @@ -345,7 +350,7 @@ public boolean checkPassword(String password, int userId) throws RequestThrottle return false; } } catch (RemoteException re) { - return true; + return false; } } @@ -513,7 +518,7 @@ public void saveLockPattern(List pattern, String savedPatt + MIN_LOCK_PATTERN_SIZE + " dots long."); } - getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId); + getLockSettings().setLockPattern(patternToString(pattern, userId), savedPattern, userId); DevicePolicyManager dpm = getDevicePolicyManager(); // Update the device encryption password. @@ -522,7 +527,7 @@ public void saveLockPattern(List pattern, String savedPatt if (!shouldEncryptWithCredentials(true)) { clearEncryptionPassword(); } else { - String stringPattern = patternToString(pattern); + String stringPattern = patternToString(pattern, userId); updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern); } } @@ -873,8 +878,8 @@ public static List stringToPattern(String string, byte gri * @param pattern The pattern. * @return The pattern in string form. */ - public String patternToString(List pattern) { - return patternToString(pattern, getLockPatternSize()); + public String patternToString(List pattern, int userId) { + return patternToString(pattern, getLockPatternSize(userId)); } /** @@ -1011,6 +1016,19 @@ public boolean isLockPatternEnabled(int userId) { return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId); } + @Deprecated + public boolean isLegacyLockPatternEnabled(int userId) { + // Note: this value should default to {@code true} to avoid any reset that might result. + // We must use a special key to read this value, since it will by default return the value + // based on the new logic. + return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId); + } + + @Deprecated + public void setLegacyLockPatternEnabled(int userId) { + setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId); + } + private boolean isLockPatternEnabled(int mode, int userId) { return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING && savedPatternExists(userId); @@ -1082,8 +1100,8 @@ public boolean isTactileFeedbackEnabled() { /** * @return the pattern lockscreen size */ - public byte getLockPatternSize() { - long size = getLong(Settings.Secure.LOCK_PATTERN_SIZE, -1, UserHandle.USER_CURRENT); + public byte getLockPatternSize(int userId) { + long size = getLong(Settings.Secure.LOCK_PATTERN_SIZE, -1, userId); if (size > 0 && size < 128) { return (byte) size; } @@ -1093,24 +1111,24 @@ public byte getLockPatternSize() { /** * Set the pattern lockscreen size */ - public void setLockPatternSize(long size) { - setLong(Settings.Secure.LOCK_PATTERN_SIZE, size, UserHandle.USER_CURRENT); + public void setLockPatternSize(long size, int userId) { + setLong(Settings.Secure.LOCK_PATTERN_SIZE, size, userId); } - public void setVisibleDotsEnabled(boolean enabled) { - setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled, UserHandle.USER_CURRENT); + public void setVisibleDotsEnabled(boolean enabled, int userId) { + setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled, userId); } - public boolean isVisibleDotsEnabled() { - return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true, UserHandle.USER_CURRENT); + public boolean isVisibleDotsEnabled(int userId) { + return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true, userId); } - public void setShowErrorPath(boolean enabled) { - setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled, UserHandle.USER_CURRENT); + public void setShowErrorPath(boolean enabled, int userId) { + setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled, userId); } - public boolean isShowErrorPath() { - return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true, UserHandle.USER_CURRENT); + public boolean isShowErrorPath(int userId) { + return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true, userId); } /** diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index a3cd8ad3c63be..baa228f565384 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -1149,20 +1149,21 @@ protected void onDraw(Canvas canvas) { currentPath.rewind(); // draw the circles - for (int i = 0; i < mPatternSize; i++) { - float centerY = getCenterYForRow(i); - for (int j = 0; j < mPatternSize; j++) { - CellState cellState = mCellStates[i][j]; - float centerX = getCenterXForColumn(j); - float translationY = cellState.translationY; - if (isHardwareAccelerated() && cellState.hwAnimating) { - DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas; - displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY, - cellState.hwRadius, cellState.hwPaint); - } else { - drawCircle(canvas, (int) centerX, (int) centerY + translationY, - cellState.radius, drawLookup[i][j], cellState.alpha); - + if (mVisibleDots) { + for (int i = 0; i < mPatternSize; i++) { + float centerY = getCenterYForRow(i); + for (int j = 0; j < mPatternSize; j++) { + CellState cellState = mCellStates[i][j]; + float centerX = getCenterXForColumn(j); + float translationY = cellState.translationY; + if (isHardwareAccelerated() && cellState.hwAnimating) { + DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas; + displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY, + cellState.hwRadius, cellState.hwPaint); + } else { + drawCircle(canvas, (int) centerX, (int) centerY + translationY, + cellState.radius, drawLookup[i][j], cellState.alpha); + } } } } @@ -1170,8 +1171,6 @@ protected void onDraw(Canvas canvas) { // TODO: the path should be created and cached every time we hit-detect a cell // only the last segment of the path should be computed here // draw the path of the pattern (unless we are in stealth mode) - // draw the path of the pattern (unless the user is in progress, and - // we are in stealth mode) final boolean drawPath = ((!mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong) || (mPatternDisplayMode == DisplayMode.Wrong && mShowErrorPath)); if (drawPath) { @@ -1231,7 +1230,9 @@ private float calculateLastSegmentAlpha(float x, float y, float lastX, float las } private int getCurrentColor(boolean partOfPattern) { - if (!partOfPattern || mInStealthMode || mPatternInProgress) { + if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong) + || (mPatternDisplayMode == DisplayMode.Wrong && !mShowErrorPath) + || mPatternInProgress) { // unselected circle return mRegularColor; } else if (mPatternDisplayMode == DisplayMode.Wrong) { diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java index 35ed63b7eb1d2..d88f4797cc1ca 100644 --- a/core/java/com/android/internal/widget/SwipeDismissLayout.java +++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java @@ -89,14 +89,21 @@ public void onEnterAnimationComplete() { } }; private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { + private Runnable mRunnable = new Runnable() { + @Override + public void run() { + if (mDismissed) { + dismiss(); + } else { + cancel(); + } + resetMembers(); + } + }; + @Override public void onReceive(Context context, Intent intent) { - if (mDismissed) { - dismiss(); - } else { - cancel(); - } - resetMembers(); + post(mRunnable); } }; private IntentFilter mScreenOffFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF); diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java index 92d5aea18a525..6103ebc257efb 100644 --- a/core/java/com/android/server/BootReceiver.java +++ b/core/java/com/android/server/BootReceiver.java @@ -97,6 +97,7 @@ private void logBootEvents(Context ctx) throws IOException { final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); final SharedPreferences prefs = ctx.getSharedPreferences("log_files", Context.MODE_PRIVATE); final String headers = new StringBuilder(512) + .append("CM Version: ").append(SystemProperties.get("ro.cm.version")).append("\n") .append("Build: ").append(Build.FINGERPRINT).append("\n") .append("Hardware: ").append(Build.BOARD).append("\n") .append("Revision: ") diff --git a/core/jni/Android.mk b/core/jni/Android.mk index ad52bd6a76bce..42b10c4fe5c32 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -16,6 +16,10 @@ else LOCAL_CFLAGS += -DPACKED="" endif +ifeq ($(TARGET_ARCH), x86) + LOCAL_CFLAGS += -DPICK_SUPPORTED_ABI_WITH_MAX_LIBS +endif + ifneq ($(ENABLE_CPUSETS),) LOCAL_CFLAGS += -DENABLE_CPUSETS endif diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index a715c5f782527..9acdab488d2f5 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -1034,6 +1034,16 @@ void AndroidRuntime::start(const char* className, const Vector& options setenv("ANDROID_ROOT", rootDir, 1); } + const char* prebundledDir = getenv("PREBUNDLED_ROOT"); + if (prebundledDir == NULL) { + if (hasDir("/system/bundled-app")) { + prebundledDir = "/system/bundled-app"; + } else { + prebundledDir = "/vendor/bundled-app"; + } + setenv("PREBUNDLED_ROOT", prebundledDir, 1); + } + //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 6cbdeaa99509b..0e5c88cf7b663 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -150,12 +150,12 @@ Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc, mPixelRef->unref(); } -Bitmap::Bitmap(void* address, int fd, +Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) : mPixelStorageType(PixelStorageType::Ashmem) { mPixelStorage.ashmem.address = address; mPixelStorage.ashmem.fd = fd; - mPixelStorage.ashmem.size = ashmem_get_size_region(fd); + mPixelStorage.ashmem.size = mappedSize; mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable)); // Note: this will trigger a call to onStrongRefDestroyed(), but // we want the pixel ref to have a ref count of 0 at this point @@ -1006,6 +1006,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { // is disposed. int dupFd = dup(blob.fd()); if (dupFd < 0) { + ALOGE("Error allocating dup fd. Error:%d", errno); blob.release(); SkSafeUnref(ctable); doThrowRE(env, "Could not allocate dup blob fd."); @@ -1014,7 +1015,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { // Map the pixels in place and take ownership of the ashmem region. nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(), - ctable, dupFd, const_cast(blob.data()), !isMutable); + ctable, dupFd, const_cast(blob.data()), size, !isMutable); SkSafeUnref(ctable); if (!nativeBitmap) { close(dupFd); diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h index eadba5c0e6341..aaea178e73870 100644 --- a/core/jni/android/graphics/Bitmap.h +++ b/core/jni/android/graphics/Bitmap.h @@ -51,8 +51,8 @@ class Bitmap { const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); - Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes, - SkColorTable* ctable); + Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, + size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info() const; diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 93259e70abbdb..b669871d90e35 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -613,7 +613,7 @@ android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitm return nullptr; } - android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable); + android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable); wrapper->getSkBitmap(bitmap); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too @@ -623,7 +623,7 @@ android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitm } android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable, int fd, void* addr, bool readOnly) { + SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly) { const SkImageInfo& info = bitmap->info(); if (info.fColorType == kUnknown_SkColorType) { doThrowIAE(env, "unknown bitmap configuration"); @@ -633,7 +633,8 @@ android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, if (!addr) { // Map existing ashmem region if not already mapped. int flags = readOnly ? (PROT_READ) : (PROT_READ | PROT_WRITE); - addr = mmap(NULL, ashmem_get_size_region(fd), flags, MAP_SHARED, fd, 0); + size = ashmem_get_size_region(fd); + addr = mmap(NULL, size, flags, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { return nullptr; } @@ -643,7 +644,7 @@ android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, // attempting to compute our own. const size_t rowBytes = bitmap->rowBytes(); - android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable); + android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable); wrapper->getSkBitmap(bitmap); if (readOnly) { bitmap->pixelRef()->setImmutable(); diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index bcd834b0501ba..b1d66b710eb31 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -99,7 +99,7 @@ class GraphicsJNI { SkColorTable* ctable); static android::Bitmap* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable, int fd, void* addr, bool readOnly); + SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly); /** * Given a bitmap we natively allocate a memory block to store the contents diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp index bb8ef83c3f8cf..ef1e4abdf14bd 100644 --- a/core/jni/android_view_DisplayListCanvas.cpp +++ b/core/jni/android_view_DisplayListCanvas.cpp @@ -102,10 +102,16 @@ static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobje // ---------------------------------------------------------------------------- static jint android_view_DisplayListCanvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) { + if (!Caches::hasInstance()) { + android::uirenderer::renderthread::RenderProxy::staticFence(); + } return Caches::getInstance().maxTextureSize; } static jint android_view_DisplayListCanvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) { + if (!Caches::hasInstance()) { + android::uirenderer::renderthread::RenderProxy::staticFence(); + } return Caches::getInstance().maxTextureSize; } diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp index c830ffd5d08b3..91765f97544c5 100644 --- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp +++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp @@ -457,6 +457,10 @@ iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) { const int numAbis = env->GetArrayLength(supportedAbisArray); Vector supportedAbis; +#ifdef PICK_SUPPORTED_ABI_WITH_MAX_LIBS + int numLibs[numAbis+1] = {0}; // +1 to avoid 0 sized array + int maxLibs = 0; +#endif for (int i = 0; i < numAbis; ++i) { supportedAbis.add(new ScopedUtfChars(env, @@ -492,10 +496,20 @@ static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supported for (int i = 0; i < numAbis; i++) { const ScopedUtfChars* abi = supportedAbis[i]; if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) { - // The entry that comes in first (i.e. with a lower index) has the higher priority. - if (((i < status) && (status >= 0)) || (status < 0) ) { +#ifdef PICK_SUPPORTED_ABI_WITH_MAX_LIBS + numLibs[i]++; + if (numLibs[i] > maxLibs) { + maxLibs = numLibs[i]; status = i; + } else if (numLibs[i] == maxLibs) { +#endif + // The entry that comes in first (i.e. with a lower index) has the higher priority. + if (((i < status) && (status >= 0)) || (status < 0) ) { + status = i; + } +#ifdef PICK_SUPPORTED_ABI_WITH_MAX_LIBS } +#endif } } } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index aef70be4922ae..4f90bd9b196f0 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -16,6 +16,8 @@ #define LOG_TAG "Zygote" +#include + // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc #include #include @@ -53,6 +55,7 @@ #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" #include "ScopedUtfChars.h" +#include "fd_utils-inl.h" #include "nativebridge/native_bridge.h" @@ -78,6 +81,12 @@ static void RuntimeAbort(JNIEnv* env) { env->FatalError("RuntimeAbort"); } +static void RuntimeAbort(JNIEnv* env, int line, const char* msg) { + std::ostringstream oss; + oss << __FILE__ << ":" << line << ": " << msg; + env->FatalError(oss.str().c_str()); +} + // This signal handler is for zygote mode, since the zygote must reap its children static void SigChldHandler(int /*signal_number*/) { pid_t pid; @@ -439,6 +448,9 @@ static void SetForkLoad(bool boost) { } #endif +// The list of open zygote file descriptors. +static FileDescriptorTable* gOpenFdTable = NULL; + // Utility routine to fork zygote and specialize the child process. static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, @@ -453,6 +465,22 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetForkLoad(true); #endif + // Close any logging related FDs before we start evaluating the list of + // file descriptors. + __android_log_close(); + + // If this is the first fork for this zygote, create the open FD table. + // If it isn't, we just need to check whether the list of open files has + // changed (and it shouldn't in the normal case). + if (gOpenFdTable == NULL) { + gOpenFdTable = FileDescriptorTable::Create(); + if (gOpenFdTable == NULL) { + RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table."); + } + } else if (!gOpenFdTable->Restat()) { + RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table."); + } + pid_t pid = fork(); if (pid == 0) { @@ -462,6 +490,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra // Clean up any descriptors which must be closed immediately DetachDescriptors(env, fdsToClose); + // Re-open all remaining open file descriptors so that they aren't shared + // with the zygote across a fork. + if (!gOpenFdTable->ReopenOrDetach()) { + RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors."); + } + // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(env); @@ -611,10 +645,34 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( jint debug_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring se_name, jintArray fdsToClose, jstring instructionSet, jstring appDataDir) { - // Grant CAP_WAKE_ALARM to the Bluetooth process. jlong capabilities = 0; if (uid == AID_BLUETOOTH) { + // Grant CAP_WAKE_ALARM and CAP_BLOCK_SUSPEND to the Bluetooth process. capabilities |= (1LL << CAP_WAKE_ALARM); + capabilities |= (1LL << CAP_BLOCK_SUSPEND); + + // Add the Bluetooth process to the system group. + jsize length = env->GetArrayLength(reinterpret_cast(gids)); + jintArray gids_with_system = env->NewIntArray(length + 1); + if (!gids_with_system) { + ALOGE("could not allocate java array for gids"); + RuntimeAbort(env); + } + + jint *gids_elements = env->GetIntArrayElements(gids, NULL); + jint *gids_with_system_elements = env->GetIntArrayElements(gids_with_system, NULL); + + if (!gids_elements || !gids_with_system_elements) { + ALOGE("could not allocate arrays for gids"); + RuntimeAbort(env); + } + + gids_with_system_elements[0] = AID_SYSTEM; + memcpy(&gids_with_system_elements[1], &gids_elements[0], length * sizeof(jint)); + + env->ReleaseIntArrayElements(gids, gids_elements, JNI_ABORT); + env->ReleaseIntArrayElements(gids_with_system, gids_with_system_elements, 0); + gids = gids_with_system; } return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, diff --git a/core/jni/fd_utils-inl-extra.h b/core/jni/fd_utils-inl-extra.h new file mode 100644 index 0000000000000..993c320897e0a --- /dev/null +++ b/core/jni/fd_utils-inl-extra.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 The CyanogenMod 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 PATH_WHITELIST_EXTRA_H \ + "/proc/apid", \ + "/proc/aprf", +*/ + +// Overload this file in your device specific config if you need +// to add extra whitelisted paths. +// WARNING: Only use this if necessary. Custom inits should be +// checked for leaked file descriptors before even considering +// this. +// In order to add your files, copy the whole file (don't forget the copyright notice!), +// uncomment the #define above and change the paths inside to match your requirements \ No newline at end of file diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h new file mode 100644 index 0000000000000..f245a7fc52398 --- /dev/null +++ b/core/jni/fd_utils-inl.h @@ -0,0 +1,559 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "JNIHelp.h" +#include "ScopedPrimitiveArray.h" + +#include + +// Whitelist of open paths that the zygote is allowed to keep open. +// +// In addition to the paths listed here, all files ending with +// ".jar" under /system/framework" are whitelisted. See +// FileDescriptorInfo::IsWhitelisted for the canonical definition. +// +// If the whitelisted path is associated with a regular file or a +// character device, the file is reopened after a fork with the same +// offset and mode. If the whilelisted path is associated with a +// AF_UNIX socket, the socket will refer to /dev/null after each +// fork, and all operations on it will fail. +static const char* kPathWhitelist[] = { + "/dev/__properties__", /* Only on Android Lollipop and below. */ + "/dev/null", + "/dev/socket/zygote", + "/dev/socket/zygote_secondary", + "/system/etc/event-log-tags", + "/sys/kernel/debug/tracing/trace_marker", + "/system/framework/framework-res.apk", + "/dev/urandom", + "/dev/ion", + "@netlink@", + "/system/framework/org.cyanogenmod.platform-res.apk", + "/proc/ged", +#ifdef PATH_WHITELIST_EXTRA_H +PATH_WHITELIST_EXTRA_H +#endif +}; + +static const char* kFdPath = "/proc/self/fd"; + +// Keeps track of all relevant information (flags, offset etc.) of an +// open zygote file descriptor. +class FileDescriptorInfo { + public: + // Create a FileDescriptorInfo for a given file descriptor. Returns + // |NULL| if an error occurred. + static FileDescriptorInfo* createFromFd(int fd) { + struct stat f_stat; + // This should never happen; the zygote should always have the right set + // of permissions required to stat all its open files. + if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { + ALOGE("Unable to stat fd %d : %s", fd, strerror(errno)); + return NULL; + } + + if (S_ISSOCK(f_stat.st_mode)) { + std::string socket_name; + if (!GetSocketName(fd, &socket_name)) { + return NULL; + } + + if (!IsWhitelisted(socket_name)) { + ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); + return NULL; + } + + return new FileDescriptorInfo(fd); + } + + // We only handle whitelisted regular files and character devices. Whitelisted + // character devices must provide a guarantee of sensible behaviour when + // reopened. + // + // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). + // S_ISLINK : Not supported. + // S_ISBLK : Not supported. + // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate + // with the child process across forks but those should have been closed + // before we got to this point. + if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { + ALOGE("Unsupported st_mode %d", f_stat.st_mode); + return NULL; + } + + std::string file_path; + if (!Readlink(fd, &file_path)) { + return NULL; + } + + if (!IsWhitelisted(file_path)) { + ALOGE("Not whitelisted : %s", file_path.c_str()); + return NULL; + } + + // File descriptor flags : currently on FD_CLOEXEC. We can set these + // using F_SETFD - we're single threaded at this point of execution so + // there won't be any races. + const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); + if (fd_flags == -1) { + ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno)); + return NULL; + } + + // File status flags : + // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through + // to the open() call. + // + // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can + // do about these, since the file has already been created. We shall ignore + // them here. + // + // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL + // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. + // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for + // their presence and pass them in to open(). + int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); + if (fs_flags == -1) { + ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno)); + return NULL; + } + + // File offset : Ignore the offset for non seekable files. + const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); + + // We pass the flags that open accepts to open, and use F_SETFL for + // the rest of them. + static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); + int open_flags = fs_flags & (kOpenFlags); + fs_flags = fs_flags & (~(kOpenFlags)); + + return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset); + } + + // Checks whether the file descriptor associated with this object + // refers to the same description. + bool Restat() const { + struct stat f_stat; + if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { + return false; + } + + return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; + } + + bool ReopenOrDetach() const { + if (is_sock) { + return DetachSocket(); + } + + // NOTE: This might happen if the file was unlinked after being opened. + // It's a common pattern in the case of temporary files and the like but + // we should not allow such usage from the zygote. + const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); + + if (new_fd == -1) { + ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno)); + return false; + } + + if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { + close(new_fd); + ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno)); + return false; + } + + if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { + close(new_fd); + ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno)); + return false; + } + + if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { + close(new_fd); + ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno)); + return false; + } + + if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { + close(new_fd); + ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno)); + return false; + } + + close(new_fd); + + return true; + } + + const int fd; + const struct stat stat; + const std::string file_path; + const int open_flags; + const int fd_flags; + const int fs_flags; + const off_t offset; + const bool is_sock; + + private: + FileDescriptorInfo(int fd) : + fd(fd), + stat(), + open_flags(0), + fd_flags(0), + fs_flags(0), + offset(0), + is_sock(true) { + } + + FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, + int fd_flags, int fs_flags, off_t offset) : + fd(fd), + stat(stat), + file_path(file_path), + open_flags(open_flags), + fd_flags(fd_flags), + fs_flags(fs_flags), + offset(offset), + is_sock(false) { + } + + // Returns true iff. a given path is whitelisted. A path is whitelisted + // if it belongs to the whitelist (see kPathWhitelist) or if it's a path + // under /system/framework that ends with ".jar". + static bool IsWhitelisted(const std::string& path) { + for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) { + if (kPathWhitelist[i] == path) { + return true; + } + } + + static const std::string kFrameworksPrefix = "/system/framework/"; + static const std::string kJarSuffix = ".jar"; + if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 && + path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) { + return true; + } + return false; + } + + // TODO: Call android::base::Readlink instead of copying the code here. + static bool Readlink(const int fd, std::string* result) { + char path[64]; + snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + + // Code copied from android::base::Readlink starts here : + + // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer, + // and truncates to whatever size you do supply, so it can't be used to query. + // We could call lstat first, but that would introduce a race condition that + // we couldn't detect. + // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here. + char buf[4096]; + ssize_t len = readlink(path, buf, sizeof(buf)); + if (len == -1) return false; + + result->assign(buf, len); + return true; + } + + // Returns the locally-bound name of the socket |fd|. Returns true + // iff. all of the following hold : + // + // - the socket's sa_family is AF_UNIX. + // - the length of the path is greater than zero (i.e, not an unnamed socket). + // - the first byte of the path isn't zero (i.e, not a socket with an abstract + // address). + static bool GetSocketName(const int fd, std::string* result) { + sockaddr_storage ss; + sockaddr* addr = reinterpret_cast(&ss); + socklen_t addr_len = sizeof(ss); + + if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) { + ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno)); + return false; + } + + + if (addr->sa_family == AF_NETLINK) { + (*result) = "@netlink@"; + return true; + } + + if (addr->sa_family != AF_UNIX) { + ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family); + return false; + } + + const sockaddr_un* unix_addr = reinterpret_cast(&ss); + + size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path); + // This is an unnamed local socket, we do not accept it. + if (path_len == 0) { + ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd); + return false; + } + + // This is a local socket with an abstract address, we do not accept it. + if (unix_addr->sun_path[0] == '\0') { + ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd); + return false; + } + + // If we're here, sun_path must refer to a null terminated filesystem + // pathname (man 7 unix). Remove the terminator before assigning it to an + // std::string. + if (unix_addr->sun_path[path_len - 1] == '\0') { + --path_len; + } + + result->assign(unix_addr->sun_path, path_len); + return true; + } + + bool DetachSocket() const { + const int dev_null_fd = open("/dev/null", O_RDWR); + if (dev_null_fd < 0) { + ALOGE("Failed to open /dev/null : %s", strerror(errno)); + return false; + } + + if (dup2(dev_null_fd, fd) == -1) { + ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno)); + return false; + } + + if (close(dev_null_fd) == -1) { + ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno)); + return false; + } + + return true; + } + + + // DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); + FileDescriptorInfo(const FileDescriptorInfo&); + void operator=(const FileDescriptorInfo&); +}; + +// A FileDescriptorTable is a collection of FileDescriptorInfo objects +// keyed by their FDs. +class FileDescriptorTable { + public: + // Creates a new FileDescriptorTable. This function scans + // /proc/self/fd for the list of open file descriptors and collects + // information about them. Returns NULL if an error occurs. + static FileDescriptorTable* Create() { + DIR* d = opendir(kFdPath); + if (d == NULL) { + ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); + return NULL; + } + int dir_fd = dirfd(d); + dirent* e; + + std::unordered_map open_fd_map; + while ((e = readdir(d)) != NULL) { + const int fd = ParseFd(e, dir_fd); + if (fd == -1) { + continue; + } + + FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); + if (info == NULL) { + if (closedir(d) == -1) { + ALOGE("Unable to close directory : %s", strerror(errno)); + } + return NULL; + } + open_fd_map[fd] = info; + } + + if (closedir(d) == -1) { + ALOGE("Unable to close directory : %s", strerror(errno)); + return NULL; + } + return new FileDescriptorTable(open_fd_map); + } + + bool Restat() { + std::set open_fds; + + // First get the list of open descriptors. + DIR* d = opendir(kFdPath); + if (d == NULL) { + ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); + return false; + } + + int dir_fd = dirfd(d); + dirent* e; + while ((e = readdir(d)) != NULL) { + const int fd = ParseFd(e, dir_fd); + if (fd == -1) { + continue; + } + + open_fds.insert(fd); + } + + if (closedir(d) == -1) { + ALOGE("Unable to close directory : %s", strerror(errno)); + return false; + } + + return RestatInternal(open_fds); + } + + // Reopens all file descriptors that are contained in the table. Returns true + // if all descriptors were successfully re-opened or detached, and false if an + // error occurred. + bool ReopenOrDetach() { + std::unordered_map::const_iterator it; + for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { + const FileDescriptorInfo* info = it->second; + if (info == NULL || !info->ReopenOrDetach()) { + return false; + } + } + + return true; + } + + private: + FileDescriptorTable(const std::unordered_map& map) + : open_fd_map_(map) { + } + + bool RestatInternal(std::set& open_fds) { + bool error = false; + + // Iterate through the list of file descriptors we've already recorded + // and check whether : + // + // (a) they continue to be open. + // (b) they refer to the same file. + std::unordered_map::iterator it = open_fd_map_.begin(); + while (it != open_fd_map_.end()) { + std::set::const_iterator element = open_fds.find(it->first); + if (element == open_fds.end()) { + // The entry from the file descriptor table is no longer in the list + // of open files. We warn about this condition and remove it from + // the list of FDs under consideration. + // + // TODO(narayan): This will be an error in a future android release. + // error = true; + // ALOGW("Zygote closed file descriptor %d.", it->first); + it = open_fd_map_.erase(it); + } else { + // The entry from the file descriptor table is still open. Restat + // it and check whether it refers to the same file. + const bool same_file = it->second->Restat(); + if (!same_file) { + // The file descriptor refers to a different description. We must + // update our entry in the table. + delete it->second; + it->second = FileDescriptorInfo::createFromFd(*element); + if (it->second == NULL) { + // The descriptor no longer no longer refers to a whitelisted file. + // We flag an error and remove it from the list of files we're + // tracking. + error = true; + it = open_fd_map_.erase(it); + } else { + // Successfully restatted the file, move on to the next open FD. + ++it; + } + } else { + // It's the same file. Nothing to do here. Move on to the next open + // FD. + ++it; + } + + // Finally, remove the FD from the set of open_fds. We do this last because + // |element| will not remain valid after a call to erase. + open_fds.erase(*element); + } + } + + if (open_fds.size() > 0) { + // The zygote has opened new file descriptors since our last inspection. + // We warn about this condition and add them to our table. + // + // TODO(narayan): This will be an error in a future android release. + // error = true; + // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size()); + + // TODO(narayan): This code will be removed in a future android release. + std::set::const_iterator it; + for (it = open_fds.begin(); it != open_fds.end(); ++it) { + const int fd = (*it); + FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); + if (info == NULL) { + // A newly opened file is not on the whitelist. Flag an error and + // continue. + error = true; + } else { + // Track the newly opened file. + open_fd_map_[fd] = info; + } + } + } + + return !error; + } + + static int ParseFd(dirent* e, int dir_fd) { + char* end; + const int fd = strtol(e->d_name, &end, 10); + if ((*end) != '\0') { + return -1; + } + + // Don't bother with the standard input/output/error, they're handled + // specially post-fork anyway. + if (fd <= STDERR_FILENO || fd == dir_fd) { + return -1; + } + + return fd; + } + + // Invariant: All values in this unordered_map are non-NULL. + std::unordered_map open_fd_map_; + + // DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable); + FileDescriptorTable(const FileDescriptorTable&); + void operator=(const FileDescriptorTable&); +}; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 881b283c32380..84c3a9c17cd2b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -66,6 +66,7 @@ + @@ -323,8 +324,14 @@ - - + + + + + + @@ -870,6 +877,11 @@ + + + @@ -1230,10 +1242,10 @@ - - @@ -1271,7 +1283,8 @@ + android:protectionLevel="signature|privileged" + androidprv:allowViaWhitelist="true" /> + + + android:protectionLevel="signature|privileged" + androidprv:allowViaWhitelist="true" /> @@ -2375,6 +2397,15 @@ + + + @@ -2568,7 +2599,8 @@ + android:protectionLevel="signature" + androidprv:allowViaWhitelist="true" /> - - - - - - - - - @@ -2859,14 +2867,14 @@ @@ -2874,19 +2882,19 @@ @@ -2906,7 +2914,7 @@ diff --git a/core/res/res/drawable/ic_lock_profile.xml b/core/res/res/color/preference_category_text_color.xml similarity index 80% rename from core/res/res/drawable/ic_lock_profile.xml rename to core/res/res/color/preference_category_text_color.xml index 393138bc7d411..7916a5ccb2578 100644 --- a/core/res/res/drawable/ic_lock_profile.xml +++ b/core/res/res/color/preference_category_text_color.xml @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + + + + diff --git a/core/res/res/drawable-hdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-hdpi/ic_lock_profile_alpha.png deleted file mode 100644 index 7fc4cec23467d..0000000000000 Binary files a/core/res/res/drawable-hdpi/ic_lock_profile_alpha.png and /dev/null differ diff --git a/core/res/res/drawable-mdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-mdpi/ic_lock_profile_alpha.png deleted file mode 100644 index d47ba1631cf10..0000000000000 Binary files a/core/res/res/drawable-mdpi/ic_lock_profile_alpha.png and /dev/null differ diff --git a/core/res/res/drawable-xhdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_profile_alpha.png deleted file mode 100644 index 4c9472c24d2dd..0000000000000 Binary files a/core/res/res/drawable-xhdpi/ic_lock_profile_alpha.png and /dev/null differ diff --git a/core/res/res/drawable-xxhdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_profile_alpha.png deleted file mode 100644 index e23c484a8fc7f..0000000000000 Binary files a/core/res/res/drawable-xxhdpi/ic_lock_profile_alpha.png and /dev/null differ diff --git a/core/res/res/drawable/ic_lock_dnd_priority.xml b/core/res/res/drawable/ic_lock_dnd_priority.xml new file mode 100644 index 0000000000000..0d455522be205 --- /dev/null +++ b/core/res/res/drawable/ic_lock_dnd_priority.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/core/res/res/drawable/ic_lock_dnd_total_silence.xml b/core/res/res/drawable/ic_lock_dnd_total_silence.xml new file mode 100644 index 0000000000000..0128dfe7e0d25 --- /dev/null +++ b/core/res/res/drawable/ic_lock_dnd_total_silence.xml @@ -0,0 +1,31 @@ + + + + + + + + \ No newline at end of file diff --git a/core/res/res/drawable/ic_lock_ring.xml b/core/res/res/drawable/ic_lock_ring.xml new file mode 100644 index 0000000000000..92b4b2e53d902 --- /dev/null +++ b/core/res/res/drawable/ic_lock_ring.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/core/res/res/drawable/ic_lock_vibrate.xml b/core/res/res/drawable/ic_lock_vibrate.xml new file mode 100644 index 0000000000000..f38ebc29774b7 --- /dev/null +++ b/core/res/res/drawable/ic_lock_vibrate.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/core/res/res/drawable/ic_power_dnd_priority.xml b/core/res/res/drawable/ic_power_dnd_priority.xml new file mode 100644 index 0000000000000..87a12165fcbd2 --- /dev/null +++ b/core/res/res/drawable/ic_power_dnd_priority.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/core/res/res/drawable/ic_power_dnd_total_silence.xml b/core/res/res/drawable/ic_power_dnd_total_silence.xml new file mode 100644 index 0000000000000..bd4e2ed8477ce --- /dev/null +++ b/core/res/res/drawable/ic_power_dnd_total_silence.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/core/res/res/drawable/ic_power_ring.xml b/core/res/res/drawable/ic_power_ring.xml new file mode 100644 index 0000000000000..3f3b856a5b97b --- /dev/null +++ b/core/res/res/drawable/ic_power_ring.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/core/res/res/drawable/ic_power_vibrate.xml b/core/res/res/drawable/ic_power_vibrate.xml new file mode 100644 index 0000000000000..068286b0b8c0d --- /dev/null +++ b/core/res/res/drawable/ic_power_vibrate.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/core/res/res/drawable/stat_notify_protected.xml b/core/res/res/drawable/stat_notify_protected.xml new file mode 100644 index 0000000000000..d67a348cf5ec8 --- /dev/null +++ b/core/res/res/drawable/stat_notify_protected.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml index bf46af8f4f37c..abd9b643e3540 100644 --- a/core/res/res/layout-xlarge/activity_list.xml +++ b/core/res/res/layout-xlarge/activity_list.xml @@ -58,7 +58,7 @@ + android:background="@color/activity_list_divider_color" /> diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml index 34cb21d4f7f5f..44a11d9d5b8c6 100644 --- a/core/res/res/layout/alert_dialog_holo.xml +++ b/core/res/res/layout/alert_dialog_holo.xml @@ -34,7 +34,7 @@ android:layout_width="match_parent" android:layout_height="2dip" android:visibility="gone" - android:background="@android:color/holo_blue_light" /> + android:background="@color/dialog_divider_color" /> + android:background="@color/dialog_divider_color" /> diff --git a/core/res/res/layout/app_permission_item_money.xml b/core/res/res/layout/app_permission_item_money.xml index 2056285661708..f66be6e2188d1 100644 --- a/core/res/res/layout/app_permission_item_money.xml +++ b/core/res/res/layout/app_permission_item_money.xml @@ -64,7 +64,7 @@ android:id="@+id/perm_money_label" android:textAppearance="?android:attr/textAppearanceSmall" android:textSize="16sp" - android:textColor="@color/perms_costs_money" + android:textColor="@color/perms_costs_money_text_color" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toEndOf="@id/perm_money_icon" diff --git a/core/res/res/layout/character_picker_button.xml b/core/res/res/layout/character_picker_button.xml index b74e620c8bcf0..0213dc15a78a5 100644 --- a/core/res/res/layout/character_picker_button.xml +++ b/core/res/res/layout/character_picker_button.xml @@ -21,6 +21,6 @@ android:focusable="false" android:textAppearance="?android:attr/textAppearanceLarge" android:background="@drawable/btn_keyboard_key_trans" - android:textColor="#FFFFFFFF" + android:textColor="@color/character_picker_button_text_color" /> diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml index f8a2bf7509cdf..856e20b966906 100644 --- a/core/res/res/layout/dialog_custom_title_holo.xml +++ b/core/res/res/layout/dialog_custom_title_holo.xml @@ -31,7 +31,7 @@ This is a custom layout for a dialog. + android:background="@color/dialog_divider_color" /> + android:background="@color/dialog_divider_color" /> + android:background="@color/dialog_divider_color" /> diff --git a/core/res/res/layout/notification_material_action_tombstone.xml b/core/res/res/layout/notification_material_action_tombstone.xml index 976448b08bb3e..7e53c46c70b8f 100644 --- a/core/res/res/layout/notification_material_action_tombstone.xml +++ b/core/res/res/layout/notification_material_action_tombstone.xml @@ -24,7 +24,7 @@ android:gravity="start|center_vertical" android:drawablePadding="8dp" android:paddingStart="8dp" - android:textColor="#555555" + android:textColor="@color/notification_action_tombstone_text_color" android:textSize="@dimen/notification_text_size" android:singleLine="true" android:ellipsize="end" diff --git a/core/res/res/layout/permission_confirmation_dialog.xml b/core/res/res/layout/permission_confirmation_dialog.xml index ab5b9fa3a5c86..1727286faaa6a 100644 --- a/core/res/res/layout/permission_confirmation_dialog.xml +++ b/core/res/res/layout/permission_confirmation_dialog.xml @@ -42,6 +42,7 @@ android:shrinkColumns="1" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="center_vertical" android:paddingLeft="16dip" android:paddingRight="16dip"> @@ -50,17 +51,14 @@ android:layout_height="wrap_content" > diff --git a/core/res/res/layout/preference_category_material.xml b/core/res/res/layout/preference_category_material.xml index 456b25280ee4d..08f051fde7da0 100644 --- a/core/res/res/layout/preference_category_material.xml +++ b/core/res/res/layout/preference_category_material.xml @@ -21,7 +21,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="16dip" android:textAppearance="@style/TextAppearance.Material.Body2" - android:textColor="?android:attr/colorAccent" + android:textColor="@color/preference_category_text_color" android:paddingStart="?attr/listPreferredItemPaddingStart" android:paddingEnd="?attr/listPreferredItemPaddingEnd" android:paddingTop="16dip" /> diff --git a/core/res/res/layout/remote_views_adapter_default_loading_view.xml b/core/res/res/layout/remote_views_adapter_default_loading_view.xml index 864e435dfda60..83ad17724d7b5 100644 --- a/core/res/res/layout/remote_views_adapter_default_loading_view.xml +++ b/core/res/res/layout/remote_views_adapter_default_loading_view.xml @@ -23,9 +23,9 @@ android:gravity="center_horizontal|center_vertical" android:text="@string/loading" - android:textColor="#60FFFFFF" + android:textColor="@color/loading_view_text_color" android:textSize="18sp" - android:shadowColor="#FF000000" + android:shadowColor="@color/loading_view_text_shadow_color" android:shadowDx="0.0" android:shadowDy="1.0" android:shadowRadius="1.0" /> diff --git a/core/res/res/layout/status_bar_latest_event_content.xml b/core/res/res/layout/status_bar_latest_event_content.xml index 9444164d9be88..0959ecc35e527 100644 --- a/core/res/res/layout/status_bar_latest_event_content.xml +++ b/core/res/res/layout/status_bar_latest_event_content.xml @@ -20,7 +20,7 @@ android:id="@+id/status_bar_latest_event_content" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="#FFFF00FF" + android:background="@color/status_bar_latest_event_content_bg_color" > diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml index 3b8dbf2dfb3f2..c032c34f5e52c 100644 --- a/core/res/res/layout/text_edit_paste_window.xml +++ b/core/res/res/layout/text_edit_paste_window.xml @@ -28,7 +28,7 @@ android:drawablePadding="8dip" android:gravity="center" android:textAppearance="?android:attr/textAppearanceMediumInverse" - android:textColor="@android:color/black" + android:textColor="@color/edit_paste_window_text_color" android:background="@android:drawable/text_edit_paste_window" android:text="@android:string/paste" android:layout_marginBottom="12dip" diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml index c947a1982348c..c1548139ca204 100644 --- a/core/res/res/layout/text_edit_side_paste_window.xml +++ b/core/res/res/layout/text_edit_side_paste_window.xml @@ -28,7 +28,7 @@ android:drawablePadding="8dip" android:gravity="center" android:textAppearance="?android:attr/textAppearanceMediumInverse" - android:textColor="@android:color/black" + android:textColor="@color/edit_side_paste_window_text_color" android:background="@android:drawable/text_edit_side_paste_window" android:text="@android:string/paste" android:layout_marginBottom="12dip" diff --git a/core/res/res/layout/typing_filter.xml b/core/res/res/layout/typing_filter.xml index d8d0a400b4dd0..74a016a35e934 100644 --- a/core/res/res/layout/typing_filter.xml +++ b/core/res/res/layout/typing_filter.xml @@ -16,8 +16,8 @@ "Program %1$d van %2$d." + "Sensors" diff --git a/core/res/res/values-af/cm_strings.xml b/core/res/res/values-af/cm_strings.xml new file mode 100644 index 0000000000000..993e77590ada3 --- /dev/null +++ b/core/res/res/values-af/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Skermfoto + + ontvang beskermde SMS + + Laat die program toe om \'n beskermde inkomende SMS te ontvang. + + verander beskermde SMS lys + + Laat die program toe om die beskermde SMS adres lys te verander. + + Sekuriteit + + Regte met betrekking tot toestel sekuriteitsinligting. + + lees foon swartlys + + Laat \'n program toe om inligting oor telefoonnommers wat geblokkeer is van inkomende oproepe of boodskappe te lees. + + Verander selfoon swartlys + + Laat \'n program toe om van die telefoonnommers wat geblokkeer is vir inkomende oproepe of boodskappe te verander. + + Stel slotskerm agtergrond in + + Laat \'n program toe om die slotskerm agtergrond te verander. + + Herlaai + + Huidige + + + Herlaai + + Recovery + + Bootloader + + Download + + Vinnige herlaai + + Herlaai + + Jou tablet gaan herlaai. + Jou foon gaan herlaai. + + Herlaai\u2026 + + Program beëindig + + ADB oor netwerk is aktief + + ADB oor USB & netwerk is aktief + + Raak om ontfouting af te skakel. + + ADB - %1$s + USB & netwerk + USB + Netwerk + + onderskep program begin + + %s is nie geïnstalleer nie + + Prioriteit + Geen + + Deaktiveer Wi-Fi warmkol weens SIM inskrywing verandering + + Skakel Wi-Fi af + + aktiveer of deaktiveer Privaatheidswag + Laat \'n program toe om te bepaal of \'n ander program met of sonder Privaatheidswag kan loop. Wanneer Privaatheidswag geaktiveer is kan die program nie toegang kry tot persoonlike data soos kontakte, boodskappe en oproep geskiedenis nie. + Privaatheidswag aktief + %1$s het nie toegang tot persoonlike data nie + Privaatheidswag + %1$s wil %2$s. + + Onthou my keuse + + toegang tot die kamera + toegang tot jou ligging + lees jou kennisgewing boodskappe + Aktiveer \'n VPN + begin by aanskakeling + verwyder jou oproep rekord data + verwyder jou kontakte + verwyder jou MMS boodskappe + verwyder jou SMS boodskappe + teken bo + kry program gebruik stats + hou jou toestel geaktiveerd + maak \'n oproep + opdateer jou kalender + opdateer die oproep lys + verander die knipbord + opdateer jou kontakte + opdateer stelsel instellings + demp / ontdemp die mikrofoon + speel oudio + plaas \'n kennisgewing + projek media + lees jou kalender + lees jou oproep lys + lees die knipbord + lees jou kantakte + lees jou MMS boodskappe + lees jou SMS boodskappe + ontvang \'n SMS boodskap + klank opneem + stuur \'n MMS boodskap + stuur \'n SMS boodskap + begin by aanskakeling + vertoon uitspring boodskappe + wissel Bluetooth + skakel sellulêre data aan/af + wissel NFC + wissel Wi-Fi + beheer alarmstelsel volume + beheer klank fokus + beheer Bluetooth volume + beheer meester volume + gebruik die media knoppies + beheer media volume + beheer kennisgewing volume + beheer luitoon volume + gebruik haptiese terugvoer + beheer stem oproep volume + skryf \'n MMS boodskap + Skryf \'n SMS boodskap + gebruik vingerfdruk + voeg \'n stem boodskap by + kry toegang na foon toestand + skandeer Wi-Fi netwerke + verander die agtergrond + gebruik assistent struktuur + neem \'n skermfoto + gebruik liggaam sensors + lees sel uitsendings + simuleer jou plek + lees eksterne spasie + skryf eksterne spasie + skakel skerm aan + kry toestel rekeninge + verander Wi-Fi status + kry root toegang + + Om die skerm te ontspeld, raak en hou die Terug knoppie. + + Geen gekoppelde toestel + %1$s gekoppelde toestel + %1$s gekoppelde toestelle + + + + Aktiwiteit begin geblokkeer + %1$s is beskerm om uitgevoer te word. Raak om toestemming te gee en die toepassing te begin. + + Battery vol gelaai + Diskonnekteer jou toestel van die laaier om die battery lewe te verleng. + + herstel battery statistieke + + Laat \'n program om die huidige lae-vlak battery gebruik data te herstel. + + SIM kaarte het verander + Raak om SIM kaart standaard opsies te stel + diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index b7651db12a999..fff69e287232b 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -254,7 +254,7 @@ "Sluit persoonlike data soos kredietkaartnommers en wagwoorde in." "deaktiveer of verander statusbalk" "Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder." - "statusbalk" + "wees die statusbalk" "Laat die program toe om die statusbalk te wees." "vou statusbalk in of uit" "Laat die program toe om die statusbalk uit te vou of in te vou." @@ -282,7 +282,7 @@ "Laat die program toe om WAP-boodskappe te ontvang en te verwerk. Hierdie toestemming sluit ook in dat boodskappe wat na jou toestel gestuur is, gemonitor of uitgevee kan word, sonder dat jy dit gesien het." "haal lopende programme op" "Laat die program toe om inligting oor die huidig- en onlangslopende take op te haal. Dit kan moontlik die program toelaat om inligting oor watter programme op die toestel gebruik word, te ontdek." - "Bestuur profiel- en toesteleienaars" + "bestuur profiel- en toesteleienaars" "Laat programme toe om die profieleienaars en die toesteleienaar te stel." "herrangskik lopende programme" "Laat die program toe om take na die voorgrond of agtergrond te skuif. Die program kan dit moontlik sonder jou insette doen." @@ -324,7 +324,7 @@ "Laat die program toe om jou tablet se oproeprekord, insluitende data oor inkomende en uitgaande oproepe, te verander. Kwaadwillige programme kan dit gebruik om jou oproeprekord uit te vee of te verander." "Laat die program toe om jou TV se oproeprekord te wysig, insluitend data oor inkomende en uitgaande oproepe. Kwaadwillige programme kan dit gebruik om jou oproeprekord uit te vee of te wysig." "Laat die program toe om jou foon se oproeprekord, insluitende data oor inkomende en uitgaande oproepe, te verander. Kwaadwillige programme kan dit gebruik om jou oproeprekord uit te vee of te verander." - "liggaamsensors (soos hartklopmonitors)" + "verkry toegang tot liggaamsensors (soos hartklopmonitors)" "Laat die program toe om toegang te verkry tot data van sensors af wat jou fisieke toestand, soos jou polsslag, monitor." "lees kalenderafsprake plus vertroulike inligting" "Laat die program toe om alle kalendergebeure wat op jou tablet gestoor is, insluitend dié van vriende en medewerkers, te lees. Dit kan moontlik die program toelaat om jou kalenderdata te deel of te stoor, ongeag van vertroulikheid of sensitiwiteit." @@ -336,15 +336,15 @@ "Laat die program toe om gebeure wat op jou foon aangepas kan word, by te voeg, te verwyder of te verander, insluitend dié van vriende en medewerkers. Dit kan moontlik die program toelaat om boodskappe wat lyk of dit van kalendereienaars af kom, te stuur, of om gebeure sonder die eienaar se kennis aan te pas." "Kry toegang tot ekstra liggingverskaffer-bevele" "Gee die program toegang tot ekstra liggingverskaffer-bevele. Dit kan die program dalk toelaat om in te meng met die werking van die GPS of ander liggingbronne." - "presiese ligging (GPS en netwerkgebaseer)" + "verkry toegang tot presiese ligging (GPS- en netwerkgegrond)" "Laat die program toe om jou presiese ligging te kry met behulp van die globaleposisioneringstelsel (GPS) of netwerkliggingbronne soos seltorings en Wi-Fi. Hierdie liggingdienste moet aangeskakel en beskikbaar wees aan jou toestel vir die program om dit te gebruik. Programme kan dit gebruik om te bepaal waar jy is en kan batterylewe opgebruik." - "benaderde ligging (netwerkgebaseer)" + "verkry toegang tot benaderde ligging (netwerkgegrond)" "Laat die program toe om jou benaderde ligging te kry. Hierdie ligging word verkry deur liggingdienste met gebruik van netwerkliggingbronne soos seltorings en Wi-Fi. Hierdie liggingdienste moet aangeskakel en beskikbaar wees aan jou toestel vir die program om dit te gebruik. Programme kan dit gebruik om te bepaal waar omtrent jy is." "verander jou klankinstellings" "Laat die program toe om globale klankinstellings soos volume en watter luidspreker vir uitvoer gebruik word, te verander." "neem klank op" "Laat die program toe om klank met die mikrofoon op te neem. Hierdie toestemming laat die program toe om klank te eniger tyd, sonder jou bevestiging, op te neem." - "sim-kommunikasie" + "stuur bevele na die SIM" "Laat die program toe om bevele na die SIM te stuur. Dit is baie gevaarlik." "neem foto\'s en video\'s" "Laat die program toe om foto\'s en video\'s met die kamera te neem. Hierdie toestemming laat die program toe om die kamera te eniger tyd sonder jou bevestiging te gebruik." @@ -382,7 +382,7 @@ "Laat die program toe om die lys van rekeninge wat aan die foon bekend is, te kry. Dit kan moontlik enige rekeninge wat geskep is deur programme wat jy geïnstalleer het, insluit." "bekyk netwerkverbindings" "Laat die program toe om inligting oor netwerkverbindings, soos watter netwerke bestaan en gekoppel is, te sien." - "volle netwerktoegang" + "verkry volle netwerktoegang" "Laat die program toe om netwerksokke te skep en gepasmaakte netwerkprotokolle te gebruik. Die blaaier en ander programme verskaf reeds die middele waardeur data na die internet gestuur kan word, so hierdie toestemming word nie vereis om data na die internet te stuur nie." "verander netwerkverbinding" "Laat die program toe om die status van netwerkkonnektiwiteit te verander." @@ -402,7 +402,7 @@ "Laat die program toe om die plaaslike Bluetooth-foon op te stel en te ontdek en met afgeleë toestelle saam te bind." "koppel aan en ontkoppel van WiMAX" "Laat die program toe om te bepaal of WiMAX geaktiveer is en of enige WiMAX-netwerke gekoppel is." - "Verander WiMAX-status" + "verander WiMAX-status" "Laat die program toe om die tablet aan WiMAX-netwerke te koppel en daarvan te ontkoppel." "Laat die program toe om die TV te koppel aan en die TV van WiMAX-netwerke af te ontkoppel." "Laat die program toe om die foon aan WiMAX-netwerke te koppel en daarvan te ontkoppel." @@ -485,7 +485,7 @@ "Laat die program toe om die kalibrasieparameters van die raakskerm te wysig. Dit behoort nooit vir normale programme nodig te wees nie." "gaan in by DRM-sertifikate" "Laat \'n program toe om DRM-sertifikate op te stel en te gebruik. Behoort nooit vir normale programme nodig te wees nie." - "Ontvang Android Straal-oordragstatus" + "ontvang Android Straal-oordragstatus" "Laat hierdie program toe om inligting oor huidige Android Straal-oordragte te ontvang." "verwyder DRM-sertifikate" "Laat \'n program toe om DRM-sertifikate te verwyder. Behoort nooit vir gewone programme nodig te wees nie." @@ -1091,11 +1091,11 @@ "Formateer tans …" "Nie ingevoeg nie" "Geen passende aktiwiteite gevind nie." - "Roeteer media-uitvoer" + "roeteer media-uitvoer" "Laat \'n program toe om media-uitvoere na ander eksterne toestelle te roeteer." - "Lees installasiesessies" + "lees installeersessies" "Laat \'n program toe om installasiesessies te lees. Dit laat dit toe om besonderhede van aktiewe pakketinstallasies te sien." - "Versoek installeer-pakette" + "versoek installeerpakkette" "Laat \'n program toe om te versoek dat pakkette geïnstalleer word." "Raak twee keer vir zoembeheer" "Kon nie legstuk byvoeg nie." diff --git a/core/res/res/values-am-watch/strings.xml b/core/res/res/values-am-watch/strings.xml index 95188b6fe1f92..c73ebf97bd353 100644 --- a/core/res/res/values-am-watch/strings.xml +++ b/core/res/res/values-am-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d መተግበሪያ ከ%2$d።" + "አነፍናፊዎች" diff --git a/core/res/res/values-am/cm_strings.xml b/core/res/res/values-am/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-am/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index ddcd80b89e9ce..34e286db40f4a 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -254,7 +254,7 @@ "እንደ የክሬዲት ካርድ ቁጥሮች እና የይለፍ ቃላት ያሉ የግል ውሂብ ያካትታል።" "የሁኔቴ አሞሌ አቦዝን ወይም ቀይር" "የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡" - "ኹናቴ አሞሌ" + "የሁኔታ አሞሌ መሆን" "የኹናቴ አሞሌ እንዲሆን ለመተግበሪያው ይፈቅዳሉ።" "የሁኔታ አሞሌ ዘርጋ/ሰብስብ" "የሁኔታ አሞሌን ለመዝረጋት እና ለመሰብሰብ ለመተግበሪያው ይፈቅዳሉ።" @@ -282,7 +282,7 @@ "መተግበሪያው የWAP መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ፈቃድ የተላኩልዎን መልዕክቶች ለእርስዎ ሳያሳይዎ የመቆጣጠር ወይም የመሰረዝ ብቃትን ያጠቃልላል።" "አሂድ መተግበሪያዎችን ሰርስረው ያውጡ" "መተግበሪያው በአሁኑ ጊዜና በቅርቡ እየተካሄዱ ስላሉ ተግባሮችን መረጃ ሰርስሮ እንዲያወጣ ይፈቅድለታል። ይህ መተግበሪያው በመሳሪያው ላይ የትኛዎቹ መተግበሪያዎች ጥቅም ላይ ስለመዋላቸው መረጃ እንዲያገኝ ሊፈቅድለት ይችላል።" - "የመገለጫ እና የመሣሪያ ባለቤቶችን ያስተዳድሩ" + "የመገለጫ እና የመሣሪያ ባለቤቶችን ማቀናበር" "የመገለጫ ባለቤቶችን እና የመሣሪያውን ባለቤት መተግበሪያዎች እንዲያዋቅሩ ይፈቅዳል።" "አሂድ ትግበራዎችን ድጋሚ ደርድር" "መተግበሪያው ተግባሮችን ወደ ቅድመ ገጹ እና ወደ ዳራው እንዲያንቀሳቅስ ይፈቅድለታል። መተግበሪያው ይህንን ያላንተ ግብዓት ሊያደርግ ይችላል።" @@ -324,7 +324,7 @@ "ስለ ገቢ እና ወጪ ጥሪዎችን ውሂብ ጨምሮ፣ የጡባዊተኮህን ምዝግብ ማስታወሻ ለመቀየር ለመተግበሪያው ይፈቅዳል። ይሄንን ተንኮል አዘል መተግበሪያዎች የስልክህን ምዝግብ ማስታወሻ ለመሰረዝ ወይም ለመለወጥ ሊጠቀሙበት ይችላሉ።" "መተግበሪያው ስለገቢ እና ወጪ ጥሪዎች ያለ ውሂብም ጨምሮ የቴሌቪዥንዎ ምዝግብ ማስታወሻ እንዲይቀርይ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ይህን ተጠቅመው የስልክዎን ምዝግብ ማስታወሻ ሊደመስሱ ወይም ሊቀይሩ ይችላሉ።" "ስለ ገቢ እና ወጪ ጥሪዎችን ውሂብ ጨምሮ፣ የስልክህን ምዝግብ ማስታወሻ ለመቀየር ለመተግበሪያው ይፈቅዳል። ይሄንን ተንኮል አዘል መተግበሪያዎች የስልክህን ምዝግብ ማስታወሻ ለመሰረዝ ወይም ለመለወጥ ሊጠቀሙበት ይችላሉ።" - "የሰውነት መመርመሪያዎች (እንደ የልብ ምት መቆጣጠሪያዎች)" + "የሰውነት ዳሳሾችን መድረስ (እንደ የልብ ምት መከታተያዎች ያሉ)" "እንደ የእርስዎ የልብ ምት የመሳሰሉ ያሉበትን አካላዊ ሁኔታ ከሚቆጣጠሩ ሰውነት ዳሳሾች ውሂብ ላይ እንዲደርስ ለመተግበሪያው ይፈቅደለታል።" "የቀን መቁጠሪያ ክስተቶች ተጨማሪ ሚስጥራዊ መረጃ አንብብ" "መተግበሪያው የጓደኞችን ወይም የስራ ባልደረቦችን ጨምሮ ሁሉንም በጡባዊ ቱኮህ ላይ የተከማቹ የቀን መቁጠሪያ ክስተቶች እንዲያነብ ይፈቅድለታል። ይህ መተግበሪያው የቀን መቁጠሪያ ውሂብህን ሚስጥራዊቱን ከግምት ሳያስገባ እንዲያጋራ ወይም እንዲያስቀምጥ ሊፈቅድለት ይችላል።" @@ -336,15 +336,15 @@ "መተግበሪያው የጓደኞችዎን እና የስራ ባልደረቦችዎን ጨምሮ በስልክዎ ላይ ሊያስተካክሏቸው የሚችሏቸውን ክስተቶች እንዲያክል፣ እንዲያስወግድ፣ እንዲለውጥ ይፈቅድለታል። ይህ መተግበሪያው ከቀን መቁጠሪያ ባለቤቶች የመጡ የሚመስሉ መልዕክቶችን እንዲልክ ወይም ያለባለቤቱ እውቀት ክስተቶችን እንዲያስተካክል ሊፈቅድለት ይችላል።" "ተጨማሪ ሥፍራ አቅራቢ ትዕዛዞችን ድረስ።" "መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይሄ መተግበሪያው በጂፒኤስ ወይም ሌላ የአካባቢ ምንጮች ስራ ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።" - "ትክክለኛ አካባቢ (በጂ ፒ ኤስ እና አውታረ መረብ ላይ የተመሠረተ)" + "ትክክለኛውን አካባቢ መድረስ (በጂፒኤስ እና አውታረ መረብ ላይ የተመሠረተ)" "መተግበሪያው የእርስዎን አለምአቀፍ የመሬት አቀማመጥ ስርዓትን (ጂ ፒ ኤስ) ወይም እንደ የተንቀሳቃሽ ስልክ ማማዎች እና Wi-Fi ያሉ የአውታረ መረብ አካባቢ ምንጮችን ተጠቅሞ ትክክለኛ አካባቢዎትን እንዲያውቅ ያስችለዋል። መተግበሪያው እነዚህ የአካባቢ አገልግሎቶችን እንዲጠቀምባቸው እነሱ ሊበሩ እና ለመሣሪያዎ የሚገኙ መሆን አለባቸው። መተግበሪያዎች እርስዎ የት እንዳሉ ለማወቅ ይህንን ሊጠቀሙበት ይችላሉ፣ እና ተጨማሪ ባትሪ ሊፈጁ ይችላሉ።" - "ግምታዊ አካባቢ (በአውታረ መረብ ላይ የተመሰረተ)" + "ግምታዊ አካባቢን መድረስ (በአውታረ መረብ ላይ የተመሰረተ)" "መተግበሪያው ግምታዊ አካባቢዎትን እንዲያገኝ ያሽችለዋል። ይህ አካባቢ እንደ የተንቀሳቃሽ ስልክ ማማዎች እና Wi-Fi ያሉ የአውታረ መረብ አካባቢ ምንጮችን በመጠቀም የሚገኝ ነው። መተግበሪያው እነዚህ የአካባቢ አገልግሎቶችን እንዲጠቀምባቸው እነሱ ሊበሩ እና ለመሣሪያዎ የሚገኙ መሆን አለባቸው። መተግበሪያዎች እርስዎ የት እንዳሉ ለማወቅ ይህንን ሊጠቀሙበት ይችላሉ።" "የድምፅ ቅንብሮችን ለውጥ" "መተግበሪያው አንደ የድምጽ መጠን እና ለውጽአት የትኛውን የድምጽ ማጉያ ጥቅም ላይ እንደዋለ የመሳሰሉ ሁለንተናዊ የድምጽ ቅንብሮችን እንዲያስተካክል ይፈቅድለታል።" "ኦዲዮ ይቅዱ" "መተግበሪያው ድምጽን በማይክሮፎን እንዲቀዳ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው ያላንተ ማረጋገጫ በማንኛውም ጊዜ ድምጽ እንዲቀዳ ይፈቅድለታል።" - "የሲም ግንኙነት" + "ወደ ሲሙ ትዕዛዞችን መላክ" "መተግበሪያው ትዕዛዞችን ወደ ሲሙ እንዲልክ ያስችለዋል። ይሄ በጣማ አደገኛ ነው።" "ፎቶዎች እና ቪዲዮዎች ያንሱ" "መተግበሪያው በካሜራው ፎቶዎችንና ቪዲዮዎችን እንዲያነሳ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው ካሜራውን በማንኛውም ጊዜ ያላንተ ማረጋገጫ እንዲጠቀም ይፈቅድለታል።" @@ -382,7 +382,7 @@ "መተግበሪያው በስልኩ የሚታወቁትን መለያዎች ዝርዝር እንዲያገኝ ይፈቅድለታል። ይህ በጫንዋቸው ማናቸውም መተግበሪያዎች የተፈጠሩ መለያዎችን ሊያጠቃልል ይችላል።" "የአውታረ መረብ ግንኙነቶችን ይመልከቱ" "መተግበሪያው እንደ የትኛዎቹ አውታረ መረቦች እንዳሉ እና እንደተገናኙ ያሉ የአውታረ መረብ ግንኙነቶች መረጃዎችን እንዲያይ ይፈቅድለታል።" - "ሙሉ የአውታረ መረብ መዳረሻ" + "ሙሉ የአውታረ መረብ መዳረሻ" "መተግበሪያው የአውታረ መረብ መሰኪያዎችን እንዲፈጥር እና ብጁ የአውታረ መረብ ፕሮቶኮሎችን እንዲጠቀም ይፈቅድለታል። አሳሹ እና ሌሎች መተግበሪያዎች ውሂብ ወደ በይነመረብ የመላኪያ መንገዶችን ስለሚያቀርቡውሂብ ወደ በይነመረብ ለመላክ ይህ ፍቃድ አያስፈልግም።" "የአውታረ መረብ ተያያዥነትን ለውጥ" "የእውታረ መረቡን ግንኙነት ሁኔታ ለመለወጥ ለመተግበሪያው ይፈቅዳሉ።" @@ -402,7 +402,7 @@ "የአካባቢውን ብሉቱዝ ጡባዊ ለማዋቀር እና አግኝቶ ከሩቅ መሣሪያዎች ጋር ለማጣመር ለመተግበሪያው ይፈቅዳሉ።" "ከWiMAX ጋር ይገናኙ እና ያላቅቁ" "መተግበሪያው WiMAX እንደነቃ እና ስለማናቸውም የተገናኙ የWiMAX አውታረ መረቦች መረጃ እንዲወስን ይፈቅድለታል።" - "የWiMAX ሁኔታ ለውጥ" + "የWiMAX ሁኔታ ለውጥ" "መተግበሪያው ጡባዊ ተኮውን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።" "መተግበሪያው ቴሌቪዥኑን ከWiMAX አውታረ መረቦች ጋር እንዲያገናኝ እና እንዲያላቀቅ ያስችለዋል።" "መተግበሪያው ስልኩን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።" @@ -485,7 +485,7 @@ "መተግበሪያው የማያ ንካ የማስተካከያ ልኬቶቹን እንዲቀይር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።" "የDRM የምስክር ወረቀቶች ላይ ይድረሱ" "አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠቀም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።" - "የAndroid Beam ሽግግር ሁኔታን ይቀበሉ" + "የAndroid Beam ማስተላለፍ ሁኔታን መቀበል" "ይም መተግበሪያ ስለአሁን የAndroid Beam ሽግግሮች መረጃ እንዲቀበል ይፈቅዳል" "የDRM እውቅና ማረጋገጫዎችን ያስወግዳል" "አንድ መተግበሪያ የDRM እውቅና ማረጋገጫዎችን እንዲያስወግድ ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።" @@ -1091,11 +1091,11 @@ "በመቅረጽ ላይ…" "አልገባም" "ምንም ተመሳሳይ እንቅስቃሴዎች አልተገኙም።" - "የሚዲያ ውፅአት መንገድ" + "የሚዲያ ውፅዓት ማዛወር" "አንድ መተግበሪያ የሚዲያ ውፅአትን ወደ ሌላ ውጫዊ መሳሪያ እንዲመራ ይፈቅድለታል።" - "የመጫን ክፍለ ጊዜዎችን አንብብ" + "የመጫን ክፍለ ጊዜዎችን ማንበብ" "መተግበሪያው የመጫን ክፍለ ጊዜዎችን እንዲያነብ ይፈቅድለታል። ይህም ስለ ገቢር የጥቅል ጭነቶች ዝርዝር መረጃን እንዲያይ ይፈቅድለታል።" - "የጭነት ጥቅሎችን ጠይቅ" + "የጭነት ጥቅሎችን መጠየቅ" "መተግበሪያ የጥቅሎች መጫንን እንዲጠይቅ ይፈቅዳል።" "ለአጉላ መቆጣጠሪያ ሁለት ጊዜ ነካ አድርግ" "ምግብር ማከል አልተቻለም።" diff --git a/core/res/res/values-ar-watch/strings.xml b/core/res/res/values-ar-watch/strings.xml index 8cbb0a56aca99..79dd73028985a 100644 --- a/core/res/res/values-ar-watch/strings.xml +++ b/core/res/res/values-ar-watch/strings.xml @@ -21,4 +21,5 @@ "التطبيق %1$d من %2$d." + "أجهزة الاستشعار" diff --git a/core/res/res/values-ar/cm_strings.xml b/core/res/res/values-ar/cm_strings.xml new file mode 100644 index 0000000000000..4d305cf4ba953 --- /dev/null +++ b/core/res/res/values-ar/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + لقطة شاشة + + استلام رسالة نصية قصيرة محمية + + يسمح للتطبيق باستلام رسالة نصية قصيرة محمية واردة. + + تعديل قائمة الرسائل النصية القصيرة المحمية + + السماح للتطبيق بتعديل قائمة عناوين الرسائل النصية القصيرة المحمية. + + الأمان + + أذونات متعلقة بمعلومات حماية الجهاز. + + قراءة القائمة السوداء للهاتف + + السماح للتطبيق بقراءة المعلومات الخاصة بأرقام الهاتف المحظورة بالنبسة للمكالمات أو الرسائل الواردة. + + تغيير القائمة السوداء للهاتف + + السماح للتطبيق بتغيير أرقام الهاتف التي يتم حظر للمكالمات الواردة أو الرسائل. + + تعيين خلفية شاشة الحارس الرئيسي + + السماج للتطبيق بتغيير خلفية شاشة التأمين. + + إعادة تمهيد + + الحالي + + + إعادة التمهيد + + استرداد + + محمل التمهيد + + التنزيل + + إعادة تمهيد سريعة + + إعادة التمهيد + + ستتم إعادة تمهيد جهازك اللوحي. + ستتم إعادة تمهيد هاتفك. + + إعادة التمهيد\u2026 + + تم إنهاء التطبيق + + تمكين ADB عبر الشبكة + + ADB عبر USB & تمكين الشبكة + + انقر لتعطيل تصحيح الأخطاء. + + ADB - %1$s + USB & الشبكة + USB + الشبكة + + مقاطعة تشغيل التطبيق + + %s لم يتم تثبيته + + الأولوية + بلا + + ايقاف بث تقنية واي فاي بسبب تغيير اشتراك SIM + + إيقاف Wi-Fi + + تمكين أو تعطيل حارس الخصوصية + يسمح للتطبيق بتغيير ما إذا كان تطبيق آخر يعمل مع \"حارس الخصوصية\". عندما يتم تشغيل تطبيق مع \"حارس الخصوصية\"، فلن يُسمح بالوصول إلى البيانات الشخصية كجهات الاتصال أو سجلات المكالمات أو الرسائل. + حارس الخصوصية نشط + %1$s لن تكون قادراً على الوصول إلى البيانات الشخصية + حارس الخصوصية + %1$s يرغب في %2$s. + + تذكر خياري + + الوصول إلى الكاميرا + الوصول إلى موقعك + قراءة إشعاراتك + تفعيل شبكة افتراضية خاصة (VPN) + البدء عند تشغيل الجهاز + حذف سجل مكالماتك + حذف جهات الاتصال الخاصة بك + حذف رسائل MMS + حذف الرسائل النصية القصيرة (SMS) + رسم نوافذ فوق الجزء العلوي + الحصول على إحصائيات باستخدام التطبيقات + إبقاء الجهاز في حالة تنبيه + إجراء اتصال هاتفي + تحديث تقويمك + تحديث سجل المكالمات + تعديل الحافظة + تحديث جهات الاتصال الخاصة بك + تحديث إعدادات النظام + كتم/إلغاء كتم الميكروفون + تشغيل الصوت + آخر إشعار + وسائط المشروع + قراءة التقويم الخاص بك + قراءة سجل المكالمات + قراءة الحافظة + قراءة جهات الاتصال الخاصة بك + قراءة رسائل MMS الخاصة بك + قراءة الرسائل النصية القصيرة الخاصة بك + استلام رسالة نصية قصيرة + تسجيل الصوت + إرسال رسالة نصية قصيرة + إرسال رسالة نصية قصيرة + البدء في التشغيل + عرض الإعلامات المنبثقة + تبديل بلوتوث + تنشيط/إيقاف بيانات الهاتف + تبديل NFC + تنشيط/ايقاف الWi-Fi + التحكم في مستوى صوت الإنذار + التحكم في تركيز الصوت + التحكم في مستوى صوت بلوتوث + التحكم في مستوى الصوت الرئيسي + استخدم أزرار الوسائط + التحكم في مستوى صوت الوسائط + التحكم في مستوى صوت الإشعار + التحكم في مستوى صوت نغمة الرنين + إستخدام نتائج اللمس + التحكم في مستوى صوت المكالمة الصوتية + كتابة رسالة MMS + كتابة رسالة نصية قصيرة + استخدام بصمة اليد + اضافة البريد الصوتى + الوصول الى حالة الهاتف + فحص شبكات Wi-Fi + تغيير الخلفية + استخدام مساعد الهيكل + التقاط الشاشة + استخدام مستشعرات الجسم + قراءة البث الخلوي + تجاهل موقعك الحالى + قراءة الذاكرة الخارجية + كتابة الذاكرة الخارجية + فتح الشاشة + احصل على حسابات الجهاز + تغيير حالة الـ Wi-Fi + الحصول على صلاحيات الجذر + + لإلغاء تثبيت هذه الشاشة، المس واستمر في ضغط زر الرجوع. + + لا يوجد جهاز متصل + %1$s جهاز متصل + %1$s أجهزة متصلة + + + + منع نشاط التشغيل + %1$s ممنوع من التشغيل. المس للمصادقة وتشغيل التطبيق. + + البطارية مشحونة بالكامل + قم بفصل جهازك من الشاحن لتحسين طول عمر البطارية. + + إعادة تعيين إحصائيات البطارية + + يسمح للتطبيق بإعادة تعيين بيانات استخدام بطارية ذات المستوى المنخفض الحالي. + + تم تغيير بطاقات SIM + اضغط لتعيين التفضيلات الافتراضية لبطاقة SIM + diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 38928d7085b9d..080a456c3be17 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -258,7 +258,7 @@ "يتضمن بيانات شخصية مثل أرقام بطاقات الائتمان وكلمات المرور." "تعطيل شريط الحالة أو تعديله" "للسماح للتطبيق بتعطيل شريط الحالة أو إضافة رموز نظام وإزالتها." - "شريط الحالة" + "العمل كشريط للحالة" "للسماح للتطبيق بأن يكون شريط الحالة." "توسيع/تصغير شريط الحالة" "للسماح للتطبيق بتوسيع شريط الحالة أو تصغيره." @@ -286,7 +286,7 @@ "‏للسماح للتطبيق بتلقي رسائل WAP ومعالجتها. ويتضمن هذا الإذن إمكانية مراقبة الرسائل التي يتم إرسالها إليك أو حذفها بدون عرضها لك." "استرداد التطبيقات التي قيد التشغيل" "للسماح للتطبيق باسترداد معلومات حول المهام التي يجري تشغيلها حاليًا والتي تم تشغيلها مؤخرًا. وقد يسمح هذا للتطبيق باكتشاف معلومات حول التطبيقات المستخدمة على الجهاز." - "إدارة المالكين لكل من الملف الشخصي والجهاز" + "إدارة الملف الشخصي ومالكي الجهاز" "للسماح للتطبيقات بتعيين مالكي الملف الشخصي ومالك الجهاز." "إعادة ترتيب التطبيقات قيد التشغيل" "للسماح للتطبيق بنقل المهام إلى المقدمة والخلفية. وقد يجري التطبيق ذلك بدون إذنك." @@ -328,7 +328,7 @@ "للسماح للتطبيق بتعديل سجل مكالمات الجهاز اللوحي، بما في ذلك البيانات عن المكالمات الواردة والصادرة. وربما تستخدم التطبيقات الضارة هذا لمسح سجل المكالمات أو تعديله." "يتيح للتطبيق تعديل سجل مكالمات التلفزيون، بما في ذلك البيانات عن المكالمات الواردة والصادرة. وربما تستخدم التطبيقات الضارة هذا لمسح سجل المكالمات أو تعديله." "للسماح للتطبيق بتعديل سجل مكالمات الهاتف، بما في ذلك البيانات عن المكالمات الواردة والصادرة. وربما تستخدم التطبيقات الضارة هذا لمحو سجل المكالمات أو تعديله." - "أجهزة استشعار الجسم (مثل شاشات معدل ضربات القلب)" + "الوصول إلى أجهزة استشعار الجسم (مثل شاشات معدل ضربات القلب)" "للسماح للتطبيق بالدخول إلى البيانات من المستشعرات التي تراقب الحالة البدنية، مثل معدل نبضات القلب." "قراءة أحداث التقويم بالإضافة إلى المعلومات السرية" "للسماح للتطبيق بقراءة جميع أحداث التقويم المخزنة على الجهاز اللوحي، بما في ذلك أحداث التقويم التابعة للأصدقاء أو زملاء العمل. وقد يتيح هذا للتطبيق مشاركة بيانات التقويم أو حفظها، بغض النظر عن مدى سرية البيانات أو حساسيتها." @@ -340,15 +340,15 @@ "للسماح للتطبيق بإضافة أو إزالة أو تغيير الأحداث التي يمكنك تعديلها على هاتفك، بما في ذلك أحداث الأصدقاء أو زملاء العمل. وقد يتيح هذا للتطبيق إرسال رسائل يبدو أنها واردة من أصحاب التقويم أو تعديل الأحداث بدون معرفة المالكين." "الدخول إلى المزيد من أوامر موفر الموقع" "‏للسماح للتطبيق بالدخول إلى أوامر إضافية لموفر الموقع. قد يتيح هذا للتطبيق التداخل مع تشغيل تقنية نظام تحديد المواقع العالمي (GPS) أو مصادر الموقع الأخرى." - "الموقع الدقيق (مستند إلى نظام تحديد المواقع العالمي والشبكة)" + "‏الوصول إلى الموقع الدقيق (استنادًا إلى نظام تحديد المواقع العالمي \"GPS\" والشبكة)" "‏للسماح للتطبيق بتحديد موقعك بدقة وهذا باستخدام نظام تحديد المواقع العالمي (GPS) أو مصادر المواقع التي تستخدم الشبكات مثل أبراج الجوال أو تقنية Wi-Fi. يتعين توفر خدمات المواقع هذه وتشغيلها على جهازك للتطبيق كي يستخدمها. وقد تستخدم التطبيقات هذا لتحديد موقعك وقد تستهلك مزيدًا من طاقة البطارية." - "الموقع التقريبي (مستند إلى الشبكة)" + "الوصول إلى الموقع التقريبي (استنادًا إلى الشبكة)" "‏للسماح للتطبيق بتحديد موقعك التقريبي الذي يستمد من خدمات الموقع باستخدام مصادر المواقع التي تستخدم الشبكات مثل أبراج الجوال وتقنية Wi-Fi. يتعين توفر خدمات المواقع هذه وتشغيلها على جهازك للتطبيق كي يستخدمها. وقد تستخدم التطبيقات هذا لتحديد موقعك التقريبي." "تغيير إعداداتك الصوتية" "للسماح للتطبيق بتعديل إعدادات الصوت العامة مثل مستوى الصوت وأي السماعات يتم استخدامها للاستماع." "تسجيل الصوت" "للسماح للتطبيق بتسجيل الصوت باستخدام الميكروفون. ويتيح هذا الإذن للتطبيق تسجيل الصوت في أي وقت وبدون موافقة منك." - "‏اتصالات SIM" + "‏إرسال أوامر إلى شريحة SIM" "‏السماح للتطبيق بإرسال أوامر إلى شريحة SIM. وهذا أمر بالغ الخطورة." "التقاط صور ومقاطع فيديو" "للسماح للتطبيق بالتقاط صور ومقاطع فيديو من خلال الكاميرا. ويتيح هذا الإذن للتطبيق استخدام الكاميرا في أي وقت وبدون موافقة منك." @@ -386,7 +386,7 @@ "للسماح للتطبيق بالحصول على قائمة بالحسابات التي يعرفها الهاتف. وقد يتضمن ذلك أية حسابات تم إنشاؤها بواسطة التطبيقات التي ثبتها." "عرض اتصالات الشبكة" "للسماح للتطبيق بعرض معلومات حول اتصالات الشبكة كعرض معلومات عن الشبكات المتوفرة والشبكات المتصلة." - "إمكانية دخول كاملة إلى الشبكة" + "حق الوصول الكامل إلى الشبكة" "للسماح للتطبيق بإنشاء مقابس شبكات واستخدام بروتوكولات شبكات مخصصة. ويوفر المتصفح وتطبيقات أخرى طرقًا لإرسال البيانات إلى الإنترنت، ولذلك لا يعد هذا الإذن مطلوبًا لإرسال البيانات إلى الإنترنت." "تغيير اتصال الشبكة" "للسماح للتطبيق بتغيير حالة اتصال الشبكة." @@ -406,7 +406,7 @@ "للسماح للتطبيق بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها." "‏الاتصال بـشبكة WiMAX وقطع الاتصال بها" "‏للسماح للتطبيق بتحديد ما إذا تم تمكين WiMAX وتحديد معلومات حول أية شبكات WiMAX متصلة." - "‏تغيير حالة WiMAX" + "‏تغيير حالة WiMAX" "‏للسماح للتطبيق بتوصيل الجهاز اللوحي بشبكات WiMAX وقطع اتصاله بها." "‏يتيح للتطبيق توصيل التلفزيون أو إلغاء توصيله بشبكات WiMAX." "‏للسماح للتطبيق بتوصيل الهاتف بشبكات WiMAX وقطع اتصاله بها." @@ -489,7 +489,7 @@ "يتيح للتطبيق إمكانية تعديل معلمات المعايرة في شاشة اللمس. يجب عدم اللجوء إليه مع التطبيقات العادية." "‏الدخول إلى شهادات DRM" "‏للسماح لأحد التطبيقات بتقديم شهادات DRM واستخدامها. لا يجب أن يكون ذلك لازمًا مطلقًا مع التطبيقات العادية." - "‏تلقي حالة نقل شعاع Android" + "‏تلقي حالة نقل شعاع Android" "‏السماح لهذا التطبيق بتلقي معلومات حول عمليات نقل شعاع Android الحالية" "‏إزالة شهادات DRM" "‏للسماح لأحد التطبيقات بإزالة شهادات DRM. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية." @@ -1119,11 +1119,11 @@ "جارٍ التهيئة…" "لم يتم الإدخال" "لم يتم العثور على أي أنشطة متطابقة." - "توجيه إخراج الوسائط" + "توجيه إخراج الوسائط" "للسماح للتطبيق بتوجيه إخراج الوسائط إلى أجهزة خارجية أخرى." - "قراءة جلسات التثبيت" + "قراءة جلسات التثبيت" "للسماح لأحد التطبيقات بقراءة جلسات التثبيت. ويسمح لك هذا بالاطلاع على تفاصيل بشأن عمليات تثبيت الحزم النشطة." - "طلب تثبيت الحزم" + "طلب حزم التثبيت" "للسماح لتطبيق ما بطلب تثبيت الحزم." "المس مرتين للتحكم في التكبير/التصغير" "تعذرت إضافة أداة." diff --git a/core/res/res/values-as-rIN/cm_strings.xml b/core/res/res/values-as-rIN/cm_strings.xml new file mode 100644 index 0000000000000..c41062011dbf5 --- /dev/null +++ b/core/res/res/values-as-rIN/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + স্ক্ৰীণস্বট + + প্ৰতিৰোধী SMS প্ৰাপ্ত কৰক + + এপ্প্‌টোক ইনকামিং প্ৰতিৰোধী SMS প্ৰাপ্ত কৰিবলৈ অনুমতি দিয়ক। + + প্ৰতিৰোধী SMS ৰ সূচী সংশোধন + + প্ৰতিৰোধী SMS ঠিকনা সূচী সংশোধন কৰিবলৈ এপ্পক অনুমতি দিয়ে। + + ছিকিউৰিটি + + ডিভাইচৰ নিৰাপত্তা তথ্য সম্পৰ্কিত অনুমতি। + + ফোনৰ ব্লেকলিষ্ট পঢ়া + + এপ্প্‌টোক ইনকামিং কল বা বাৰ্তাৰ বাবে অৱৰুদ্ধ কৰা ফোন নম্বৰবোৰৰ তথ্য পঢ়িবলৈ অনুমতি দিয়ে। + + ফোনৰ ব্লেকলিষ্ট পৰিবৰ্তন কৰা + + এপ্প্‌টোক ইনকামিং কল বা বাৰ্তাৰ বাবে অৱৰুদ্ধ কৰা ফোন নম্বৰবোৰ পৰিবৰ্তন কৰিবলৈ অনুমতি দিয়ে। + + কীগাৰ্ড ৱালপেপাৰ ছেট কৰা + + এপ্প্‌ এটাক লক স্ক্ৰীণৰ ৱালপেপাৰ পৰিবৰ্তন কৰিবলৈ অনুমতি দিয়ে। + + ৰিবুট + + বৰ্তমান + + + ৰিবুট + + পুনৰুদ্ধাৰ + + বুটলোডাৰ + + ডাউনলোড + + কোমল পুনঃবুট + + ৰিবুট + + আপোনাৰ টেবলেট কম্পিউটাৰ ৰিবুট হ\'ব। + আপোনাৰ ফোন পুনৰাৰম্ভ হ\'ব। + + ৰিবুটিং\u2026 + + এপ্প্‌ বন্ধ হৈছে + + ADB অভাৰ নেটৱৰ্ক সক্ষম কৰা হৈছে + + ADB অভাৰ USB আৰু নেটৱৰ্ক সক্ষম কৰা হৈছে + + ডিবাগিং অক্ষম কৰিবলৈ স্পৰ্শ কৰক। + + ADB - %1$s + USB আৰু নেটৱৰ্ক + USB + নেটৱৰ্ক + + এপ্প্‌ লান্চ্চ কৰাটো অৱৰুদ্ধ কৰা + + %s ইনষ্টল কৰা নাই + + অগ্ৰাধিকাৰ + হাল্লা + + SIM গ্ৰাহকভুক্তি পৰিৱৰ্তন হোৱা বাবে Wi-Fi হটস্পট অক্ষম কৰা হৈছে + + Wi-Fi অফ কৰা + + গোপনীয়তা ৰক্ষক সক্ষম বা অক্ষম কৰা + আন এটা এপ্পে গোপনীয়তা ৰক্ষকৰ সৈতে চলিব নে সেইটো পৰিবৰ্তন কৰিবলৈ অনুমতি দিয়ে। যেতিয়া এটা এপ্প্‌ গোপনীয়তা ৰক্ষকৰ সৈতে চলি থাকে, তেতিয়া ই যোগাযোগ, কল লগ বা বাৰ্তাৰ দৰে ব্যক্তিগত ডাটাবোৰত প্ৰৱেশ কৰিব নোৱাৰে। + গোপনীয়তা ৰক্ষক সক্ৰিয় কৰা + %1$s এ ব্যক্তিগত ডাটাত প্ৰৱেশ কৰিব নোৱাৰে + গোপনীয়তা ৰক্ষক + %2$s%1$s কৰিবলৈ বিচাৰে। + + মোৰ পচন্দ মনত ৰাখক + + কেমেৰাত প্ৰৱেশ কৰক + আপোনাৰ অৱস্থানত প্ৰৱেশ কৰক + আপোনাৰ অধিসূচনাসমূহ পঢ়া + এটা VPN সক্ৰিয় কৰা + পাৱাৰ আপৰ সময়ত আৰম্ভ কৰা + আপোনাৰ কল লগবোৰ বিলোপ কৰা + আপোনাৰ যোগাযোগবোৰ বিলোপ কৰা + আপোনাৰ MMS বাৰ্তাবোৰ বিলোপ কৰা + আপোনাৰ SMS বাৰ্তাবোৰ বিলোপ কৰা + উইণ্ডো শীৰ্ষলৈ টানি অনা + এপ্প্‌ ব্যৱহাৰৰ পৰিসংখ্যা পোৱা + আপোনাৰ ডিভাইচ সাৰে ৰখা + এটা ফোন কল কৰা + আপোনাৰ কেলেণ্ডাৰ উন্নীত কৰা + কল লগ উন্নীত কৰা + ক্লিপবোৰ্ড সংশোধন কৰা + আপোনাৰ কণ্টেক্টবোৰ উন্নীত কৰা + ছিষ্টেম ছেটিং উন্নীত কৰা + মাইক্ৰ\'ফোন মিউট/আনমিউট কৰা + অডিঅ’ প্লে কৰক + অধিসূচনা পোষ্ট কৰা + প্ৰজেক্ট মিডিয়া + আপোনাৰ কেলেণ্ডাৰ পঢ়া + কল লগ পঢ়া + ক্লিপবোৰ্ড পঢ়া + আপোনাৰ কনটেক্টসমূহ পঢ়ক + আপোনাৰ MMS বাৰ্তাবোৰ পঢ়া + আপোনাৰ SMS বাৰ্তাবোৰ পঢ়া + এটা SMS বাৰ্তা প্ৰাপ্ত কৰা + অডিঅ’ ৰেকৰ্ড + MMS বাৰ্তা প্ৰেৰণ কৰা + SMS বাৰ্তা প্ৰেৰণ কৰা + পাৱাৰ আপৰ সময়ত আৰম্ভ কৰা + টোষ্ট বাৰ্তা প্ৰদৰ্শন কৰা + Bluetooth টগল কৰা + ম\'বাইল ডাটা টগল কৰক + NFC টগল কৰা + Wi-Fi টগল কৰক + এলাৰ্ম ভলিউম নিয়ন্ত্ৰণ কৰা + অডিঅ\' ফোকাচ নিয়ন্ত্ৰণ কৰা + Bluetooth ভলিউম নিয়ন্ত্ৰণ কৰা + মাষ্টাৰ ভলিউম নিয়ন্ত্ৰণ কৰা + মিডিয়া বুটামবোৰ নিয়ন্ত্ৰণ কৰা + মিডিয়া ভলিউম নিয়ন্ত্ৰণ কৰা + অধিসূচনা ভলিউম নিয়ন্ত্ৰণ কৰা + ৰিংটোন ভলিউম নিয়ন্ত্ৰণ কৰা + হেপ্টিক ফীডবেক ব্যৱহাৰ কৰা + ভইচ কল ভলিউম নিয়ন্ত্ৰণ কৰা + এটা MMS বাৰ্তা লিখক + এটা SMS বাৰ্তা লিখক + আঙুলিৰছাপ ব্যৱহাৰ কৰক + এটা ভইচমেইল যোগ দিয়ক + ফোন অৱস্থাত প্ৰৱেশ কৰক + Wi-Fi নেটৱৰ্ক স্কেন কৰক + ৱালপেপাৰ পৰিৱৰ্তন কৰক + সহায়তা গাঁথনি ব্যৱহাৰ কৰক + এটা স্ক্ৰীণশ্বট লওক + দেহ চেনচৰ ব্যৱহাৰ কৰক + চেল ব্ৰডকাষ্ট পঢ়ক + আপোনাৰ অৱস্থান ম\'ক কৰক + বাহ্যিক ষ্ট\'ৰেজ পঢ়ক + বাহ্যিক ষ্ট\'ৰেজলৈ লিখক + স্ক্ৰীণ অন কৰক + ডিভাইচ একাউণ্ট প্ৰাপ্ত কৰক + Wi-Fi অৱস্থা পৰিৱৰ্তন কৰক + ৰুট প্ৰৱেশাধিকাৰ প্ৰাপ্ত কৰা + + এই স্ক্ৰীণ আনপিন কৰিবলৈ, বেক বুটামটো স্পৰ্শ কৰক আৰু হেঁচি ৰাখক। + + কোনো সংযোগিত ডিভাইচ নাই + %1$s সংযোগিত ডিভাইচ + %1$s সংযোগিত ডিভাইচসমূহ + + + + কাৰ্যকলাপ লান্চ্চ কৰাটো অৱৰুদ্ধ কৰা হৈছে + %1$s টো লান্চ্চ কৰাৰ পৰা প্ৰতিৰোধী। এপ্লিকেচনটো প্ৰমাণীকৰণ আৰু লান্চ্চ কৰিবলৈ টেপ কৰক। + + বেটেৰী সম্পূৰ্ণৰূপে চাৰ্জ হৈ গ\'ল + বেটেৰীৰ জীৱ্ন কাল বঢ়াবলৈ আপোনাৰ ডিভাইচটো চাৰ্জাৰৰ পৰা আতৰাই ৰাখক। + + বেটাৰী পৰিসংখ্যা ৰিছেট কৰক + + এটা এপ্লিকেচনক চলিত নিম্ন-লেভেলৰ বেটাৰি ব্যৱহাৰ ডাটা ৰিছেট কৰিবলৈ অনুমতি দিয়ে। + + diff --git a/core/res/res/values-as-rIN/strings.xml b/core/res/res/values-as-rIN/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-as-rIN/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ast-rES/cm_strings.xml b/core/res/res/values-ast-rES/cm_strings.xml new file mode 100644 index 0000000000000..bed144f8edaab --- /dev/null +++ b/core/res/res/values-ast-rES/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Capturar pantalla + + recibir SMS protexíos + + Permite que l\'aplicación reciba mensaxes SMS entrantes protexíos. + + modificar llista de SMS protexíos + + Permite que l\'aplicación modifique la llista de direiciones de mensaxes SMS protexíos. + + Seguridá + + Permisos rellacionaos a la seguridá de la información del preséu. + + Lleer llista prieta del teléfonu + + Permite a una aplicación lleer información sobre los númberos telefónicos bloquiaos pa llamaes o mensaxes entrantes. + + camudar la llista prieta del teléfonu + + Permite qu\'una aplicación camude los númberos telefónicos bloquiaos pa llamaes o mensaxes entrantes. + + Afita\'l fondu de pantalla de bloquéu + + Permite que l\'aplicación afite\'l fondu de la pantalla de bloquéu. + + Reaniciar + + Actual + + + Reaniciar + + Mou Recovery + + Mou Bootloader + + Descargar + + Reaniciu suave + + Reaniciar + + La tablet va reaniciase. + El teléfonu va reaniciase. + + Reaniciando\u2026 + + Aplicación finada + + ADB sobre rede habilitáu + + ADB sobre USB y rede habilitáu + + Toca pa deshabilitar la depuración. + + ADB - %1$s + USB y rede + USB + Rede + + interceutar la execución d\'aplicaciones + + %s nun ta instalada + + Prioridá + Dengún + + Deshabilitóse\'l puntu Wi-Fi pola mor del cambéu de la soscripción de la SIM + + Apagar Wi-Fi + + habilitar o deshabilitar la privacidá + Permite que l\'aplicación cambie l\'estáu de privacidá d\'otra. Cuando una aplicación s\'executa cola privacidá habilitada, nun va poder acceder a los datos personales, talos como contautos, mensaxes o rexistros de llamaes. + Privacidá activada + %1$s nun va poder acceder a los datos personales + Privacidá + %1$s quies %2$s. + + Recordar la mio escoyeta + + acceder a la cámara + acceder a la to llocalización + lleer les tos notificaciones + activar una VPN + executase al aniciu + desaniciar rexistru de llamaes + desaniciar contautos + desaniciar los tos MMS + desaniciar los tos SMS + dibuxar ventanes na parte superior + obtener estadístiques d\'usu de l\'app + caltener encesu\'l preséu + facer una llamada + anovar el to calendariu + anovar el rexistru de llamaes + modificar el cartafueyu + anovar los tos contautos + anovar los axustes del sistema + activar/silenciar micrófonu + reproducir soníu + espublizar una notificación + Proyeutu Media + lleer el to calendariu + lleer el rexistru de llamaes + lleer el cartafueyu + lleer los tos contautos + lleer los tos mensaxes MMS + lleer los tos mensaxes SMS + recibir un mensaxe SMS + grabar soníu + unviar un mensaxe MMS + unviar un mensaxe SMS + executase al aniciu + notificaciones emerxentes + cambiar Bluetooth + conmutar datos móviles + cambiar NFC + alternar Wi-Fi + remanar volume de l\'alarma + remanar el volume de soníu + remanar el volume del Bluetooth + remanar el volume principal + usar los botones multimedia + remanar el volume multimedia + remanar el volume de notificaciones + remanar el volume de llamada + usar rempuesta háptica + remanar el volume de la llamada + escribir un mensaxe MMS + escribir un mensaxe SMS + usar buelga + amestar corréu de voz + estáu d\'accesu al teléfonu + escaniar rede Wi-Fi + camudar el fondu + usar cadarma d\'asistencia + facer una captura + usar sensores corporales + lleer tresmisiones celulares + simular la llocalización + lleer almacenamientu esternu + escribir almacenamientu esternu + prender pantalla + consiguir cuentes del preséu + camudar estáu del Wi-Fi + obtener accesu root + + Pa desfixar esta pantalla, ten primíu\'l botón Atrás. + + Nun hai dengún preséu coneutáu + %1$s preséu coneutáu + %1$s preseos coneutaos + + + + Bloquióse\'l llanzamientu de l\'actividá + %1$s protexóse pa nun llanciase. Calca p\'autenticate y llanciar l\'aplicación. + + Batería cargada ensembre + Desconeuta\'l preséu del cargador p\'ameyorar la vida útil de la batería. + + reafitar estadístiques de batería + + Permite qu\'una aplicación reafite los datos actuales d\'usu de batería a nivel baxu. + + Les tarxetes SIM camudaron + Toca p\'afitar les preferencies por defeutu de la tarxeta SIM + diff --git a/core/res/res/values-ast-rES/strings.xml b/core/res/res/values-ast-rES/strings.xml new file mode 100644 index 0000000000000..e1b3d0107ea42 --- /dev/null +++ b/core/res/res/values-ast-rES/strings.xml @@ -0,0 +1,3179 @@ + + + + + + B + + KB + + MB + + GB + + TB + + PB + + %1$s%2$s + + %1$d díes + + %1$d día + %2$d hrs + + %1$d día + %2$d hrs + + %1$d hrs + + %1$d hr + %2$d mins + + %1$d hr + %2$d mins + + %1$d mins + + %1$d min + + %1$d min + %2$d segs + + %1$d min + %2$d segs + + %1$d segs + + %1$d seg + + <Ensin títulu> + + (Ensin númberu de teléfonu) + + Desconocíu + + Buzón de voz + + MSISDN1 + + + + Hebo un fallu de conexón o\'l códigu MMI nun ye válidu. + + La operación namái ye válida pa númberos de marcación fixa. + + El serviciu habilitóse. + + Habilitóse\'l serviciu pa: + + El serviciu inhabilitóse. + + El rexistru féxose correutamente. + + L\'elementu desanicióse correutamente. + + Contraseña incorreuta + + MMI completu + + El códigu PIN antiguu qu\'introduxisti ye correutu. + + El códigu PUK qu\'introduxisti nun ye correutu. + + Los códigos PIN inxertaos nun concasen. + + Introduz un códigu PIN con una llonxitú ente cuatro y ocho díxitos. + + Escribi un códigu PUK d\'ocho caráuteres o más. + + La tarxeta SIM ta bloquiada col códigu PUK. Introduz el códigu PUK pa desbloquiala. + Introduz el códigu PUK2 pa desbloquiar la tarxeta SIM. + + Error, habilitar bloquéu de SIM/RUIM. + + + Quédate %d intentu pa bloquiar la tarxeta SIM. + Quédente %d intentos pa bloquiar la tarxeta SIM. + + + IMEI + + MEID + + ID d\'emisor de llamada entrante + + ID d\'emisor de llamada saliente + + ID de llinia coneutada + + Restricción de ID de llinia coneutada + + Esvíu de llamada + + Llamada n\'espera + + Bloquéu de llamada + + Cambéu de contraseña + + Cambéu de PIN + Númberu de llamada entrante presente + Númberu de llamada entrante restrinxíu + Llamada a trés + Refugu de llamaes molestes non deseaes + Entrega de númberu de llamada entrante + Nun molestar + + El ID d\'emisor presenta\'l valor predetermináu de restrinxíu. Siguiente llamada: Restrinxíu + + El ID d\'emisor presenta\'l valor predetermináu de restrinxíu. Siguiente llamada: Non restrinxíu + + El ID d\'emisor presenta\'l valor predetermináu de no restrinxíu. Siguiente llamada: Restrinxíu + + El ID d\'emisor presenta\'l valor predetermináu de no restrinxíu. Siguiente llamada: Non restrinxíu + + El serviciu nun se suministra. + + Nun pues modificar el ID d\'emisor. + + Modificóse l\'accesu restrinxíu. + + El serviciu de datos ta bloquiáu. + + El serviciu d\'emerxencia ta bloquiáu. + + El serviciu de voz ta bloquiáu. + + Tán bloquiaos tolos servicios de voz. + + El serviciu de SMS ta bloquiáu. + + Los servicios de voz y de datos tán bloquiaos. + + Tán bloquiaos tolos servicios de voz y de SMS. + + Tán bloquiaos tolos servicios de voz, de datos y de SMS. + + El preséu solicitó\'l mou TTY FULL. + El preséu solicitó\'l mou TTY HCO. + El preséu solicitó\'l mou TTY VCO. + El preséu solicitó\'l mou TTY OFF. + + + + Voz + + Datos + + FAX + + SMS + + Asíncronos + + Sincronización + + Paquete + + PAD + + + + Indicador d\'itinerancia activáu + Indicador d\'itinerancia desactiváu + Indicador d\'itinerancia parpaguiante + Fuera del vecindariu + Fuera del edificiu + Itinerancia: sistema preferíu + Itinerancia: sistema disponible + Itinerancia: partner d\'alianza + Itinerancia: partner de gran calidá + Itinerancia: funcionalidá de serviciu completa + Itinerancia: funcionalidá de serviciu parcial + Banner d\'itinerancia activáu + Banner d\'itinerancia desactiváu + Guetando serviciu + + Llamaes Wifi + + + + + + + %s + + %s + + Non + + Rede Wi-Fi preferida + + Rede móvil preferida + + Namái Wi-Fi + + + + {0}: Non esviada + + {0}: {1} + + {0}: {1} trescurríos {2} segundos + + {0}: Non esviada + + {0}: Non esviada + + + + Códigu de función completu + + Hebo un fallu de conexón o\'l códigu de la función nun ye válidu. + + + + Aceutar + + Hebo un fallu de rede. + + Nun pudo alcontrase la URL. + + Nun s\'almite l\'esquema d\'autenticación del sitiu. + + Nun pudo autenticase. + + L\'autenticación per aciu del sirvidor proxy nun se fexo correutamente. + + Nun pudo afitase conexón col sirvidor. + + Nun pudo afitase comunicación col sirvidor. Inténtalo de nueves. + + Escosó\'l tiempu d\'espera de conexón col sirvidor. + + La páxina contién munchos redireicionamientos de sirvidor. + + Protocolu non almitíu + + Nun pudo afitase una conexón segura. + + Nun pudo abrise la páxina porque la URL nun ye válida. + + Nun pudo accedese al ficheru. + + Nun pudo atopase\'l ficheru solicitáu. + + Tán procesándose abondes solicitúes. Vuelvi a intentalo dempués. + + + + Error d\'aniciu de sesión de %1$s + + + + Sincronización + + Sincronización + + Abondes eliminaciones de %s + + Escosó l\'espaciu d\'almacenamientu de la tablet. Desanicia dalgunos ficheros pa lliberar espaciu. + + Escosó l\'espaciu d\'almacenamientu de la tablet. Desanicia dalgunos ficheros pa lliberar espaciu. + + L\'almacenamientu de la TV ta completu. Desanicia dalgunos ficheros pa lliberar espaciu. + + Escosó l\'espaciu d\'almacenamientu del teléfonu. Desanicia dalgunos ficheros pa lliberar espaciu. + + + + Ye dable que la rede tea supervisada + + Por un terceru desconocíu + + Pol alministrador del perfil de trabayu + + Por %s + + + + Perfil de trabayu desaniciáu + + Desanicióse\'l perfil de trabayu por mor de la falta d\'una app d\'alministración. + + L\'app d\'alministración de perfil de trabayu nun s\'atopa o ta frañada. + Desaniciáronse\'l perfil de trabayu y datos. Contauta col alministrador p\'asistencia. + + El to perfil de trabayu yá nun ta disponible nesti preséu. + + + + Van desaniciase los datos del preséu + + L\'app alministración nun s\'atopa o ta dañada, y nun pue usase. + Van desaniciase los datos del preséu. Contauta col alministrador pa más ayuda. + + Yo + + + + Opciones de la tablet + + Opciones de TV + + Opciones del teléfonu + + Mou silenciu + + Activar conexón inalámbrica + + Desactivar función inalámbrica + + Bloquéu de pantalla + + Apagar + + Timbre desactiváu + + Mou vibración + + Timbre activáu + + Anovamientu del sistema Android + Preparando l\'anovamientu\u2026 + Procesando\'l paquete d\'anovamientu\u2026 + Reaniciando\u2026 + + Reafitar a axustes de fábrica + Reiniciando\u2026 + + Apagando\u2026 + + La tablet va apagase. + + Va apagase la TV. + + El reló va apagase + + El teléfonu va apagase. + + ¿De xuru que quies apagar el teléfonu? + + Reaniciar en mou seguru + + ¿Quies reaniciar el sistema en mou seguru? Van inhabilitase toles aplicaciones esternas que tengas instalaes. Eses aplicaciones van restaurase la próxima vegada que reanicies del sistema. + + Reciente + + Nun hai aplicaciones recientes. + + Opciones de la tablet + + Opciones de TV + + Opciones del teléfonu + + Bloquéu de pantalla + + Apagar + + Informe de fallu + + Crear informe de fallos + + Va atropase información tocante al estáu actual del preséu y va unviase per corréu-e. Van pasar unos minutos dende qu\'entame a xenerase l\'informe de fallos hasta que s\'unvie, polo qu\'encamentámoste que seyas paciente. + + + Mou silenciu + + El soníu ta desactiváu. Activar + + El soníu ta activáu. Desactivar + + Mou avión + + Mou avión activáu + + Mou avión desactiváu + + Axustes + + Asistencia + + Asistente voz + + Bloquiar agora + + 999+ + + Mou seguru + + Sistema Android + + Personal + + Trabayu + + Contautos + + acceder a los contautos + + Llocalización + + accesu a la llocalización d\'esti preséu + + Calendariu + + acceder al calendariu + + SMS + + unviar y ver mensaxes SMS + + Almacenamientu + + acceder a les semeyes, conteníu multimedia y los ficheros del preséu + + Micrófonu + + grabar soníu + + Cámara + + facer semeyes y grabar vídeos + + Teléfonu + + facer y xestionar llamaes telefóniques + + Sensores corporales + + acceder a los datos del sensor tocante a los tos signos vitales + + Recuperar el conteníu de la ventana + + Inspeiciona\'l conteníu de la ventana cola que teas interactuando. + + Activar esploración táctil + + Los elementos esbillaos van dicise en voz alta y vas poder esplorar la pantalla per duana de xestos. + + Activar accesibilidá web meyorada + + Ye dable que s\'instalen secuencies de comandos pa que\'l conteníu de les aplicaciones seya más accesible. + + Observar el testu qu\'escribes + + Inclúi datos personales como númberos de tarxetes de créitu y contraseñes. + + + inhabilitar o modificar la barra d\'estáu + + Permite que l\'aplicación inhabilite la barra d\'estáu o amieste y desanicie iconos del sistema. + + ser la barra d\'estáu + + Permite que l\'aplicación apaeza na barra d\'estáu. + + espander/contrayer la barra d\'estáu + + Permite que l\'aplicación espanda o contraiga la barra d\'estáu. + + instalar accesos direutos + + Permite qu\'una aplicación amieste accesos direutos a la pantalla d\'aniciu ensin intervención del usuariu. + + desinstalar accesos direutos + + Permite que l\'aplicación desanicie accesos direutos de la pantalla d\'aniciu ensin la intervención del usuariu. + + redireicionar llamaes salientes + + Permite que l\'aplicación vea\'l númberu que se ta marcando mientres una llamada saliente cola opción de redirixila a otro númberu o albortar dafechu la llamada. + + recibir mensaxes de testu (SMS) + + Permite que l\'aplicación reciba y procese mensaxes MMS, lo que significa que podría usar esti permisu pa remanar o desaniciar mensaxes unviaos al preséu ensin amosá-ylos al usuariu. + + recibir mensaxes de testu (MMS) + + Permite que l\'aplicación reciba y procese mensaxes MMS, lo que significa que podría usar esti permisu pa remanar o desaniciar mensaxes unviaos al preséu ensin amosá-ylos al usuariu. + + lleer mensaxes de difusión móvil + + Permite a l\'app lleer + los mensaxes de difusión móvil que recibe\'l preséu. En dalgunas llocalizaciones, + les alertes de difusión móvil únviense pa informar situaciones d\'emerxencia. + Les aplicaciones malicioses puen afeutar el rindimientu o funcionamientu del + preséu cuando se recibe un mensaxe de difusión móvil d\'emerxencia. + + lleer feeds a los que ta soscritu l\'usuariu + + Permite que l\'aplicación obtenga detalles sobre los feeds sincronizaos anguaño. + + unviar y ver mensaxes SMS + + Permite que l\'aplicación unvie mensaxes SMS, lo que pue xenerar cargos inesperaos. Les aplicaciones malintencionaes puen causate gastos imprevistos al unviar mensaxes ensin la to confirmación. + + lleer los tos mensaxes de testu (SMS o MMS) + + Permite que l\'aplicación llea mensaxes SMS almacenaos na tablet o na tarxeta SIM. L\'aplicación pue usar esti permisu pa lleer tolos mensaxes SMS, independientemente de cuál seya\'l so conteníu o\'l so nivel de confidencialidá. + + Permite que l\'app llea mensaxes SMS + na TV o na tarxeta SIM. Esta opción permite que l\'app llea tolos + mensaxes SMS, independientemente del conteníu o de la confidencialidá. + + Permite que l\'aplicación llea mensaxes SMS almacenaos nel teléfonu o na tarxeta SIM. L\'aplicación pue usar esti permisu pa lleer tolos mensaxes SMS, independientemente de cuál seya\'l so conteníu o\'l so nivel de confidencialidá. + + recibir mensaxes de testu (WAP) + + Permite que l\'aplicación reciba y procese mensaxes WAP, lo que significa que podría usar esti permisu pa remanar o desaniciar mensaxes unviaos al usuariu ensin amosá-ylos. + + recuperar aplicaciones n\'execución + + Permite que l\'aplicación recupere información sobre xeres que se tán executando nesi momentu o que s\'executaren de recién. L\'aplicación pue usar esti permisu pa descubrir cuáles son les aplicaciones que s\'usen nel preséu. + + remanar perfiles y propietariu del preséu + + Permite que les apps configuren los perfiles de propietarios y el propietariu del preséu. + + reorganizar aplicaciones n\'execución + + Permite que l\'aplicación mueva xeres a segundu o a primer planu. L\'aplicación pue usar esti permisu pa facer estos movimientos ensin que-y lo indique l\'usuariu. + + habilitar mou coche + + Permite que l\'aplicación habilite\'l mou coche. + + zarrar otres aplicaciones + + Esti permisu autoriza a l\'aplicación a torgar procesos en segundu planu d\'otres aplicaciones y pue facer, poro, qu\'eses aplicaciones dexen d\'executase. + + amosar sobre otres aplicaciones + + Permite que l\'aplicación escriba sobre otres aplicaciones o en partes d\'interfaz d\'usuariu. Puen interferir col usu de la interfaz en cualquier aplicación o modificar lo que crees que s\'amuesa n\'otres aplicaciones. + + facer que l\'aplicación s\'execute siempre + + Permite que l\'aplicación faiga que dalgunes de les sos partes se caltengan na memoria. Esto pue llendar la cantidá de memoria disponible pa otres aplicaciones y ralentizar la tablet. + + Permite que l\'aplicación faiga que dalgunes de les sos partes se caltengan na memoria. Esto pue llendar la cantidá de memoria disponible pa otres aplicaciones y ralentizar el teléfonu. + + medir l\'espaciu d\'almacenamientu de l\'aplicación + + Permite que l\'aplicación recupere\'l so códigu, los datos y los tamaños de caché. + + modificar los axustes del sistema + + Permite que l\'aplicación modifique los datos de configuración del sistema. Les aplicaciones malintencionaes puen dañar la configuración del sistema. + + executase al entamu + + Permite que l\'aplicación s\'execute automáticamente una vegada que\'l sistema s\'anicie completamente. Esto pue facer que la tablet tarde más n\'aniciase y permite que l\'aplicación ralentice\'l funcionamientu global del preséu. + + + Permite que l\'aplicación s\'execute automáticamente una vegada que\'l sistema s\'anicie completamente. Esto pue facer que\'l teléfonu tarde más n\'aniciase y pue permitir que l\'aplicación ralentice\'l funcionamientu global del preséu. + + unviar emisión persistente + + Permite que l\'aplicación unvie emisiones que permanecen nel preséu una vegada que la emisión finó. Un usu escesivu podría ralentizar la tablet o tornala inestable al facer qu\'use muncha memoria. + + + Permite que l\'aplicación unvie emisiones que permanecen nel preséu una vegada que la emisión finó. Un usu escesivu podría ralentizar el teléfonu o tornalu inestable al facer qu\'use muncha memoria. + + consultar los tos contautos + + Permite que l\'aplicación consulte información sobre contautos almacenaos na tablet, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Esti permisu permite guardar los datos de los contautos, y les aplicaciones malintencionaes puen usalu pa compartir datos de contautos del usuariu ensin el so consentimientu. + + + Permite que l\'aplicación consulte información sobre contautos almacenaos nel teléfonu, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Esti permisu permite guardar los datos de los contautos, y les aplicaciones malintencionaes puen usalu pa compartir datos de contautos del usuariu ensin el so consentimientu. + + modificar los tos contautos + + Permite que l\'aplicación modifique los datos de los contautos almacenaos na tablet, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Les aplicaciones puen usar esti permisu pa desaniciar datos de contautos. + + + Permite que l\'aplicación modifique los datos de los contautos almacenaos nel teléfonu, incluyida la frecuencia cola que los llamesti, unviasti correos o tuvisti en contautu con ellos d\'otru mou. Les aplicaciones puen usar esti permisu pa desaniciar datos de contautos. + + lleer el rexistru de llamaes + + Permite que l\'aplicación consulte\'l rexistru de llamaes de la tablet, incluyíos datos sobre llamaes entrantes y salientes. Esti permisu permite guardar los datos del rexistru de llamaes, y les aplicaciones malintencionaes puen usalo pa compartir datos del rexistru de llamaes ensin el consentimientu del usuariu. + + + Permite que l\'aplicación consulte\'l rexistru de llamaes del teléfonu, incluyíos datos sobre llamaes entrantes y salientes. Esti permisu permite guardar los datos del rexistru de llamaes, y les aplicaciones malintencionaes puen usalo pa compartir datos del rexistru de llamaes ensin el consentimientu del usuariu. + + escribir nel rexistru de llamaes + + Permite que l\'aplicación modifique\'l rexistru de llamaes de la tablet, incluyíos datos sobre llamaes entrantes y salientes. Les aplicaciones malintencionaes puen usar esti permisu pa desaniciar o modificar el rexistru de llamaes. + + + Permite que l\'aplicación modifique\'l rexistru de llamaes del teléfonu, incluyíos datos sobre llamaes entrantes y salientes. Les aplicaciones malintencionaes puen usar esti permisu pa desaniciar o modificar el rexistru de llamaes. + + acceder a sensores corporales (como mon. frec. card) + + + + lleer eventos de calendariu ya información confidencial + + Permite que l\'aplicación consulte tolos eventos de calendariu almacenaos na tablet, incluyíos los de collacios y compañeros de trabayu. L\'aplicación pue usar esti permisu pa compartir o guardar datos del calendariu del usuariu ensin tener en cuenta si son privaos o confidenciales. + + + Permite que l\'aplicación consulte tolos eventos de calendariu almacenaos nel teléfonu, incluyíos los de collacios y compañeros de trabayu. L\'aplicación pue usar esti permisu pa compartir o guardar datos del calendariu del usuariu ensin tener en cuenta si son privaos o confidenciales. + + amestar o modificar eventos de calendariu y unviar mensaxes a los invitaos ensin el consentimientu de los propietarios + + + + + acceder a comandos de fornidor de llocalización adicional + + Permite a l\'app acceder + a comandos estres del fornidor de llocalización. Esto pue permiti-y interferir + nel funcionamientu del GPS o d\'otres fontes de llocalización. + + accesu a llocalización precisa + (basada en rede y GPS) + + Permite que l\'aplicación obtenga la to llocalización precisa per duana del Sistema de posicionamientu global (GPS) o fontes de llocalización de rede, como torres de telefonía y redes Wi-Fi. Estos servicios de llocalización tienen de tar activaos y disponibles pa que l\'aplicación pueda usalos. Les aplicaciones puen usar esti permisu pa determinar la to llocalización y ye dable que\'l preséu consuma más batería. + + accesu a llocalización aproximada + (basada en rede) + + Permite que l\'aplicación obtenga la to llocalización aproximada. Esta llocalización remanez de los servicios de llocalización qu\'usen fontes de llocalización de rede, como torres de telefonía y redes Wi-Fi. Estos servicios de llocalización tienen de tar activaos y disponibles pa que l\'aplicación pueda usalos. Les aplicaciones puen usar esti permisu pa determinar la to llocalización de mou aproximáu. + + camudar la configuración d\'audiu + + Permite que l\'aplicación modifique la configuración d\'audiu global (por exemplu, el volume y l\'altavoz de salida). + + grabar soníu + + Permite que l\'aplicación grabe audiu col micrófonu. L\'aplicación pue usar esti permisu pa grabar audiu en cualquier momentu ensin tener la confirmación del usuariu. + + unviar comandos a la SIM + + Permite que l\'aplicación unvie comandos a la tarxeta SIM. Esti permisu YE MUI PELIGROSU. + + facer semeyes y vídeos + + Permite que l\'aplicación faiga semeyes o grabe vídeos cola cámara. Esti permisu autoriza a l\'aplicación a usar la cámara en cualquier momentu ensin la to confirmación. + + remanar la vibración + + Permite que l\'aplicación remane la función de vibración. + + remanar llinterna + + Permite que l\'aplicación remane la función de llinterna. + + llamar direutamente a númberos de teléfonu + + Permite que l\'aplicación faiga llamaes ensin intervención del usuariu, lo que pue dar llugar a llamaes o cargos inesperaos. Les aplicaciones nun puen usar este serviciu pa facer llamaes a númberos d\'emerxencia, pero les aplicaciones malintencionaes puen causate gastos imprevistos al facer llamaes ensin la to confirmación. + + acceder al serviciu IMS pa facer llamaes + + Permite a l\'app usar el serviciu IMS pa facer llamaes ensin la to intervención. + + consultar la identidá y l\'estáu del teléfonu + + Permite que l\'aplicación acceda a les funciones de teléfonu del preséu. L\'aplicación pue usar esti permisu pa descubrir identificadores de preseos y númberos de teléfonu, pa saber si una llamada ta activa y pa conocer el númberu remotu col que s\'afitó conexón per aciu d\'una llamada. + + evitar que la tablet entre en mou de suspensión + + + evitar que\'l teléfonu entre en mou de suspensión + + Permite que l\'aplicación impida que la tablet entre en mou de suspensión. + + + Permite que l\'aplicación impida que\'l teléfonu entre en mou de suspensión. + + tresmitir infrabermeyos + + Permite que l\'aplicación utilice\'l tresmisor d\'infrabermeyos de la tablet. + + + Permite que l\'aplicación utilice\'l tresmisor d\'infrabermeyos del teléfonu. + + afitar fondu de pantalla + + Permite que l\'aplicación afite\'l fondu de pantalla del sistema. + + axustar el tamañu del fondu de pantalla + + Permite que l\'aplicación afite\'l tamañu del fondu de pantalla del sistema. + + afitar estaya horaria + + Permite que l\'aplicación camude la estaya horaria de la tablet. + + + Permite que l\'aplicación camude la estaya horaria del teléfonu. + + guetar cuentes nel preséu + + Permite que l\'aplicación obtenga una llista de cuentes reconocíes po la tablet, ente les que puen incluyise les cuentes creaes poles aplicaciones que tengas instalaes. + + + Permite que l\'aplicación obtenga una llista de cuentes reconocíes pol teléfonu, ente les que puen incluyise les cuentes creaes poles aplicaciones que tengas instalaes. + + ver conexones de rede + + Permite que l\'aplicación vea información sobre conexones de rede (por exemplu, qué redes esisten y tán coneutaes). + + tener accesu completu a rede + + Permite que l\'aplicación cree sockets de rede y use protocolos de rede personalizaos. El restolador web y otres aplicaciones proporcionen los medios necesarios pal unviu de datos a Internet, polo que nun fai falta usar esti permisu pa eso. + + cambiar la coneutividá de rede + + Permite que l\'aplicación modifique l\'estáu de la coneutividá de rede. + + cambiar coneutividá d\'anclaxe a rede + + Permite que l\'aplicación cambie l\'estáu de la coneutividá de rede d\'anclaxe. + + ver conexones Wi-Fi + + Permite que l\'aplicación vea información sobre conexones a redes Wi-Fi (por exemplu, si ta habilitada la conexón Wi-Fi y el nome de los preseos Wi-Fi coneutaos). + + coneutase a redes Wi-Fi y desconeutase + + Permite que l\'aplicación se coneute a puntos d\'accesu Wi-Fi y se desconeute d\'ellos y que faiga cambeos na configuración de redes Wi-Fi del preséu. + + permitir receición multidifusión Wi-Fi + + Permite que l\'aplicación reciba paquetes unviaos a tolos preseos d\'una rede Wi-Fi qu\'usen direiciones de multidifusión, non sólo a la tablet. Utiliza más batería que\'l mou de non multidifusión. + + Permite que l\'aplicación reciba paquetes unviaos a tolos preseos d\'una rede Wi-Fi que utilicen direiciones de multidifusión, non sólo al teléfonu. Utiliza más batería que\'l mou de non multidifusión. + + acceder a los axustes de Bluetooth + + Permite que l\'aplicación configure la tablet Bluetooth llocal y que deteute preseos remotos y s\'emparexe con ellos. + + + Permite que l\'aplicación configure\'l teléfonu Bluetooth local y que deteute preseos remotos y s\'emparexe con ellos. + coneutase a WiMAX y desconeutase d\'esta red + Permite que l\'aplicación determine si ta habilitada la conexón WiMAX y obtenga información sobre les redes WiMAX que tán coneutaes. + camudar estáu WiMAX + Permite que l\'aplicación coneute la tablet a redes WiMAX y la desconeute d\'elles. + Permite que l\'aplicación coneute\'l teléfonu a redes WiMAX y lu desconeute d\'elles. + + enllazar con preseos Bluetooth + + Permite que l\'aplicación acceda a la configuración de Bluetooth de la tablet y qu\'afite y aceute conexones colos preseos sincronizaos. + + + Permite que l\'aplicación acceda a la configuración de Bluetooth del teléfonu y qu\'afite y aceute conexones colos preseos sincronizaos. + + remanar Comunicación de campu cercanu (NFC) + + Permite que l\'aplicación se comunique con llectores, tarxetes y etiquetes de Comunicación de campu cercanu (NFC). + + inhabilitar el bloquéu de pantalla + + Permite que l\'aplicación inhabilite\'l bloquéu del tecláu y cualquier proteición con contraseña asociada. Por exemplu, el teléfonu pue inhabilitar el bloquéu del tecláu cuando se recibe una llamada telefónica y volver a habilitalu cuando fina la llamada. + + remanar hardware de buelgues dixitales + + Permite que l\'app emplegue métodos p\'amestar y desaniciar plantíes de buelgues dixitales pal so usu. + + Usar hardware de buelgues dixitales + + Permite que l\'app use\'l hardware de buelgues dixitales pa facer l\'autenticación + + La buelga dixital deteutóse parcialmente. Vuelvi a intentalo. + + Nun pudo procesase la buelga dixital. Vuelvi intentalo. + + El sensor de buelgues dixitales ta suciu. Llimpia\'l sensor y vuelvi intentalo. + + Movisti\'l deu enforma rápido. Vuelvi intentalo. + + Movisti\'l deu mui lento. Vuelvi intentalo. + + + + + El hardware pa buelgues dixitales nun ta disponible. + + Nun pue atroxase la buelga dixital. Desanicia una de les esistentes. + + Finó\'l tiempu d\'espera pa la buelga dixital. Vuelvi intentalo. + + Encaboxóse la operación de buelga dixital. + + Milenta intentos. Volvi tentalo más sero. + + Vuelvi intentalo. + + Deu %d + + + + + Iconu de buelga + + lleer la configuración de sincronización + + Permite que l\'aplicación consulte la configuración de sincronización d\'una cuenta. L\'aplicación pue usar esti permisu, por exemplu, pa determinar si l\'aplicación Contautos ta sincronizada con una cuenta. + + activar y desactivar la sincronización + + Permite que l\'aplicación modifique la configuración de sincronización d\'una cuenta. Esti permisu pue usase, por exemplu, p\'habilitar la sincronización de l\'aplicación Contautos con una cuenta. + + lleer estadístiques de sincronización + + Permite que l\'aplicación consulte les estadístiques de sincronización d\'una cuenta (por exemplu, l\'historial d\'eventos sincronizaos y la cantidá de datos sincronizaos). + + consultar el conteníu del almacenamientu USB + + consultar el conteníu de la tarxeta SD + + Permite que l\'aplicación llea\'l conteníu del almacenamientu USB. + + Permite que l\'aplicación llea\'l conteníu de la tarxeta SD. + + editar o desaniciar conteníu de USB + + modificar o desaniciar el conteníu de la tarxeta SD + + Permite escribir nel almacenamientu USB. + + Permite que l\'aplicación escriba na tarxeta SD. + + facer/recibir llamaes SIP + + Permite a la app facer y recibir llamaes SIP. + + + + + + + + interactuar cola pantalla de llamada + + Permite que l\'aplicación remane cómo y cuándo apaez la pantalla de llamada. + + interactuar colos servicios de telefonía + + Permite a la app interactuar colos servicios de telefonía pa facer/recibir llamaes. + + ufrir una esperiencia d\'usuariu de llamada + + Permite a la app ufrir una esperiencia d\'usuariu de llamada + + lleer usu de rede históricu + + Permite que l\'aplicación consulte l\'usu de rede históricu de redes y d\'aplicaciones específiques. + + alministrar política de rede + + Permite que l\'aplicación alministre polítiques de rede y defina regles específiques de l\'aplicación. + + modificar cálculu d\'usu de rede + + Permite que l\'aplicación modifique cómo se rexistra l\'usu de rede en rellación coles aplicaciones. Les aplicaciones normales nun tendríen d\'usar esti permisu. + + acceder a les notificaciones + + Permite que l\'aplicación recupere, desamine y desanicie notificaciones, incluyíes les qu\'espublizaron otres aplicaciones. + + enllazar con un serviciu de deteutor de notificaciones + + Permite enllazar cola interfaz de nivel superior d\'un serviciu de deteutor de notificaciones. Nun tendría de ser necesario pa les aplicaciones normales. + + enllazar con un serviciu de fornidor de condiciones + + Permite enllazar cola interfaz de nivel superior d\'un serviciu de fornidor de condiciones. Nun tendría de ser necesario pa les aplicaciones normales. + + enllazar con un serviciu de curiapantalles + + Permite enllazar cola interfaz de nivel superior d\'un serviciu de curiapantalles. Nun tendría de ser necesario pa les aplicaciones normales. + + executar l\'aplicación de configuración proporcionada pol operador + + Permite executar l\'aplicación de configuración proporcionada pol operador. Nun tendría de ser necesario p\'aplicaciones normales. + + deteutar cambeos nel estáu de la rede + + Permite qu\'una aplicación deteute cambeos nel estáu de la rede. Nun tendría de ser necesario p\'aplicaciones normales. + camudar la calibración del preséu d\'entrada + + Permite a la app camudar los parámetros de calibración de la pantalla táctil. Nun tendría de ser necesario pa les aplicaciones normales. + + acceder a certificaos DRM + + Permite a la app dar y usar certificaos DRM. Nun tendría de ser necesario pa les aplicaciones normales. + recibir estáu de tresferencies d\'Android Beam + Permite qu\'esta app reciba información tocante a les tresferencies actuales d\'Android Beam + + desaniciar certificaos DRM + + Permite a la app desaniciar certificaos DRM. Nun tendría de ser necesario pa les aplicaciones normales. + + + + enllazar con servicios de fornidores + + Permite al propietariu enllazar con servicios de fornidores. Les aplicaciones normales nun tendríen de precisar esti permisu. + + Accesu a la función Nun molestar + + Permite que l\'app llea y modifique la configuración de la función Nun molestar. + + + Establecimientu de regles de contraseña + + Permite remanar la llonxitú y los caráuteres permitíos nes contraseñes y los PIN pal bloquéu de pantalla. + + Control d\'intentos de bloquéu de pantalla + + Remana\'l númberu de contraseñes incorreutes introducíes al desbloquiar la pantalla y bloquia la tablet o desanicia tolos datos si s\'inxerten munches contraseñes incorreutes. + + + Remana\'l númberu de contraseñes incorreutes introducíes al desbloquiar la pantalla y bloquia\'l teléfonu o desanicia tolos datos si s\'inxerten munches contraseñes incorreutes. + Remana\'l númberu de contraseñes incorreutes + introducíes al desbloquiar la pantalla y bloquia la tablet o desanicia tolos datos + si s\'inxerten munches contraseñes incorreutes. + Remana\'l númberu de contraseñes incorreutes + introducíes al desbloquiar la pantalla y bloquia la TV o desanicia tolos datos + si s\'inxerten munches contraseñes incorreutes. + Remana\'l númberu de contraseñes incorreutes + introducíes al desbloquiar la pantalla y bloquia\'l tefnu o desanicia tolos datos + si s\'inxerten munches contraseñes incorreutes. + + Camudar el bloquéu de pantalla + + Camudar el bloquéu de pantalla + + Bloquéu de pantalla + + Remanar cómo y cuándo se bloquia la pantalla + + Desaniciar tolos datos + + Desaniciar los datos de la tablet ensin avisar, reafitando los datos de fábrica + + + Desaniciar los datos del teléfonu ensin avisar, reafitando los datos de fábrica + + Desaniciar los datos del usuariu + + Permite desaniciar los datos del usuariu nesta tablet ensin avisu previu. + + Permite desaniciar los datos del usuariu nesta TV ensin avisu previu. + + Permite desaniciar los datos del usuariu nesti tfnu ensin avisu previu. + + Definir el sirvidor proxy global + + Configura\'l proxy global de preséu que va usase + mentanto s\'habilita la política. Namái el propietariu del preséu pue configurar el proxy global. + + Config. vencimientu contraseña + + Permite modificar la frecuencia cola que se camuda la contraseña, el PIN o\'l patrón de bloquéu de pantalla. + + Cifráu d\'almacenamientu + + Desixe que se cifren los datos de l\'aplicación almacenaos. + + Inhabilitar cámares + + Evitar l\'usu de les cámares del preséu + + Deshabilitar func. del bloquéu + + Evita l\'usu de dalgunes funciones de bloquéu de pantalla. + + + + + Casa + Móvil + Trabayu + Fax del trabayu + Fax de casa + Busca + Otru + Personalizar + + + + + + Casa + Trabayu + Otra + Personalizar + + + + + + Casa + Trabayu + Otra + Personalizar + + + + + + Casa + Trabayu + Otru + Personalizar + + + + + + Trabayu + Otra + Personalizar + + + + + + AIM + Windows Live + Yahoo! + Skype + QQ + Google Talk + ICQ + Jabber + + + Personalizáu + + Casa + + Móvil + + Trabayu + + Fax del trabayu + + Fax de casa + + Busca + + Otru + + Devolución de llamada + + Coche + + Teléfonu principal de la empresa + + RDSI + + Principal + + Otru fax + + Señal móvil + + Télex + + TTY TDD + + Móvil del trabayu + + Busca del trabayu + + Asistente + + MMS + + Personalizáu + + Cumpleaños + + Aniversariu + + Otros + + Personalizáu + + Casa + + Trabayu + + Otru + + Móvil + + Personalizada + + Casa + + Trabayu + + Otro + + Personalizáu + + Casa + + Trabayu + + Otru + + Personalizada + + AIM + + Windows Live + + Yahoo! + + Skype + + QQ + + Hangouts + + ICQ + + Jabber + + NetMeeting + + Trabayu + + Otra + + Personalizada + + Personalizada + + Asistente + + Hermanu + + Fíu/a + + Pareya de fechu + + Padre + + Collaciu/a + + Xefe + + Madre + + Padre/madre + + Pareya + + Recomendáu por + + Pariente + + Hermana + + Cónyugue + + Personalizada + + Casa + + Trabayu + + Otru + + Nun s\'atopó nenguna aplicación pa ver esti contautu. + + Introduz el códigu PIN. + + Introduz el códigu PUK y un nuevu códigu PIN. + + Códigu PUK + + Nuevu códigu PIN + + Toca pa introducir contraseña + + Introduz la contraseña pa desbloquiar. + + Inxerta\'l códigu PIN pa desbloquiar. + + Códigu PIN incorreutu + + Pa desbloquiar el teléfonu, primi la tecla de menú y, a darréu, primi 0. + + Númberu d\'emerxencia + + + + Ensin serviciu + + Pantalla bloquiada + + Primi la tecla de menú pa desbloquiar el teléfonu o facer una llamada d\'emerxencia. + + Primi la tecla de menú pa desbloquiar la pantalla. + + Dibuxar patrón de desbloquéu + + Emerxencia + + Volver a llamada + + Correutu + + Vuelvi a intentalo + + Vuelvi a intentalo + + Perpasóse\'l númberu máximu d\'intentos de desbloquéu facial. + + Falta la tarxeta SIM. + + Nun s\'inxertó nenguna tarxeta SIM na tablet. + + + Nun s\'inxertó nenguna tarxeta SIM nel teléfonu. + + Inxerta una tarxeta SIM. + + Falta la tarxeta SIM o nun pue lleese. Introduz una tarxeta SIM. + + Tarxeta SIM inutilizable + + La tarxeta SIM inhabilitóse permanentemente.\n Pa obtener otra tarxeta SIM, ponte en contautu col tu fornidor de servicios de telefonía. + + Pista anterior + + Pista siguiente + + Posar + + Reproducir + + Detener + + Rebobinar + + Avance rápidu + + Namái llamaes d\'emerxencia + + Bloquiada pa la rede + + La tarxeta SIM ta bloquiada col códigu PUK. + + Ver la Guía d\'usuariu o contautar con atención al veceru. + + La tarxeta SIM ta bloquiada. + + Desbloquiando tarxeta SIM\u2026 + + Fixisti %d intentos fallíos de desbloquéu. +\n\nVuelvi intentalo en %d segundos. +     + + Introduxisti una contraseña incorreuta %d vegaes.\n\nInténtalo otra vuelta en %d segundos. +     + + Introduxisti un códigu PIN incorreutu %d vegaes. \n\nInténtalo otra vuelta en %d segundos. + + Fallasti %d vegaes al dibuxar el patrón de desbloquéu. Si falles otres %d vegaes, vas tener d\'usar les tos credenciales d\'accesu de Google pa desbloquiar la tablet.\n\n Inténtalo otra vuelta en %d segundos. + + + Fallasti %d vegaes al dibuxar el patrón de desbloquéu. Si falles otres %d vegaes, vas tender d\'usar les tos credenciales d\'accesu de Google pa desbloquiar el teléfonu.\n\n Inténtalo otra vuelta en %d segundos. + + Intentasti desbloquiar la tablet %d vegaes, pero nun pudisti. Si falles %d vegaes más, van restablecese los datos de fábrica y van perdese tolos datos del usuariu. + + + Intentasti desbloquiar el teléfonu %d vegaes, pero nun pudisti. Si falles %d vegaes más, van restablecese los datos de fábrica y van perdese tolos datos del usuariu. + + Intentasti desbloquiar la tablet %d vegaes, pero nun pudisti. Van restablecese los datos de fábrica del preséu. + + + Intentasti desbloquiar el teléfonu %d vegaes, pero nun pudisti. Van restablecese los datos de fábrica del preséu. + + Espera %d segundos y vuelvi a intentalo. + + ¿Escaecisti\'l patrón? + + Desbloquéu de cuenta + + Demasiaos intentos incorreutos de creación del patrón + + Pa desbloquiar el teléfonu, anicia sesión cola to cuenta de Google. + + Nome d\'usuariu (corréu electrónicu) + + Contraseña + + Aniciar sesión + + Nome d\'usuariu o contraseña non válidu + + Si escaecisti\'l to nome d\'usuariu o contraseña,\nentra na páxina \"google.com/accounts/recovery". + + Comprobando\u2026 + + Desbloquiar + + Activar soníu + + Desactivar soníu + + Patrón aniciáu + + Patrón desaniciáu + + Amestóse una caxella. + + + Amestóse la caxella %1$s + + Patrón completáu + + Área de patrón + + %1$s. Widget %2$d de %3$d + + Amestar widget + + Baleru + + Área de desbloquéu ampliada + + Área de desbloquéu contrayida + + Widget de %1$s + + Seleutor d\'usuarios + + Estáu + + Cámara + + Controles multimedia + + Empezó a cambiase l\'orde de los widgets. + + Finó de cambiase l\'orde de los widgets. + + Widget %1$s desaniciáu + + Ampliar área de desbloquéu + + Desbloquéu eslizando\'l deu + + Desbloquéu por patrón + + Desbloquéu facial + + Desbloquéu por PIN + + Desbloquéu por contraseña + + Área de patrón + + Área pa eslizar + + + + \?123 + + ABC + + ALT + + caráuter + + pallabra + + enllaz + + llinia + + "%-l%P" + + "%-l%p" + + Fallu na prueba de fábrica + + L\'aición FACTORY_TEST namái ye compatible colos paquetes instalaos en /system/app. + + Nun s\'atopó nengún paquete que proporcione l\'aición FACTORY_TEST. + + Reaniciar + + + + La páxina \"%s\" diz: + + JavaScript + + Confirmar navegación + + Colar d\'esta páxina + + Permanecer nesta páxina + + %s\n\n¿De xuru que quies colar d\'esta páxina? + + Confirmar + + Suxerencia: toca dos vegaes p\'ampliar o amenorgar el conteníu. + + Autocompletar + + Configurar Autocompletar + + \u0020 + + $1$2$3 + + , + + $1$2$3 + + attention|attn + + province|region|other|provincia|bairro|suburb + + company|business|organization|organisation|department|firma|firmenname|empresa|societe|société|ragione.?sociale|会社|название.?компании|单位|公司 + + address.?line|address1|addr1|street|strasse|straße|hausnummer|housenumber|house.?name|direccion|dirección|adresse|indirizzo|住所1|morada|endereço|Адрес|地址 + + address|adresse|indirizzo|住所|地址 + + address.?line2|address2|addr2|street|suite|unit|adresszusatz|ergänzende.?angaben|direccion2|colonia|adicional|addresssuppl|complementnom|appartement|indirizzo2|住所2 + + address.?line3|address3|addr3|street|line3|municipio|batiment|residence|indirizzo3 + + country|location|国|国家 + + zip|postal|post code|pcode|^1z$|postleitzahl|cp|cdp|cap|郵便番号|codigo|codpos|cep|Почтовый.?Индекс|邮政编码|邮编|郵遞區號 + + zip|^-$|post2|codpos2 + + city|town|ort|stadt|suburb|ciudad|provincia|localidad|poblacion|ville|commune|localita|市区町村|cidade|Город|市|分區 + + state|county|region|province|land|county|principality|都道府県|estado|provincia|область|省|地區 + + same as + + use my + + bill + + ship + + e.?mail|メールアドレス|Электронной.?Почты|邮件|邮箱|電郵地址 + + user.?name|user.?id|vollständiger.?name|用户名 + + ^name|full.?name|your.?name|customer.?name|firstandlastname|nombre.*y.*apellidos|^nom|お名前|氏名|^nome|姓名 + + ^name|^nom|^nome + + irst.*name|initials|fname|first$|vorname|nombre|forename|prénom|prenom|名|nome|Имя + + middle.*initial|m\\.i\\.|mi$ + + middle.*name|mname|middle$|apellido.?materno|lastlastname + + last.*name|lname|surname|last$|nachname|apellidos|famille|^nom|cognome|姓|morada|apelidos|surename|sobrenome|Фамилия + + phone|telefonnummer|telefono|teléfonu|telfixe|電話|telefone|telemovel|телефон|电话 + + area.*code|acode|area + + prefix|preselection|ddd + + sufixu + + ext|ramal + + card.?holder|name.?on.?card|ccname|owner|karteninhaber|nombre.*tarjeta|nom.*carte|nome.*cart|名前|Имя.*карты|信用卡开户名|开户名|持卡人姓名|持卡人姓名 + + nome + + verification|card identification|cvn|security code|cvv code|cvc + + number|card.?#|card.?no|ccnum|nummer|credito|numero|número|numéro|カード番号|Номер.*карты|信用卡号|信用卡号码|信用卡卡號 + + expir|exp.*month|exp.*date|ccmonth|gueltig|gültig|monat|fecha|date.*exp|scadenza|有効期限|validade|Срок действия карты|月 + + exp|^/|year|ablaufdatum|gueltig|gültig|yahr|fecha|scadenza|有効期限|validade|Срок действия карты|年|有效期 + + ^card + + fax|télécopie|telecopie|ファックス|факс|传真|傳真 + + country.*code|ccode|_cc + + ^\\($ + + ^-$|^\\)$ + + ^-$ + + Provincia + + Códigu postal + + Estáu + + Códigu postal + + Conceyu + + Islla + + Distritu + + Departamentu + + Prefectura + + Distritu + + Área + + Emiratu + + consultar l\'historial y marcadores web + + Permite que l\'aplicación consulte l\'historial de toles URL visitaes pol restolador web y tolos sos marcadores. Nota: esti permisu nun puen usalu restoladores esternos nin otres aplicaciones que tengan funciones de navegación per Internet. + + escribir nel historial y nos marcadores web + + Permite que l\'app + modifique l\'historial o los marcadores del restolador almacenaos na + tablet. L\'aplicación pue usar esti permisu pa desaniciar o modificar datos + del restolador. Nota: Esti permisu nun pue usase por restoladores + esternos nin otres apps que tengan funciones de navegación per Internet. + + + Permite que l\'app + modifique l\'historial o los marcadores del restolador almacenaos nel + tefnu. L\'aplicación pue usar esti permisu pa desaniciar o modificar datos + del restolador. Nota: Esti permisu nun pue usase por restoladores + esternos nin otres apps que tengan funciones de navegación per Internet. + + afitar una alarma + + Permite que l\'app afite una alarma + nuna app instalada d\'alarmes. Ye dable que dalgunes apps + d\'alarma nun incluyan esta función. + + amestar buzón de voz + + Permite que l\'aplicación amieste mensaxes a la bandexa d\'entrada del buzón de voz. + + modificar los permisos de llocalización xeográfica del restolador web + + Permite que l\'aplicación modifique los permisos de llocalización xeográfica del restolador web. Les aplicaciones malintencionaes puen usar esti permisu p\'autorizar l\'unviu d\'información sobre la llocalización a sitios web arbitrarios. + + ¿Quies que\'l restolador web recuerde esta contraseña? + + Agora non + + Recordar + + Enxamás + + Nun tienes permisu p\'abrir esta páxina. + + Testu copiáu al cartafueyu. + + Más + + MENU+ + + espaciu + + intro + + desaniciar + + + + Guetar + + + Guetar + + Consulta + + Desaniciar consulta + + Unviar consulta + + Guetar por voz + + ¿Habilitar esploración táctil? + + %1$s quier habilitar la esploración táctil. Cuando esta función tea activada, vas poder escuchar o ver descripciones del conteníu esbilláu o usar xestos pa interactuar cola tablet. + + %1$s quier habilitar la esploración táctil. Cuando esta función tea activada, vas poder escuchar o ver descripciones del conteníu esbilláu o usar xestos pa interactuar col teléfonu. + + hai un mes + + hai más d\'un mes + + + Últimu %d día + Últimos %d díes + + + el mes pasáu + + anterior + + el %s + + a les %s + + en %s + + día + + díes + + hora + + hores + + min + + minutos + + segundu + + segundos + + selmana + + selmanes + + añu + + años + + + 1 segundu + %d segundos + + + + 1 minutu + %d minutos + + + + 1 hora + %d hores + + + Incidencies col videu + + Esti videu nun pue tresmitise al preséu. + + Nun pue reproducise\'l videu. + + Aceutar + + "%1$s, %2$s" + + "meudía" + + "Meudía" + + "medianueche" + + "Medianueche" + + %1$02d:%2$02d + + %1$d:%2$02d:%3$02d + + Esbillar too + + Cortar + + Copiar + + Apegar + + Sustituyir\u2026 + + Desaniciar + + Copiar URL + + Esbillar testu + + Seleición de testu + + Amestar al diccionariu + + Desaniciar + + Métodu d\'introducción de testu + + Aiciones de testu + + Queda poco espaciu + + Ye dable que dalgunes funciones del sistema nun funcionen. + + Nun hai espaciu bastante pal sistema. Comprueba qu\'heba 250 MB llibres y reanicia\'l preséu. + + %1$s ta executándose + + Toca pa obtener más información o pa detener l\'aplicación. + + Aceutar + + Encaboxar + + Aceutar + + Encaboxar + + Atención + + Cargando\u2026 + + + + NON + + Completar aición usando + + Completar aición usando %1$s + + Abrir con + + Abrir con %1$s + + Editar con + + Editar con %1$s + + Compartir con + + Compartir con %1$s + + Esbillar una aplicación na pantalla d\'aniciu + + Usar %1$s como aplicación d\'aniciu + + Usar siempre pa esta aición + + Usar una app distinta + + Pa desaniciar los valores predeterminaos, vete a Axustes del sistema > Aplicaciones > Descargaes. + + Esbilla una aición + + Seleicionar una aplicación pal preséu USB + + Nenguna aplicación pue facer esta aición. + + + + Detúvose l\'aplicación %1$s. + + Detúvose\'l procesu %1$s. + + + + L\'aplicación %2$s nun respuende.\n\n¿Quies zarrala? + + L\'actividá %1$s nun respuende.\n\n¿Quies zarrala? + + L\'aplicación %1$s nun respuende. ¿Quies zarrala? + + El procesu %1$s nun respuende.\n\n¿Quies zarralu? + + Aceutar + + Informar + + Esperar + + La páxina nun respuende.\n\n¿Quies zarrala? + + Aplicación redireicionada + + %1$s ta executándose. + + Primeramente, anicióse l\'aplicación %1$s. + + Escala + + Amosar siempre + + Pa volver a habilitar esta opción, vete a Axustes > Aplicaciones > Descargaes. + + L\'aplicación %1$s (procesu %2$s) infrinxó la política StrictMode autoaplicable. + + El procesu %1$s infrinxó la política StrictMode autoaplicable. + + Anovando Android + + + Optimizando almacenamientu. + + Optimizando aplicación %1$d de %2$d\u2026 + + Preparando %1$s. + + Aniciando aplicaciones + + Finando arranque\u2026 + + %1$s n\'execución + + Toca esta opción pa cambiar a l\'aplicación. + + ¿Cambiar aplicaciones? + + Ta executándose otra aplicación. P\'aniciar una aplicación nueva, has detenela. + Volver a %1$s + Nun aniciar la nueva aplicación + Aniciar %1$s + Detener l\'aplicación anterior ensin guardar + + %1$s perpasó la llende de + memoria + + Recopilóse\'l volcáu de pila; + toca pa compartir + + ¿Compartir volcáu de pila? + + El procesu %1$s perpasó la llende + de memoria de procesu de %2$s. Hai un volcáu de pila disponible + pa que puedas compartilu col programador. Curiáu, esti volcáu de pila + pue contener información personal a la que pue acceder l\'app. + + Seleiciona una aición pal testu + + Volume del timbre + + Volume multimedia + + Reproduciendo a traviés de Bluetooth + + Tonu de silenciu afitáu + + Volume de la llamada + + Volume de la llamada de Bluetooth + + Volume d\'alarma + + Volume de notificaciones + + Volume + + Volume de Bluetooth + + Volume del tonu + + Volume de llamada + + Volume multimedia + + Volume de notificaciones + + + + Tonu predetermináu + + Tonu predetermináu (%1$s) + + Nengún + + Tonos + + Tonu desconocíu + + + Rede Wi-Fi disponible + Redes Wi-Fi disponibles + + + + Rede Wi-Fi abierta disponible + Redes Wi-Fi abiertes disponibles + + + Coneutase a una rede Wi-Fi. + + Acceder a la rede + + %1$s + + La rede Wi-Fi nun tiene accesu a Internet + + Toca pa opciones + + Nun pudo afitase conexón cola rede Wi-Fi. + + tien una conexón inestable a Internet. + + + + ¿Permitir conexón? + + L\'app %1$s quier coneutase a la rede Wi-Fi %2$s + + Una aplicación + Wi-Fi Direutu + Aniciar Wi-Fi Direct. Va desactivase\'l funcionamientu de la zona o del cliente Wi-Fi. + Nun pudo aniciase Wi-Fi Direct. + Wi-Fi Direct activáu + Toca p\'acceder a Axustes + Aceutar + Refugar + Invitación unviada + Invitación pa coneutase + De: + Pa: + Escribi\'l PIN solicitáu: + PIN: + La tablet va desconeutase temporalmente de la rede Wi-Fi mientres teas coneutáu a %1$s + El teléfonu va desconeutase temporalmente de la rede Wi-Fi mientres teas coneutáu a %1$s. + + Inxertar carácter + + + + Unviando mensaxes SMS\u2026 + + <b>%1$s</b> ta unviando un gran númberu de mensaxes SMS. ¿Quies permitir que l\'aplicación siga unviando mensaxes? + + Permitir + + Refugar + + + + <b>%1$s</b> quier unviar un mensaxe a <b>%2$s</b>. + + Esto pue ocasionar cargos na to cuenta móvil. + + Esto va ocasionar cargos na to cuenta móvil. + + Unviar + + Encaboxar + + Recordar opción esbillada + + Pues cambiar esta opción más tarde en Axustes > Aplicaciones. + + Permitir siempre + + Nun permitir enxamás + + + + Tarxeta SIM desaniciada + + La rede móvil nun va tar disponible hasta que reanicies el preséu con una tarxeta SIM válida. + + Fecho + + Tarxeta SIM amestada + + Reanicia\'l preséu p\'acceder a la rede móvil. + + Reaniciar + + + Afitar hora + + Afitar data + + Afitar + + Fecho + + + NUEVU: + + Proporcionáu por %1$s + + Nun fai falta nengún permisu + + ye dable que se cobre por usar l\'aplicación. + + + Almacenamientu USB masivu + + Conexón per USB + + Coneutóse\'l preséu al ordenador per USB. Toca\'l siguiente botón si quies tresferir ficheros ente l\'ordenador y l\'almacenamientu USB del preséu. + + Coneutóse\'l preséu al ordenador per USB. Toca\'l siguiente botón si quies tresferir ficheros ente l\'ordenador y la tarxeta SD del preséu. + + Activar almacenamientu USB + + Hebo un fallu al usar l\'almacenamientu USB como almacenamientu USB masivu. + + Hebo un fallu al usar la tarxeta SD pal almacenamientu USB masivu. + + Conexón per USB + + Toca pa tresferir ficheros + + Desactivar almacenamientu USB + + Toca pa desactivar l\'almacenamientu USB. + + + + L\'almacenamientu USB ta n\'usu + + Enantes de desactivar l\'almacenamientu USB, desactiva l\'almacenamientu USB del preséu Android del ordenador. + + Enantes de desactivar l\'almacenamientu USB, desactiva la tarxeta SD del preséu Android del ordenador. + + Desactivar almacenamientu USB + + Hebo un fallu al desactivar l\'almacenamientu USB. Comprueba que desactivasti\'l host USB, y darréu, vuelvi a intentalo. + + Activar almacenamientu USB + + Si actives l\'almacenamientu USB, van parase dalgunes aplicaciones que tas usando y ye dable que nun tean disponibles hasta que lu desactives. + + Fallu de funcionamientu de USB + + Aceutar + + USB pa cargar + + USB pa tresferir ficheros + + USB pa tresferir semeyes + + USB pa MIDI + + Coneutáu a un accesoriu USB + + Toca pa más opciones. + + Depuración USB coneutada + + Toca pa desactivar la depuración USB. + + + + + + + Cambiar tecláu + + Esbillar teclaos + + Amosar métodu d\'entrada + + Hardware + + Seleiciona un diseñu de tecláu + + Toca pa seleicionar un diseñu de tecláu. + ABCDEFGHIJKLMNOPQRSTUVWXYZ + 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ + candidatos + + + + Tresnando\'l mediu %s + + Verificando fallos + + Deteutóse %s nuevu + + Pa tresferir semeyes y conteníu multimedia + + %s ta dañáu + + %s ta dañáu. Toca pa iguar. + + %s non compatible + + El preséu nun ye compatible con %s. Toca la pantalla pa configuralu nun formatu compatible. + + Desmontóse %s de mou inesperáu. + + Pa evitar perda de datos, desactiva\'l preséu %s enantes d\'estrayelu + + Estráxose %s + + %s estrayíu; inxerta ún nuevu + + Espulsando\'l mediu %s\u2026 + + Nun estrayer + + Configurar + + Espulsar + + Esplorar + + Nun s\'atopa %s + + Volver a inxertar preséu + + Moviendo %s + + Moviendo datos + + Tresferencia completa + + Tresfiriéronse los datos a %s + + Nun pudieron tresferise datos + + Los datos quedaron na llocalización orixinal + + Estrayíu + + Espulsáu + + Comprobando\u2026 + + Llistu + + Namái-llectura + + Nun s\'estraxo de mou seguru + + Toyíu + + Non compatible + + Espulsando\u2026 + + Formatiando\u2026 + + Non inxertáu + + Nun s\'atopó nenguna actividá coincidente. + + route media output + + Permite que l\'aplicación dirixa salides de medios a otros preseos esternos. + + lleer sesiones instalaes + + Permite qu\'una aplicación consulte sesiones d\'instalación pa ver detalles tocante a instalaciones de paquetes activos. + + solicitar paquetes instalaos + + Permite qu\'una app solicite la instalación de paquetes. + + Toca dos vegaes p\'acceder al control de zoom. + + Nun pudo amestase\'l widget. + + Dir + + Guetar + + Unviar + + Siguiente + + Fecho + + Anterior + + Executar + + + + Marcar númberu\ncon %s + + Crear un contautu\na partir de %s + + + + Les siguientes aplicaciones soliciten permisu p\'acceder a la to cuenta agora y nel futuru. + ¿Quies permitir esta solicitú? + Solicitú d\'accesu + Permitir + Refugar + Permisu solicitáu + Permisu solicitáu\npa la cuenta %s + + Tas usando esta app fuera del perfil de trabayu + + Tas usando esta app nel to perfil de trabayu + + Métodu d\'introducción de testu + + Sincronización + + Accesibilidá + + Fondu de pantalla + + Camudar fondu de pantalla + + Deteutor de notificaciones + + Fornidor de condiciones + + + VPN activada + + VPN activada por %s + + Toca p\'alministrar la rede. + + Coneutáu a %s. Toca p\'alministrar la rede. + + Coneutando VPN siempre activada… + + VPN siempre activada coneutada + + Fallu de VPN siempre activada + + Toca pa configurar + + + Esbillar ficheru + + Ficheru non esbilláu + + Restablecer + + Unviar + + + Habilitóse\'l mou coche. + Toca pa salir del mou coche. + + + Anclaxe a rede/Zona Wi-Fi activu + Toca pa configurar + + Atrás + Siguiente + + Saltar + + Nun hai coincidencies. + + Guetar na páxina + + + + Una coincidencia + + %d de %d + + + Listo + + + Desaniciando almacenamientu USB\u2026 + + Desaniciando tarxeta SD\u2026 + + + Compartir + + Guetar + + Guetar na web + + Atopar siguiente + + Atopar anterior + + Solicitú de llocalización de %s + + Solicitú de llocalización + + Solicitú unviada por %1$s (%2$s) + + + + Non + + Perpasóse la llende de desanicios. + + Hai %1$d elementos desaniciaos pa %2$s (cuenta %3$s). ¿Qué quies facer? + + Desaniciar elementos + + Desfacer los desanicios + + Nun facer un res agora + + Esbilla una cuenta + "Amestar una cuenta" + + Amestar cuenta + + + Aumentar + + Amenorgar + + Caltén primíu %s. + + Esliza\'l deu hacia arriba p\'aumentar y hacia abaxo p\'amenorgar. + + + Aumentar minutos + + Amenorgar minutos + + Aumentar hores + + Amenorgar hores + + Afitar p.m. + + Afitar a.m. + + + Aumentar mes + + Amenorgar mes + + Aumentar díes + + Amenorgar díes + + Aumentar añu + + Amenorgar año + + Mes anterior + + Mes siguiente + + + Alt + + Encaboxar + + Desaniciar + + Fecho + + Cambéu de mou + + Mayús + + Intro + + + Esbillar una aplicación + + Nun pudo abrise %s + + + Compartir con + + Compartir con %s + + + "Caltén primíu l'iconu de desbloquéu y eslízalu." + + Esliza\'l deu pa desbloquiar. + + Coneuta un auricular pa escuchar les contraseñes. + + Puntu + + Dir al escritoriu + + Desplazase hacia arriba + + Más opciones + + %1$s, %2$s + + %1$s, %2$s, %3$s + + Almacenamientu internu + + Tarxeta SD + + Tarxeta SD de %s + + Unidá USB + + Unidá USB de %s + + Almacenamientu USB + + Avisu d\'usu de datos + + Toca pa ver l\'usu y axustes. + + Algamóse la llende de datos 2G-3G + + Algamóse la llende de datos 4G + + Algamóse la llende de datos móviles + + Llende de datos Wi-Fi algamada + + Datos posaos restu de ciclu + + Llende de datos 2G-3G perpasada + + Llende de datos 4G perpasada + + Perpasóse llende datos móviles + + Llende de datos Wi-Fi perpasada + + Llende perpasada en %s + + Conexones automátiques restrinxíes + + Toca pa desaniciar la restricción. + + + Certificáu de seguranza + + Esti certificáu ye válidu. + + Emitíu pa: + + Nome común: + + Organización: + + Departamentu: + + Emitíu por: + + Validez: + + Data d\'emisión: + + Data de caducidá: + + Númberu de serie: + + Buelgues dixitales: + + Buelga dixital SHA-256: + + Buelga dixital SHA-1: + + Ver too + + Selecionar actividá + + Compartir con + + ", " + + Unviando\u2026 + + ¿Aniciar el restolador web? + + ¿Aceutar la llamada? + + Siempre + + Namái una vegada + + %1$s nun almites perfiles de trabayu + + Tablet + + + Teléfonu + + Auriculares + + Altavoces de la base + + HDMI + + Sistema + + Audiu Bluetooth + + Pantalla inalámbrica + + Cast + + Coneutar a preséu + + Unviar pantalla a preséu + + Guetando por preseos… + + Axustes + + Desconeutar + + Analizando\u2026 + + Coneutando\u2026 + + Disponible + + Non disponible + + N\'usu + + + Pantalla integrada + + Pantalla HDMI + + Superposición #%1$d + + %1$s: %2$d x %3$d, %4$d dpi + + , seguru + + + ¿Escaecisti\'l patrón? + + El patrón ye incorreutu + + Contraseña incorreuta + + PIN incorreutu + + Inténtalo otra vuelta en %1$d segundos. + + Dibuxa\'l to patrón de desbloquéu. + + Inxerta\'l PIN de la tarxeta SIM. + + Introduz el PIN. + + Escribi la contraseña. + + La tarxeta SIM ta inhabilitada. Pa continuar, inxerta\'l códigu PUK. Si quies obtener más información, ponte en contautu col operador + + Introduz el códigu PIN deseáu + + Confirma\'l códigu PIN + + Desbloquiando tarxeta SIM… + + Códigu PIN incorreutu + + Introduz un códigu PIN con una llonxitú comprendida ente cuatro y ocho díxitos. + + El códigu PUK tien de tener ocho númberos como mínimo. + + Vuelvi a introducir el códigu PUK correutu. Si introduces un códigu incorreutu delles vegaes, va inhabilitase la tarxeta SIM. + + Los códigos PIN nun concasen. + + Abondos intentos incorreutos de crear el patrón + + Pa desbloquiar el teléfonu, anicia sesión cola to cuenta de Google. + + Nome d\'usuariu (corréu-e) + + Contraseña + + Aniciar sesión + + El nome d\'usuariu o la contraseña nun son válidos. + + Si escaecisti\'l nome d\'usuariu o la contraseña,\nvete a la páxina \"google.com/accounts/recovery". + + Comprobando cuenta… + + Punxisti un códigu PIN incorreutu %d vegaes. \n\nVuelvi a intentalo en %d segundos. + + Punxisti una contraseña incorreuta %d vegaes. \n\nVuelvi a intentalo en %d segundos. + Fallasti %d vegaes al dibuxar el patrón de desbloquéu. \n\nVuelvi a intentalo en %d segundos. + + Intentasti desbloquiar la tablet %d vegaes, pero nun pudisti. Si falles otres %d vegaes, van reafitase los datos de fábrica y van perdese tolos datos del usuariu. + + + Intentasti desbloquiar el teléfonu %d vegaes, pero nun pudisti. Si falles otres %d vegaes, van reafitase los datos de fábrica y van perdese tolos datos del usuariu. + + Intentasti desbloquiar la tablet %d vegaes, pero nun pudisti. Van reafitase los datos de fábrica del preséu. + + + Intentasti desbloquiar el teléfonu %d vegaes, pero nun pudisti. Van reafitase los datos de fábrica del preséu. + + Fallasti %d vegaes al dibuxar el patrón de desbloquéu. Si falles otres %d vegaes, vas tener d\'usar una cuenta de corréu-e pa desbloquiar la tablet.\n\n Vuelvi a intentalo en %d segundos. + + + Fallasti %d vegaes al dibuxar el patrón de desbloquéu. Si falles otres %d vegaes, vas tener d\'usar una cuenta de corréu-e pa desbloquiar el teléfonu.\n\n Vuelvi a intentalo en %d segundos. + + " — " + + Desaniciar + + + ¿Quies xubir el volume penriba del nivel recomendáu?\n\nEscuchar soníos al altu la lleva mentanto llargos períodos de tiempu pue dañar los oyíos + + + Caltén la pantalla primida con dos deos p\'habilitar les funciones d\'accesibilidá. + + Accesibilidá habilitada + + Accesibilidá encaboxada + + Usuariu actual: %1$s + + Camudando a %1$s\u2026 + + Propietariu + + Fallu + + Esti cambéu nun ta permitíu pol alministrador + + Nun s\'atopó nenguna aplicación que pueda facer esta aición. + Revocar + + + ISO A0 + + ISO A1 + + ISO A2 + + ISO A3 + + ISO A4 + + ISO A5 + + ISO A6 + + ISO A7 + + ISO A8 + + ISO A9 + + ISO A10 + + ISO B0 + + ISO B1 + + ISO B2 + + ISO B3 + + ISO B4 + + ISO B5 + + ISO B6 + + ISO B7 + + ISO B8 + + ISO B9 + + ISO B10 + + ISO C0 + + ISO C1 + + ISO C2 + + ISO C3 + + ISO C4 + + ISO C5 + + ISO C6 + + ISO C7 + + ISO C8 + + ISO C9 + + ISO C10 + + Carta + + Carta del gobiernu + + Llegal + + Junior legal + + Doble carta + + Tabloide + + Index Card 3x5 + + Index Card 4x6 + + Index Card 5x8 + + Monarch + + Quarto + + Foolscap + + ROC 8K + + ROC 16K + + PRC 1 + + PRC 2 + + PRC 3 + + PRC 4 + + PRC 5 + + PRC 6 + + PRC 7 + + PRC 8 + + PRC 9 + + PRC 10 + + PRC 16K + + Pa Kai + + Dai Pa Ka + + Jurro Ku Kai + + JIS B10 + + JIS B9 + + JIS B8 + + JIS B7 + + JIS B6 + + JIS B5 + + JIS B4 + + JIS B3 + + JIS B2 + + JIS B1 + + JIS B0 + + JIS Exec + + Chou4 + + Chou3 + + Chou2 + + Hagaki + + Oufuku + + Kahu + + Kaku2 + + You4 + + Cualquier tamañu vertical + + Cualquier tamañu horizontal + + Encaboxáu + + Fallu al escribir conteníu + + desconocíu + + Serviciu d\'impresión non habilitáu + + Instalóse\'l serviciu %s + + Tocar p\'habilitar + + Introduz el PIN del alministrador + + Inxertar PIN + + Incorreutu + + PIN actual + + PIN nuevu + + Confirma\'l PIN nuevu + + Crear PIN pa modificar restricciones + + Los númberos PIN nun concasen. Vuelvi a intentalo. + + El PIN ye enforma curtiu. Tien de tener al menos 4 díxitos. + + + + Inténtalo en 1 s + Inténtalo en %d s + + + Volver a intentalo dempués + + Visualización en pantalla completa + + Pa salir, esliza\'l deu hacia abaxo dende la parte superior. + + Atalántolo + + Fecho + + Control eslizante circular d\'hores + + Control eslizante circular de minutos + + Seleicionar hores + + Seleicionar minutos + + Seleicionar mes y día + + Seleicionar añu + + %1$s desaniciáu + + %1$s de trabayu + + -- + + + + sans-serif-medium + + sans-serif-medium + + sans-serif-medium + + Pa desactivar esta pantalla, caltén primíos al empar los botones de retrocesu y Visión xeneral. + + Pa desactivar esta pantalla, caltén primíu\'l botón Visión xeneral. + + L\'app ta fixada: nun se permite desfixala nesti preséu. + + Pantalla fixada + + Pantalla desfixada + + Solicitar PIN pa desactivar + + Solicitar patrón de desbloquéu pa desactivar + + Solicitar contraseña pa desactivar + + Instaláu pol alministrador + + Anováu pol alministrador + + Desaniciáu pol alministrador + + + + + Mentanto 1 min (hasta la(les) %2$s) + Mentanto %1$d mins (hasta la(les) %2$s) + + + + + Mentanto 1 hr (hasta la(les) %2$s) + Mentanto %1$d hrs (hasta la(les) %2$s) + + + + Mientres un minutu + Mientres %d minutos + + + + Mentanto 1 min + Mentanto %d mins + + + + Mientres una hora + Mientres %d hores + + + + Mentanto 1 hr + Mentanto %d hrs + + + + Hasta les %1$s hores (próxima alarma) + + Hasta que lo desactives + + Hasta que desactives Nun molestar + + %1$s / %2$s + + + Nun molestar + + Tiempu d\'inactividá + + Nueche, na selmana + + Fin de selmana + + Eventu + + + + + + Perfil de trabayu + + Puertu USB de periféricos Android + + Android + + Puertu USB de periféricos + + + Más opciones + + Zarrar la barra de ferramientes flotante + + + + %1$d elementu esbilláu + %1$d elementos esbillaos + + + + diff --git a/core/res/res/values-az-rAZ-watch/strings.xml b/core/res/res/values-az-rAZ-watch/strings.xml index 7e4a7620d7942..92007186e65f4 100644 --- a/core/res/res/values-az-rAZ-watch/strings.xml +++ b/core/res/res/values-az-rAZ-watch/strings.xml @@ -21,4 +21,5 @@ "Tətbiq %1$d/%2$d." + "Sensorlar" diff --git a/core/res/res/values-az-rAZ/cm_strings.xml b/core/res/res/values-az-rAZ/cm_strings.xml new file mode 100644 index 0000000000000..519809f53e29d --- /dev/null +++ b/core/res/res/values-az-rAZ/cm_strings.xml @@ -0,0 +1,170 @@ + + + + + + Ekran şəkli + + qorunan SMS qəbul et + + Tətbiqetməyə qorunan bir SMS qəbul etmə icazəsi verər. + + qorunan SMS siyahısını dəyişdir + + Tətbiqetməyə qorunan SMS ünvan siyahısını dəyişdirmə icazəsi verər. + + Təhlükəsizlik + + Cihaz təhlükəsizlik məlumatı ilə bağlı icazələr. + + telefon qara siyahısını oxu + + Tətbiqetmənin gələn zəngləri və ya mesajları əngəllənmiş telefon nömrələri haqqında məlumat oxumasına icazə verər. + + telefon qara siyahısını dəyişdir + + Tətbiqetmənin gələn zəngləri və ya mesajları əngəllənmiş telefon nömrələrini dəyişdirməsinə icazə verər. + + klaviatura divar kağızını tənzimlə + + Tətbiqetmənin kilit ekranı divar kağızını dəyişdirməsinə icazə verər. + + Yenidən başlat + + Hazırki + + + Yenidən başlat + + Bərpa rejimi (Recovery) + + Önyükləyici (Bootloader) + + Endirmə rejimi + + Proqram təminatını yenidən başlatma + + Yenidən başlat + + Planşetiniz yenidən başladılacaq. + Telefonunuz yenidən başlayacaq. + + Yenidən başladılır\u2026 + + Tətbiq sonlandırıldı + + Şəbəkə üzərindən ADB fəaldır + + USB & şəbəkə üzərindən ADB fəaldır + + Xəta ayırdetməni ləğv etmək üçün toxunun. + + ADB - %1$s + USB & şəbəkə + USB + Şəbəkə + + tətbiqetmə başlatmanın qarşısını al + + %s quraşdırılmayıb + + Üstünlük + Yoxdur + + SIM abunəliyini dəyişmə ilə əlaqədar Wi-Fi internet paylaşma ləğv edildi + + Wi-Fi\'ı bağla + + Gizlilik Qorumasını fəallaşdır ya da ləğv et + Tətbiqetməyə başqa bir tətbiqetmənin Gizlilik Qorumasını işlədib işlədə bilməyəcəyini müəyyənləşdirmə imkanı verər. Əgər tətbiqetmə Gizlilik Qoruması ilə işləyərsə şəxslər, zəng qeydləri və ya mesajlar kimi şəxsi verilənlərə müraciət edə bilməyəcək. + Gizlilik Qoruması fəaldır + %1$s şəxsi verilənlərə müraciət edə bilməyəcək + Gizlilik Qoruması + %1$s %2$s icazəsindən istifadə etmək istəyir. + + Seçimimi yadda saxla + + kameraya müraciət + olduğunuz yerə müraciət + bildirişləri oxu + VPN aktivetmə + açılanda başla + zəng qeydini sil + şəxsləri sil + MMS mesajlarını sil + SMS mesajlarını sil + pəncərələri yuxarıda göstər + tətbiq istifadə statistikalarını al + cihazı oyanıq saxla + telefon zəngi edin + təqvimi yenilə + zəng qeydini yenilə + lövhəni dəyiş + şəxsləri yenilə + sistem tənzimləmələrini yenilə + mikrofonu aç/bağla + səs çal + bildiriş göndər + medianı əks etdir + təqvimi oxu + zəng qeydini oxu + lövhəni + şəxsləri oxu + MMS mesajlarını oxu + SMS mesajlarını oxu + SMS mesajı qəbul et + səs yaz + MMS mesajı göndər + SMS mesajı göndər + açılanda başla + bildiriş mesajlarını göstər + Bluetooth açıb bağla + NFC aç bağla + zəngli saat səsinin idarəsi + səs fokunusuna nəzarət + Bluetooth səsinə nəzarət + əsas səs səviyyəsinə nəzarət + media düymələrindən istifadə et + media səsinə nəzarət + bildiriş səsinə nəzarət + zəng səsini idarə et + sensor geri bildirişdən istifadə et + səsli zəng səviyyəsinə nəzarət + MMS mesajı yazın + SMS mesajı yazın + root müraciəti əldə et + + Bu ekranı çıxarmaq üçün Geri düyməsinə toxunub basılı tutun. + + Bağlı cihaz yoxdur + %1$s cihaz bağlıdır + %1$s cihaz bağlıdır + + + + + + batareya statistikalarını sıfırla + + Tətbiqetmənin aşağı batareya istifadə verilənlərini sıfırlamasına icazə verər. + + diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml index 34df873801840..a138275dd3600 100644 --- a/core/res/res/values-az-rAZ/strings.xml +++ b/core/res/res/values-az-rAZ/strings.xml @@ -254,7 +254,7 @@ "Kredit kartı nömrələri və parollar kimi şəxsi məlumatlar daxildir." "status panelini deaktivləşdir və ya dəyişdir" "Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir." - "status paneli" + "status paneli edin" "Tətbiqə status paneli olmağa imkan verir." "status panelini genişlətmək və ya yığmaq" "Tətbiqə status panelini genişləndirməyə və ya yox etməyə imkan verir." @@ -282,7 +282,7 @@ "Tətbiqə WAP mesajlar göndərmək və ya qəbul etmək imkanı verir. Buna mesajları izləmək və Sizə xəbər vermədən silmək imkanları da daxildir." "işlənən tətbiqlər əldə etmək" "Tətbiqə hazırda və az öncə işləyən tapşırıqlar haqqında ətraflı məlumat əldə etməyə imkan verir. Bu da cihazda hansı tətbiqlərin istifadə olunması haqqında məlumatların əldə edilməsinə imkan verir." - "Profil və cihaz sahiblərini idarə edin" + "profil və cihaz sahiblərini idarə edin" "Profil və cihaz sahiblərini təyin etmək üçün tətbiqə icazə verin." "işlənən tətbiqlərin sırasını dəyişmək" "Tətbiqə tapşırıqları ön plandan arxa plana keçirməyə imkan verir. Tətbiq bunu Sizin daxiletməniz olmadan da edə bilər." @@ -324,7 +324,7 @@ "Tətbiqə planşetinizdəki zəng jurnalını, həmçinin gedən və gələn zənglərin siyahısını dəyişməyə imkan verir. Zərərli tətbiqlər bundan istifadə edərək, zəng jurnalınıza dəyişiklik edə bilər." "Proqrama TV-nizin zəng jurnalını, o cümlədən daxil olan və çıxan zənglərlə bağlı məlumatları dəyişdirmək imkanı verə bilər. Zərərli proqramlar zəng jurnalınızı silmək və ya dəyişdirmək üçün bundan istifadə edə bilər." "Tətbiqə sizin daxil olan və gedən zənglər daxil olmaqla telefon zəngi loqlarınızı redaktə etmək icazəsi verir. Zərərli tətbiqlər bundan telefon loqlarınızı silmək və ya redaktə etmək üçün istifadə edə bilər." - "bədən sensorları (ürək döyüntüsü sayı kimi)" + "bədən sensorlarına (ürək döyüntüsü monitorları kimi) giriş" "Tətbiqə ürək döyüntüsü kimi fiziki durumunuzu izləməyən sensorların datasına daxil olmağa icazə verir." "təqvim tədbirlərini və konfidensial məlumatları oxuyur" "Tətbiqə dostlarınızın və əməkdaşlarınızın planşetinizdə yerləşən kalendar tədbirlərini oxumağa icazə verir. Bu tətbiqə konfidensiallıq və ya həssaslıqdan asılı olmayaraq sizin kalendar məlumatlarınızı paylaşmaq və ya saxlamağa imkan yaradır." @@ -336,15 +336,15 @@ "Dostlarınız və həmkarlarınıza məxsus olanlar da daxil olmaqla, tətbiqə telefonunuzdakı tədbirləri dəyişməyə, tədbir əlavə etməyə və ya silməyə imkan verir. Bu, tədbirə Sizin adınızdan və Sizdən xəbərsiz, təqvim sahibi kimi mesaj göndərmək imkanı verir." "əlavə məkan provayderi əmrlərinə çıxış" "Tətbiqə ekstra məkan provayder əmrlərinə girişə imkan verir. Bu, tətbiqə GPS və ya digər lokal mənbələrlə əməliyyata müdaxiləyə imkan verə bilər." - "dəqiq yeri (GPS və şəbəkə-əsaslı)" + "dəqiq məkana (GPS və şəbəkə əsasında) giriş" "Qlobal Pozisiya Sistemini və ya şəbəkə qüllələri və Wi-Fi kimi şəbəkə məkanını istifadə edərək tətbiqə Sizin dəqiq yerinizi təyin etməyə imkan verir. Bu məkan xidmətləri aktivləşdirilməlidirlər ki, Siz tətbiqi istifadə edən zaman tətbiq onları istifadə edə bilsin. Tətbiqlər Sizin harada olmağınızı bunun vasitəsilə təyin edəcək, eyni zamanda, bu xidmət əlavə batareya enerjisi apara bilər." - "təxmini məkan (şəbəkə əsaslı)" + "təxmini məkana (şəbəkə əsaslı) giriş" "Tətbiqə təxmini yerinizi almaq üçün imkan verir. Bu yer, yerləşmə xidmətləri tərəfindən mobil qüllələr və Wi-Fi kimi şəbəkə yerləşmə mənbələrdən istifadə etməklə əldə edilir. Bu yerləşmə xidmətləri tətbiqin onlardan istifadəsi üçün açıq və cihazınızın onları istifadəsi üçün mövcud olmalıdır. Tətbiqlər bundan sizin təxminən harada olduğunuzu müəyyənləşdirmək üçün istifadə edə bilər." "audio ayarlarınızı dəyişir" "Tətbiqə səs və hansı spikerin çıxış üçün istifadə olunduğu kimi qlobal səs ayarlarını dəyişdirməyə imkan verir." "səs yaz" "Tətbiqə mikrofonla audio yazmaq icazəsi verir. İcazə tətbiqə sizin təsdiqiniz olmadan istənilən zaman səs yazma izni verir." - "sim rabitəsi" + "əmrləri SIM\'ə göndərin" "Tətbiqə SIM-ə əmrlər göndərməyə imkan verir. Bu, çox təhlükəlidir." "şəkil və video çəkmək" "Tətbiqə kamera ilə şəkil və video çəkməyə imkan yaradır. Bu icazə tətbiqə sizin təsdiqiniz olmadan kameradan istifadə icazəsi verir." @@ -382,7 +382,7 @@ "Tətbiqə telefonda olan hesabların siyahısını əldə etməyə imkan verir. Buna quraşdırdığınız istənilən tətbiq tərəfindən yaradılan hesablar da aiddir." "şəbəkə bağlantılarına baxmaq" "Tətbiqə mövcud olan və qoşulan şəbəkələr kimi qoşulmalar haqqında məlumatı görməyə icazə verir." - "tam şəbəkə girişi" + "tam şəbəkə girişi var" "Tətbiqə şəbəkə soketlərini yaratmağa və fərdi şəbəkə protokollarını istifadə etməyə imkan verir. Brauzer və digər tətbiqlər datanın internetə ötürülməsini təmin edən vəsaitlər verir, ona görə də datanın internetə gönrədilməsi üçün bu icazə tələb olunmur." "şəbəkə bağlantısını dəyişir" "Tətbiqə şəbəkə vəziyyətini dəyişməyə icazə verir." @@ -402,7 +402,7 @@ "Tətbiqə lokal Bluetooth telefonunu konfiqurə etməyə və uzaq cihazları kəşf etmək və onlara qoşulmaq icazəsi verir." "WiMAX\'a qoşul və bağlantını kəs" "Tətbiqə WiMAX mövcudluğu və qoşulmuş WiMAX şəbəkələrini təyin etməyə icazə verir." - "WiMAX vəziyyətini dəyişir" + "WiMAX vəziyyətini dəyişir" "Tətbiqə planşeti WiMAX şəbəkələrinə qoşmaq və onlardan ayırmaq icazəsi verir." "Proqrama TV-ni WiMAX şəbəkələrinə qoşmaq və onlarla əlaqəni kəsmək imkanı verir." "Tətbiqə telefonu WiMAX şəbəkəsinə qoşmağa və ya WiMAX şəbəkəsindən ayırmağa imkan verir." @@ -485,7 +485,7 @@ "Sensor ekran parametr kalibrasiyalarını dəyişmək üçün tətbiqə icazə verin. Normal tətbiqlər belə şeyləri istəmir." "DRM sertifikatlarına giriş" "Tətbiqə DRM sertifikatları təmin etməyə və işlətməyə icazə verir. Normal tətbiqlər tərəfindən heç vaxt istənilməməlidir." - "Android Beam transfer statusunu əldə edin" + "Android Beam transfer statusunu əldə edin" "Bu tətbiqə hazırkı Android Beam transferləri haqqında məlumat əldə etməyə icazə verir" "Müəllif hüquqlarının qorunması üçün texniki vasitələr sertifikatlarını silin" "Tətbiqə müəllif hüquqlarının qorunması üçün texniki vasitələr sertifikatlarını silməyə icazə verir. Normal tətbiqlər tərəfindən heç vaxt tələb edilmir." @@ -1091,11 +1091,11 @@ "Format edilir..." "Daxil edilməyib" "Uyğun gələn fəaliyyət tapılmadı." - "Media çıxışını yönləndirir" + "media çıxışını yönləndirin" "Tətbiqə media çıxışını digər xarici cihazlara yönləndirmək imkanı verir." - "Quraşdırma sessiyalarını oxuyun" + "quraşdırma sessiyalarını oxuyun" "Tətbiqə quraşdırma sessiyalarını oxumağa yardım edir. Bu da aktiv paket quraşdırmaları haqqında məlumatları görməyə imkan verir." - "Pektləri quraşdırma sorğusu" + "paketləri quraşdırma sorğusu" "Tətbiqə paketləri quraşdırma sorğusu göndərməyə icazə verir." "Zoom nəzarəti üçün iki dəfə toxunun" "Widget əlavə edilə bilmədi." diff --git a/core/res/res/values-be/cm_strings.xml b/core/res/res/values-be/cm_strings.xml new file mode 100644 index 0000000000000..9053cf0c2384d --- /dev/null +++ b/core/res/res/values-be/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Здымак экрану + + атрыманне абароненых SMS + + Дазваляе праграме атрымліваць абароненыя SMS. + + мадыфікацыя спісу абароненых SMS + + Дадатак зможа змяняць спіс адрасатаў абароненых SMS-паведамленняў. + + Бяспека + + Дазволы, што адносяцца да бяспекі дадзеных на прыладзе. + + прагляд чорнага спісу + + Дазваляе праграме праглядаць звесткі пра нумары тэлефонаў, ад якіх заблакаваны тэлефанаванні ці паведамленні. + + мадыфікацыя чорнага спісу + + Дазваляе праграме ўносіць змены ў спіс нумароў тэлефонаў, ад якіх заблакаваны тэлефанаванні ці паведамленні. + + усталёўка шпалераў экрану блакавання + + Дазваляе праграме змяняць шпалеры экрану блакавання. + + Перазагрузіць + + Бягучы + + + Перазагрузіць + + Рэжым аднаўлення + + Загрузчык + + Спампоўкі + + Перазапуск інтэрфейсу + + Перазагрузіць + + Ваш планшэт будзе перазапушчаны. + Ваш тэлефон будзе перазапушчаны. + + Перазапуск\u2026 + + Дадатак зачынены + + ADB праз сетку ўключана + + ADB праз USB & сетку ўключана + + Націснуць для выключэння наладкі. + + ADB - %1$s + па сетцы & USB + USB + Па сетцы + + Перахоп запуску дадаткаў + + %s не ўсталявана + + Важныя + Не + + Выключаныя Wi-Fi кропкі доступу ў сувязі са зменай падпіскі SIM + + Вымкнуць Wi-Fi + + уключэнне ці выключэнне рэжыму абароны прыватнасці + Дазваляе праграме выбіраць, ці будзе іншая праграма працаваць у рэжыме абароны прыватнасці. Калі праграма запушчана ў рэжыме абароны прыватнасці, яна не будзе мець доступу да асабістых дадзеных, такіх як кантакты, паведамленні ці гісторыя тэлефанаванняў. + Рэжым абароны прыватнасці актыўны + %1$s не будзе мець доступу да асабістых дадзеных + Рэжым абароны + %1$s жадае %2$s. + + Запамятаць вырашэнне + + атрымаць доступ да камеры + атрымаць доступ да месцазнаходжання прылады + чытаньне паведамленьняў + актываваць VPN + прызначыць запуск пры ўлучэнні прылады + выдаліць часопіс званкоў + выдаліць кантакты + выдаліць MMS-паведамленні + выдаліць SMS-паведамленні + адлюстроўваць элементы інтэрфейсу па-над іншымі вокнамі + атрымаць статыстыку выкарыстання дадаткаў + забараніць прыладзе пераходзіць да рэжыму сну + выканаць тэлефонны званок + змяніць дадзеныя каляндара + змяніць дадзеныя часопіса званкоў + змяніць змесціва буфера абмену + змяніць дадзеныя кантактаў + змяніць сістэмныя параметры + выключыць ці ўключыць мікрафон + прайграванне аўдыя + вывесці паведамленне + выканаць трансляцыю кантэнту + прачытаць дадзеныя каляндара + прачытаць дадзеныя спіса выклікаў + прачытаць змесціва буфера абмену + прачытаць дадзеныя кантактаў + прачытаць MMS-паведамленні + прачытаць SMS-паведамленні + атрымаць SMS-паведамленне + запіс аўдыя + даслать MMS-паведамленне + даслать SMS-паведамленне + прызначыць запуск пры ўлучэнні прылады + адлюстроўваць усплывальныя паведамленні + пераключыць стан Bluetooth + пераключыць стан сотавай сеткі + пераключыць стан модуля NFC + пераключыць стан Wi-Fi + атрымаць кіраванне гучнасцю будзільніка + атрымаць кіраванне аўдыя фокусам + атрымаць кіраванне гучнасцю Bluetooth-прылад + атрымаць кіраванне агульнай гучнасцю + выкарыстоўваць кнопкі мультымедыя + атрымаць кіраванне гучнасцю мультымедыя + кіраванне гучнасцю паведамленняў + кіраванне гучнасцю званка + выкарыстоўваць вібраводгук + атрымаць кіраванне гучнасцю пры гутарцы + стварыць MMS-паведамленне + стварыць SMS-паведамленне + Выкарыстанне адбіткаў пальцаў + Дадаць галасавое паведамленне + атрыманне стану тэлефона + Сканаваць сеткі Wi-Fi + змена шпалер + Выкарыстоўваць структуру падтрымкі + зрабіць скрыншот + Выкарыстоўваць датчыкі + Шырокаапавяшчальныя паведамленні + Фіктыўнае месцазнаходжанне + чытанне дадзеных + захоўваць дадзеныя на картку памяці + улучэнне экрану + атрымаць інфармацыю карыстальнікаў + Змяніць стан Wi-Fi + атрымаць правы суперкарыстальніка + + Каб адмацаваць экран, націсніце і ўтрымвайце кнопку \"Назад\". + + Няма падлучаных прылад + %1$s падлучаная прылада + Падлучана прылад: %1$s + + + + Запуск дадатку забаронены + Дадатак %1$s заблакаваны на запуск. Націсні, каб увесці паролль і запусціць дадатак. + + Батарэя цалкам зараджана + Адлучы зарадную прыладу каб павялічыць тэрмін жыцця батарэі. + + Абнуленне статыстыкі батарэі + + Дазволіць дадатку чысціць дадзеныя пра выкарыстанне акумулятарнай батарэі прылады. + + SIM-картка змянілася + Націсні, каб усталяваць параметры па змаўчанні + diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml new file mode 100644 index 0000000000000..94637b60d9079 --- /dev/null +++ b/core/res/res/values-be/strings.xml @@ -0,0 +1,1795 @@ + + + + + + Біт + + КБ + + МБ + + ГБ + + + + ПБ + + %1$s%2$s + + %1$d содняў + + %1$d содні + %2$d гадзінаў + + %1$d содні + %2$dгадзін + + %1$d гадзінаў + + %1$d гадзін + %2$d хвілін + + %1$d г + %2$d хв + + %1$d хвілінаў + + %1$d хвіліна + + %1$d хвілін + %2$d сэкунд + + %1$d хвілін + %2$d сэкунда + + %1$d сэкундаў + + %1$d сэкунд + + <Без назвы> + + (Няма нумару тэлефону) + + Невядомы + + Галасавая пошта + + MSISDN1 + + + Праблема падчас падлучэньня, магчыма памылка коду MMI. + + Абмежаваньне: выкарыстоўваюцца толькі дазволеныя нумары. + + Служба была ўключана. + + Служба была ўключана для: + + Служба была адключана. + + Рэгістрацыя прайшла пасьпяхова. + + Пасьпяхова выдалена. + + Памылковы пароль. + + Запыт MMI завершаны. + + Памылка: неабходны стары PIN-код. + + Уведзены памылковы PUK-код. + + PIN-коды ня супадаюць. + + PIN-код (ад 4 да 8 лічбаў). + + PUK-код ад 8 лічбаў і больш. + + SIM-картка заблакавана PUK-кодам. Неабходны PUK-код, каб разблакаваць картку. + Для разблакаваньня SIM-карткі неабходны PUK2-код. + + Памылка. Падлучы блакаваньне SIM-карткі ці карткі RUIM. + + + У вас засталася %d спроба перад тым, як SIM-картка будзе заблакавана. + У вас засталася %d спробы перад тым, як SIM-картка будзе заблакавана. + У вас засталася %d спробы перад тым, як SIM-картка будзе заблакавана. + + + IMEI + + MEID + + Уваходны выклік + + Зыходны выклік + + + Абмежаваньне ідэнтыфікатару падлучанай лініі + + Пераадрасаваньне выклікаў + + Чаканьне выкліку + + Забарона выклікаў + + Зьмена пароля + + Зьмена PIN-коду + Бягучы нумар выкліку + Нумар выкліку абмежаваны + Трохбаковы выклік + Адмова ад непажаданых выклікаў + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wi-Fi выклік + + + + + %s + + %s + + Адключана + + Wi-Fi пераважна + + Сотавы пераважна + + толькі Wi-Fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Рэжым лёту + + + + + + + Блакаваць зараз + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Дазваляе праграме дасылаць каманды да SIM-карткі. Гэта вельмі небяспечна. + + + + + + + + + + + + + + + + + + + + выкарыстанне інфрачырвонай перадачы + + Дазваляе праграме выкарыстоўваць інфрачырвоны перадатчык планшэту. + + + Дазваляе праграме выкарыстоўваць інфрачырвоны перадатчык тэлефону. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Скасаваць + + + Скасаваць + + + + УКЛ + + ВЫКЛ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Скасаваць + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Скасаваць + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Гэтае дзеянне забаронена адміністратарам + + + + ISO A0 (841х1189 мм) + + ISO A1 (594х841 мм) + + ISO A2 (420х594 мм) + + ISO A3 (297х420 мм) + + ISO A4 (210x297 мм) + + ISO A5 (148x210 мм) + + ISO A6 (105x148 мм) + + ISO A7 (74x105 мм) + + ISO A8 (52x74 мм) + + ISO A9 (37x52 мм) + + ISO A10 (26x37 мм) + + ISO B0 (1000x1414 мм) + + ISO B1 (707x1000 мм) + + ISO B2 (500x707 мм) + + ISO B3 (353x500 мм) + + ISO B4 (250x353 мм) + + ISO B5 (176x250 мм) + + ISO B6 (125x176 мм) + + ISO B7 (88x125 мм) + + ISO B8 (62x88 мм) + + ISO B9 (44x62 мм) + + ISO B10 (31x44 мм) + + ISO C0 (917x1297 мм) + + ISO C1 (648x917 мм) + + ISO C2 (458x648 мм) + + ISO C3 (324x458 мм) + + ISO C4 (229x324 мм) + + ISO C5 (162x229 мм) + + ISO C6 (114x162 мм) + + ISO C7 (81x114 мм) + + ISO C8 (57x81 мм) + + ISO C9 (40x57 мм) + + ISO C10 (28x40 мм) + + Letter (216x279 мм) + + Government Letter (203x267 мм) + + Legal (216x356 мм) + + Junior Legal (203x127 мм) + + Ledger (432x279 мм) + + Tabloid (279x432 мм) + + Index Card 3x5 (76x127 мм) + + Index Card 4x6 (102x152 мм) + + Index Card 5x8 (127x203 мм) + + Monarch (184x267 мм) + + Quarto (203x254 мм) + + Foolscap (203x330 мм) + + ROC 8K (270x390 мм) + + ROC 16K (195x270 мм) + + PRC 1 (102x165 мм) + + PRC 2 (102x176 мм) + + PRC 3 (125x176 мм) + + PRC 4 (110x208 мм) + + PRC 5 (110x220 мм) + + PRC 6 (120x320 мм) + + PRC 7 (160x230 мм) + + PRC 8 (120x309 мм) + + PRC 9 (229x324 мм) + + PRC 10 (324x458 мм) + + PRC 16K (146x215 мм) + + Pa Kai (146x215 мм) + + Dai Pa Kai (275x395 мм) + + Jurro Ku Kai (275x395 мм) + + JIS B10 (32x45 мм) + + JIS B9 (45x64 мм) + + JIS B8 (64x91 мм) + + JIS B7 (91x128 мм) + + JIS B6 (128x182 мм) + + JIS B5 (182x257 мм) + + JIS B4 (257x364 мм) + + JIS B3 (364x515 мм) + + JIS B2 (515x728 мм) + + JIS B1 (728x1030 мм) + + JIS B0 (1030x1456 мм) + + JIS Exec (216x330 мм) + + Chou4 (90x205 мм) + + Chou3 (120x235 мм) + + Chou2 (111,1x146 мм) + + Hagaki (100x148 мм) + + Oufuku (148x200 мм) + + Kaku (240x322,1 мм) + + Kaku2 (240x332 мм) + + You4 (105x235 мм) + + + + Скасавана + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-bg-watch/strings.xml b/core/res/res/values-bg-watch/strings.xml index 1f1d921d8ba83..1cd56eb825437 100644 --- a/core/res/res/values-bg-watch/strings.xml +++ b/core/res/res/values-bg-watch/strings.xml @@ -21,4 +21,5 @@ "Прилож. %1$d от %2$d." + "Сензори" diff --git a/core/res/res/values-bg/cm_strings.xml b/core/res/res/values-bg/cm_strings.xml new file mode 100644 index 0000000000000..8b94d248ebad4 --- /dev/null +++ b/core/res/res/values-bg/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Снимка на екрана + + приемай защитени SMS + + Разрешава на приложението да приема входящи защитени SMS. + + Модифициране на списъка със защитени SMS + + Разрешава на приложението да модифицира списъка с контакти на защитените SMS съобщения. + + Сигурност + + Разрешения, свързани с информацията за защита на устройството. + + Прочетете списъка с блокирани контакти + + Разрешава на приложението да прочетете информацията за телефонни номера, които са блокирани за входящи повиквания или съобщения. + + Промяна на списъка с блокирани контакти + + Разрешава на приложението да промени телефонните номера, които са блокирани за входящи повиквания или съобщения. + + Задаване на тапет за заключен екран + + Разрешава на едно приложение да променя тапета на заключения екран. + + Рестартиране + + Текущ + + + Рестартиране + + Режим на възстановяване + + Буутлоудър + + Изтегляне + + Софтуерно рестартиране + + Рестартиране + + Таблетът ще се рестартира. + Телефонът ще се рестартира. + + Рестартиране\u2026 + + Затворено приложение + + ADB над мрежата е активиран + + ADB над USB & мрежата е активирана + + Докоснете за да деактивирате отстраняване на грешки. + + ADB - %1$s + USB & мрежа + USB + Мрежа + + Прихвани стартиращите приложения + + %s не е инсталиран + + Приоритет + Без + + Изключена Wi-Fi точка за достъп, поради промяна в абонаментна на СИМ + + Изключете Wi-Fi + + Активира или деактивира Защитен режим + Разрешава на приложението да променя статута на поверителност на друго приложение. Когато едно приложение се използва с защита на поверителността, не може да има достъп до персонални данни, като контакти, регистри с повиквания или съобщения. + Защитен режим e активен + %1$s няма да можете да получите достъп до лични данни + Защитен режим + %1$s бих искал да %2$s . + + Запомни избора ми + + достъп до камерата + достъп до вашето местоположение + прочети своите известия + активиране на VPN + изпълнение при включване + изтриване на дневника за повиквания + Изтриване на контакти + Изтриване на MMS съобщенията + Изтриване на SMS съобщенията + Издърпай прозореца на най-отгоре + Вземи статистика за използването на приложението + Задръж устройството будно + осъществете телефонно повикване + актуализиране на вашият календар + актуализация на дневника за повиквания + промяна на клипборда + актуализиране на вашите контакти + актуализиране на системните настройки + изключи/включи микрофона + изпълнение на аудио + публикувай уведомление + медиен проект + прегледай календара + прегледай повикванията + прегледай клипборда + прегледай контактите + прегледай MMS съобщенията + прегледайте вашите SMS съобщения + получихте SMS съобщение + записване на звук + Изпращане на MMS съобщение + Изпращане на SMS съобщение + изпълнение при включване + показвай изкачащи уведомления + активиране/деактивиране Bluetooth + Превключване клетъчен данни + активиране/деактивиране NFC + активирай/деактивирай Wi-Fi + контрол на силата на алармата + контрол на силата на звука + контрол на силата на Bluetooth + главен контрол на звука + Използвайте мултимедийните бутони + контрол на звука за мултимедия + контрол на звука за уведомления + контрол на звука при повикване + Използвайте haptic feedback + контрол на звука при разговор + Напишете MMS съобщение + Напишете SMS съобщение + използвай пръстов отпечатък + добави гласова поща + достъп до състоянието на телефона + сканирай за Wi-Fi мрежи + Смяна на тапета + Използвайте структура за подпомагане + снимай екрана + използвай сензорите за тяло + регистрирай излъчването на антенна клетка + симулиране на местоположение + прочети външната памет + пиши върху външната памет + включи екрана + изведи акаунти на устройството + променете състоянието на Wi-Fi + получете администраторски права + + За да освободите този екран, докоснете и задръжте бутона назад. + + Няма свързано устройство + %1$s устройството е свързано + %1$s устройствата са свързани + + + + Старта на приложението блокиран + %1$s е блокиран. Докосни за да потвърдиш старта на приложението. + + Батерията е напълно заредена + Изключете зарядното устройството за да удължите живота на батерията. + + Нулиране статистиката на батерията + + Позволява заявление да рестартирате текущите данни за използването на ниско ниво на батерията. + + СИМ картите са променени + Докоснете за да зададете настройките по подразбиране на СИМ картата + diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 14f09b75b7530..e1f3c47aceb65 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -254,7 +254,7 @@ "Включва лични данни, като например номера на кредитни карти и пароли." "деактивиране или промяна на лентата на състоянието" "Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони." - "лента на състоянието" + "изпълняване на ролята на лента на състоянието" "Разрешава на приложението да бъде лентата на състоянието." "разгъване или свиване на лентата на състоянието" "Разрешава на приложението да разгъва или свива лентата на състоянието." @@ -282,7 +282,7 @@ "Разрешава на приложението да получава и обработва WAP съобщения. Това разрешение включва възможността да наблюдава или изтрива изпратените до вас, без да ви ги покаже." "извличане на изпълняваните приложения" "Разрешава на приложението да извлича информация за задачите, изпълнявани понастоящем и неотдавна. Това може да му позволи да открива данни за това, кои приложения се използват на устройството." - "Управление на собствениците на потребителските профили и на устройствата" + "управление на собствениците на потребителските профили и устройствата" "Разрешава на приложенията да задават собствениците на потребителските профили и собственика на устройствата." "пренареждане на изпълняваните приложения" "Разрешава на приложението да прехвърля задачи на преден и на заден план. То може да направи това без вашето потвърждение." @@ -324,7 +324,7 @@ "Разрешава на приложението да променя списъка с обаждания на таблета ви, включително данните за входящите и изходящите обаждания. Злонамерените приложения могат да използват това, за да изтрият или променят този списък." "Разрешава на приложението да променя списъка с обажданията на телевизора ви, включително данните за входящите и изходящите повиквания. Злонамерените приложения може да използват това, за да изтрият или променят списъка с обажданията ви." "Разрешава на приложението да променя списъка с обаждания на телефона ви, включително данните за входящите и изходящите обаждания. Злонамерените приложения могат да използват това, за да изтрият или променят този списък." - "телесни сензори (като монитори за сърдечния ритъм)" + "достъп до телесните сензори (напр. пулсомери)" "Разрешава на приложението да осъществява достъп до данните от сензорите, които следят физическото ви състояние, като например сърдечния ви ритъм." "четене на събития от календари плюс поверителна информация" "Разрешава на приложението да чете всички събития от календари, съхранени на таблета ви, включително тези на приятели или колеги. Това може да му позволи да споделя или запазва данните от календара ви независимо от поверителността." @@ -336,15 +336,15 @@ "Разрешава на приложението да добавя, премахва и променя събития, които можете да променяте на телефона си, включително тези на приятели или колеги. Това може да му позволи да изпраща съобщения, които изглежда, че идват от собствениците на календарите, или да променя събития без знанието на собствениците." "достъп до допълнителни команди на доставчика на местоположение" "Разрешава на приложението достъп до допълнителни команди на доставчика на местоположение. Това може да позволи на приложението да смущава работата на GPS или на другите източници на местоположение." - "точно местоположение (основано на GPS и мрежата)" + "достъп до точното местоположение (въз основа на GPS и мрежата)" "Разрешава на приложението да получи точното ви местоположение посредством системата GPS или съответните мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на устройството ви, за да могат да се използват от приложението. Приложенията може да ползват това, за да определят къде се намирате, и да изразходват повече енергия от батерията." - "приблизително местоположение (основано на мрежата)" + "достъп до приблизителното местоположение (въз основа на мрежата)" "Разрешава на приложението да получи приблизителното ви местоположение. То се извлича от услугите за местоположение посредством съответните мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги трябва да са включени и налице на устройството ви, за да могат да се използват от приложението. Приложенията може да ползват това, за да определят къде приблизително се намирате." "промяна на настройките ви за звука" "Разрешава на приложението да променя глобалните настройки за звука, като например силата и това, кой високоговорител се използва за изход." "запис на звук" "Разрешава на приложението да записва звук с микрофона. Това разрешение му позволява да го прави по всяко време без потвърждение от ваша страна." - "комуникация със SIM картата" + "изпращане на команди до SIM картата" "Разрешава на приложението да изпраща команди до SIM картата. Това е много опасно." "правене на снимки и видеоклипове" "Разрешава на приложението да прави снимки и видеоклипове с камерата. Това разрешение му позволява да я използва по всяко време без потвърждение от ваша страна." @@ -382,7 +382,7 @@ "Разрешава на приложението да получава списъка с профили, известни на телефона. Това може да включва и създадените от инсталирани от вас приложения." "преглед на връзките с мрежата" "Разрешава на приложението да вижда информация за връзките с мрежата, като например съществуващите и свързаните мрежи." - "пълен достъп до мрежата" + "пълен достъп до мрежата" "Разрешава на приложението да създава мрежови сокети и да използва персонализирани мрежови протоколи. Браузърът и другите приложения предоставят средства за изпращане на данни до интернет, така че това разрешение не се изисква за тази цел." "промяна на връзката с мрежата" "Разрешава на приложението да променя състоянието на връзката с мрежата." @@ -402,7 +402,7 @@ "Разрешава на приложението да конфигурира локалния телефон с Bluetooth, както и да открива и да се сдвоява с отдалечени устройства." "установяване и прекратяване на връзката с WiMAX" "Разрешава на приложението да определя дали WiMAX мрежата е активирана, както и информация за всички такива мрежи, които са свързани." - "Промяна на състоянието на WiMAX мрежата" + "промяна на състоянието на WiMAX мрежата" "Разрешава на приложението да свързва таблета към WiMAX мрежа и да прекратява връзката му с нея." "Разрешава на приложението да установява и прекратява връзката на телевизора с WiMAX мрежи." "Разрешава на приложението да свързва телефона към WiMAX мрежа и да прекратява връзката му с нея." @@ -485,7 +485,7 @@ "Разрешава на приложението да променя параметрите на калибриране на сензорния екран. Нормалните приложения би трябвало никога да не се нуждаят от това." "достъп до сертификатите за управление на цифровите права (DRM)" "Разрешава на приложението да обезпечава и използва сертификатите за управление на цифровите права (DRM). Нормалните приложения би трябвало никога да не се нуждаят от това." - "Получаване на състоянието на прехвърлянията чрез Android Лъч" + "получаване на състоянието на прехвърлянията чрез Android Лъч" "Разрешава на това приложение да получава информация относно текущите прехвърляния чрез Android Лъч" "премахване на сертификатите за управление на цифровите права (DRM)" "Разрешава на приложението да премахва сертификатите за управление на цифровите права (DRM). Нормалните приложения би трябвало никога да се нуждаят от това." @@ -1091,11 +1091,11 @@ "Форматира се…" "Не е поставено" "Не бяха намерени съответстващи дейности." - "Насочване на изходящата мултимедия" + "маршрутизиране на извеждането на мултимедия" "Разрешава на приложението да насочва изходящата мултимедия към други външни устройства." - "Четене на сесии за инсталиране" + "четене на сесии за инсталиране" "Разрешава на приложението да чете сесии за инсталиране. Това му позволява да вижда подробности за активните инсталирания на пакети." - "Заявка за инсталиране на пакети" + "заявка на пакети за инсталиране" "Разрешава на приложението да заявява инсталиране на пакети." "Докоснете двукратно за управление на промяната на мащаба" "Приспособлението не можа да бъде добавено." diff --git a/core/res/res/values-bn-rBD-watch/strings.xml b/core/res/res/values-bn-rBD-watch/strings.xml index b93484115ab72..f68e824f18d3e 100644 --- a/core/res/res/values-bn-rBD-watch/strings.xml +++ b/core/res/res/values-bn-rBD-watch/strings.xml @@ -21,4 +21,5 @@ "%2$dটির মধ্যে %1$dটি অ্যাপ্লিকেশান" + "সেন্সরগুলি" diff --git a/core/res/res/values-bn-rBD/cm_strings.xml b/core/res/res/values-bn-rBD/cm_strings.xml new file mode 100644 index 0000000000000..148a78dd9345f --- /dev/null +++ b/core/res/res/values-bn-rBD/cm_strings.xml @@ -0,0 +1,141 @@ + + + + + + স্ক্রীনসর্ট + + সুরক্ষিত এসএমএস গৃহীত হবে + + একটি আগত সুরক্ষিত এসএমএস গ্রহণ করতে অ্যাপটিকে অনুমতি দিন। + + সংরক্ষিত এসএমএস তালিকা পরিবর্তন করতে সক্ষম + + + নিরাপত্তা + + ডিভাইসের নিরাপত্তা তথ্য সংক্রান্ত অনুমতি। + + ফোনের নিষিদ্ধ তালিকা পড়ুন + + একটি অ্যাপকে অভিমুখী কল বা বার্তার জন্য অবরুদ্ধ ফোন নাম্বারের তথ্য পাঠের অনুমতি দিন। + + ফোনের নিষিদ্ধ তালিকা পরিবর্তন করুন + + একটি অ্যাপকে অভিমুখী কল বা বার্তার জন্য অবরুদ্ধ ফোন নাম্বার পরিবর্তনের অনুমতি দিন। + + কীগার্ড ওয়ালপেপার নির্ধারণ + + অ্যাপটিকে লক স্ক্রীন ওয়ালপেপার পরিবর্তনের অনুমতি দিন। + + পুনরায় চালু + + + + পুনরায় চালু + + পুনরুদ্ধার + + বুটলোডার + + ডাউনলোড + + দ্রুত পুনরায় চালু + + + আপনার ট্যাবলেট পুনরায় চালু হবে। + আপনার ফোন পুনরায় চালু হবে। + + পুনরায় চালু হচ্ছে\u2026 + + + নেটওয়ার্কের উপর এডিবি সক্রিয় + + এডিবির উপর ইউএসবি & নেটওয়ার্ক সক্রিয় + + ডিবাগ নিষ্ক্রিয় করতে স্পর্শ করুন। + + + + + অগ্রাধিকার + + + ওয়াইফাই বন্ধ করুন + + গোপনীয়তা রক্ষাকারী সক্রিয় বা নিস্ক্রিয় করুন + অ্যাপটি কে অন্য অ্যাপ পরিবর্তন করার অনুমতি দিন যা গোপনীয়তা রক্ষাকারী সঙ্গে চলমান। যখন একটি অ্যাপ গোপনীয়তা রক্ষাকারী সঙ্গে চলমান থাকে তখন এটি ব্যক্তিগত তথ্য ব্যাবহার করতে পারবে না, যেমন যোগাযোগ, কল লগ, বা বার্তা। + গোপনীয়তা রক্ষাকারী সক্রিয় + %1$s ব্যাক্তিগত তথ্য ব্যাবহার করতে পারবেন না + গোপনীয়তা রক্ষাকারী + %1$s করতে চায় %2$s. + + + ক্যামেরায় প্রবেশাধিকার + আপনার অবস্থানে প্রবেশাধিকার + আপনার নোটিফিকেশানস প্রবেশাধিকার + অ্যাপের সংস্থান তথ্যাদি পান + আপনার ডিভাইস জাগ্রত রাখা + একটি ফোন কল করুন + আপনার পঞ্জিকা হালনাগাদ করুন + কল লগ হালনাগাদ করুন + ক্লিপবোর্ড রূপান্তর করুন + আপনার যোগাযোগসমূহে হালনাগাদ করুন + সিস্টেম রুপান্তর নির্ধারণ হালনাগাদ করুন + অডিও প্লে করুন + একটি নোটিফিকেশান পোস্ট + আপনার পঞ্জিকায় প্রবেশাধিকার + কল লগ এ প্রবেশাধিকার + ক্লিপবোর্ড এ প্রবেশাধিকার + যোগাযোগসমূহে প্রবেশাধিকার + এমএমএস বার্তায় প্রবেশাধিকার + এমএমএস বার্তায় প্রবেশাধিকার + একটি এসএমএস বার্তা গ্রহণ + অডিও রেকর্ড + এমএমএস বার্তা প্রেরণ + এসএমএস বার্তা প্রেরণ + শক্তি প্রাপ্তি থেকে আরম্ভ + ব্লু-টুথ টগল + এনএফসি টগল + এলার্ম ভলিউম নিয়ন্ত্রণ + অডিও ফোকাস নিয়ন্ত্রণ + ব্লু-টুথ ভলিউম নিয়ন্ত্রণ + মাস্টার ভলিউম নিয়ন্ত্রণ + মিডিয়া বোতামগুলোর ব্যবহার + মিডিয়া ভলিউম নিয়ন্ত্রণ + নোটিফিকেশান ভলিউম নিয়ন্ত্রণ + রিংটোন ভলিউম নিয়ন্ত্রণ + কাম্পা প্রতিক্রিয়ার ব্যবহার + ভয়েস কলের ভলিউম নিয়ন্ত্রণ + এমএমএস বার্তা লিখুন + এসএমএস বার্তা লিখুন + + + + + + + + ব্যাটারির পরিসংখ্যান পুনঃবিন্যাস করুন + + + diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml index 48f99718b57a0..71f87b253fd2e 100644 --- a/core/res/res/values-bn-rBD/strings.xml +++ b/core/res/res/values-bn-rBD/strings.xml @@ -254,7 +254,7 @@ "ক্রেডিট কার্ডের নম্বর ও পাসওয়ার্ডগুলির মতো ব্যক্তিগত তথ্য অন্তর্ভুক্ত করে৷" "স্থিতি দন্ড নিষ্ক্রিয় অথবা সংশোধন করে" "অ্যাপ্লিকেশানকে স্থিতি দন্ড অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷" - "স্থিতি দন্ড" + "স্থিতি দন্ডে থাকুন" "অ্যাপ্লিকেশানটিকে স্থিতি দন্ডে থাকতে দেয়৷" "স্থিতি দন্ড সম্প্রসারিত/সঙ্কুচিত করে" "অ্যাপ্লিকেশানটিকে স্থিতি দন্ড প্রসারিত বা সঙ্কুচিত করতে দেয়৷" @@ -282,7 +282,7 @@ "অ্যাপ্লিকেশানটিকে WAP বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷" "চলমান অ্যাপ্লিকেশান উদ্ধার করে" "বর্তমানে ও সাম্প্রতিককালের সক্রিয় ক্রিয়াগুলি সম্বন্ধে তথ্য পুনরুদ্ধার করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এছাড়া এটি ডিভাইসটিতে কোন অ্যাপ্লিকেশানগুলি ব্যবহৃত হচ্ছে তার বিষয়ে তথ্য খুঁজে বের করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করতে পারে৷" - "প্রোফাইল এবং ডিভাইস মালিকদের পরিচালনা করুন" + "প্রোফাইল এবং ডিভাইস মালিকদের পরিচালনা করুন" "অ্যাপ্লিকেশানগুলিকে প্রোফাইলের মালিকদের এবং ডিভাইসের মালিককে সেট করার অনুমতি দেয়৷" "চলমান অ্যাপ্লিকেশান পুনর্বিন্যাস করে" "অ্যাপ্লিকেশানটিকে কার্যগুলিকে পুরোভাগে এবং পশ্চাদপটে সরানোর অনুমতি দেয়৷ অ্যাপ্লিকেশানটি আপনার ইনপুট ছাড়া এটি করতে পারে৷" @@ -324,7 +324,7 @@ "ইনকামিং ও আউটগোয়িং কলগুলি সম্পর্কিত ডেটা সহ আপনার ট্যাবলেটের কল লগ পরিবর্তন করতে দেয়৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি এটিকে আপনার কল লগ মুছে দিতে বা পরিবর্তন করতে ব্যবহার করতে পারে৷" "ইনকামিং ও আউটগোয়িং কলগুলি সম্পর্কিত ডেটা সহ আপনার টিভির কল লগ পরিবর্তন করতে দেয়৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি এটিকে আপনার কল লগ মুছে দিতে বা পরিবর্তন করতে ব্যবহার করতে পারে৷" "ইনকামিং ও আউটগোয়িং কলগুলি সম্পর্কিত ডেটা সহ আপনার ফোনের কল লগ পরিবর্তন করতে দেয়৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি এটিকে আপনার কল লগ মুছে দিতে বা পরিবর্তন করতে ব্যবহার করতে পারে৷" - "শরীরের সেন্সর (হার্ট রেট মনিটারের মত)" + "শরীরের সেন্সর (হার্ট রেট মনিটারের মত) অ্যাক্সেস করুন" "অ্যাপ্লিকেশানটিকে আপনার শারীরিক অবস্থা যেমন, আপনার হৃৎস্পন্দন পর্যবেক্ষণ করে এমন সেন্সরগুলি অ্যাক্সেস করতে মঞ্জুরি দেয়।" "ক্যালেন্ডার ইভেন্ট, তার সাথে গোপন তথ্যও পড়ে" "আপনার ট্যাবলেটে সঞ্চিত সমস্ত ক্যালেন্ডার ইভেন্ট পড়তে অ্যাপ্লিকেশানটিকে মঞ্জুর করে, এর মধ্যে বন্ধু ও সহকর্মীদেরগুলিও অন্তর্ভুক্ত৷ এটি গোপনীয়তা বা সংবেদনশীলতা নির্বিশেষে আপনার ক্যালেন্ডার ডেটা ভাগ ও সংরক্ষণ করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করতে পারে৷" @@ -336,15 +336,15 @@ "সেইসকল বন্ধু বা সহকর্মী সহ আপনি আপনার ফোনে যে ইভেন্টগুলি সংশোধন করতে পারেন তা যুক্ত করাতে, সরাতে, পরিবর্তন করতে এই অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ এটি অ্যাপ্লিকেশানটিকে বার্তা পাঠাতে দেয় যা দেখে মনে হবে যে এটি ক্যালেন্ডার মালিকদের থেকে এসেছে অথবা মালিককে না জানিয়ে ইভেন্টগুলি পরিবর্তন করতে দিতে পারে৷" "অতিরিক্ত অবস্থান প্রদানকারী কমান্ডগুলি অ্যাক্সেস করে" "অবস্থানের সাথে সম্পর্কিত তথ্য প্রদানকারীর অতিরিক্ত কম্যান্ডগুলিকে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এটি অ্যাপ্লিকেশানটিকে GPS অথবা অন্যান্য অবস্থান নির্ণয়ের সাথে সম্পর্কিত উৎসগুলির ক্রিয়াপ্রণালীর নিয়ন্ত্রণকে মঞ্জুর করতে পারে৷" - "সুনির্দিষ্ট অবস্থান (GPS এবং নেটওয়ার্ক ভিত্তিক)" + "সুনির্দিষ্ট অবস্থান (GPS এবং নেটওয়ার্ক-ভিত্তিক) অ্যাক্সেস করুন" "গ্লোবাল পজিশনিং সিস্টেম (GPS) অথবা সেল টাওয়ার ও Wi-Fi এর মতো নেটওয়ার্কের অবস্থান উৎসগুলি ব্যবহার করে আপনার যথাযথ অবস্থান নির্ণয় করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এই অবস্থান নির্ণয়ের সাথে সম্পর্কিত পরিষেবাগুলিকে চালু করে রাখতে হবে এবং অ্যাপ্লিকেশানটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার ডিভাইসে উপলব্ধ করে রাখতে হবে৷ অ্যাপ্লিকেশানগুলি আপনার অবস্থান নির্ণয়ের কাজে এগুলির ব্যবহার করতে পারে, এবং এর জন্য অতিরিক্ত ব্যাটারি পাওয়ার লাগতে পারে৷" - "আনুমানিক অবস্থান (নেটওয়ার্ক ভিত্তিক)" + "আনুমানিক অবস্থান (নেটওয়ার্ক-ভিত্তিক) অ্যাক্সেস করুন" "আপনার আনুমানিক অবস্থান নির্ণয় করতে অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷ এই অবস্থান নির্ণয় সেল টাওয়ার ও Wi-Fi এর মতো নেটওয়ার্কের অবস্থান উৎসগুলি ব্যবহার করে অবস্থান নির্ধারণের সাথে সম্পর্কিত পরিষেবাগুলি থেকে নেওয়া হয়ে থাকে৷ এই অবস্থান নির্ণয়ের সাথে সম্পর্কিত পরিষেবাগুলিকে চালু করে রাখতে হবে এবং অ্যাপ্লিকেশানটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার ডিভাইসে উপলব্ধ করে রাখতে হবে৷ অ্যাপ্লিকেশানগুলি আপনার আনুমানিক অবস্থান নির্ণয়ের কাজে এগুলির ব্যবহার করতে পারে৷" "আপনার অডিও সেটিংস পরিবর্তন করে" "ভলিউম এবং যেখানে স্পিকার আউটপুট সামগ্রী হিসাবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷" "অডিও রেকর্ড করে" "অ্যাপ্লিকেশানটিকে মাইক্রোফোনের দ্বারা অডিও রেকর্ড করার অনুমতি দেয়৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে আপনার অনুমোদন ছাড়া যেকোনো সময় অডিও রেকর্ড করার অনুমতি দেয়৷" - "sim যোগাযোগ" + "SIM এ আদেশগুলি পাঠান" "অ্যাপ্লিকেশানটিকে সিম কার্ডে কমান্ডগুলি পাঠানোর অনুমতি দেয়৷ এটি খুবই বিপজ্জনক৷" "ছবি এবং ভিডিও তোলে" "ক্যামেরার সাহায্যে ছবি তুলতে ও ভিডিও তৈরি করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে আপনার নিশ্চয়তা ছাড়াই যেকোনো সময় ক্যামেরা ব্যবহার করতে মঞ্জুর করে৷" @@ -382,7 +382,7 @@ "ফোনটির মেমরিতে থাকা অ্যাকাউন্টের তালিকাটি পেতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এতে আপনার দ্বারা ইনস্টল করা অ্যাপ্লিকেশানগুলির মাধ্যমে তৈরি যেকোনো অ্যাকাউন্ট অন্তর্ভুক্ত হতে পারে৷" "নেটওয়ার্ক সংযোগগুলি দেখুন" "কোন নেটওয়ার্কগুলি বিদ্যমান এবং সংযুক্ত রয়েছে তার তথ্য দেখার জন্য অ্যাপ্লিকেশানটিকে অনুমতি প্রদান করে৷" - "সম্পূর্ণ নেটওয়ার্ক অ্যাক্সেস" + "সম্পূর্ণ নেটওয়ার্ক অ্যাক্সেস রয়েছে" "নেটওয়ার্ক সকেটগুলি তৈরি করতে এবং কাস্টম নেটওয়ার্ক প্রোটোকলগুলি ব্যবহার করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ ব্রাউজার ও অন্যান্য অ্যাপ্লিকেশানগুলি ইন্টারনেটে ডেটা প্রেরণ করার উপায় সরবরাহ করে, তাই ইন্টারনেটে ডেটা প্রেরণ করতে এই অনুমতিটির প্রয়োজন হয় না৷" "নেটওয়ার্ক সংযোগ পরিবর্তন করে" "অ্যাপ্লিকেশানকে নেটওয়ার্ক সংযোগ অবস্থা পরিবর্তন করার অনুমতি দেয়৷" @@ -402,7 +402,7 @@ "অ্যাপ্লিকেশানটিকে স্থানীয় Bluetooth ফোনটিকে কনফিগার এবং দূরবর্তী ডিভাইসগুলি আবিষ্কার এবং এর সাথে যুক্ত করতে দেয়৷" "WiMAX এর সাথে সংযুক্ত হন বা সংযোগ বিচ্ছিন্ন করুন" "অ্যাপ্লিকেশানটিকে WiMAX সক্ষম করা আছে কিনা সে বিষয়ে নিশ্চিত হতে এবং সংযুক্ত যেকোনো WiMAX নেটওয়ার্ক সম্পর্কিত তথ্য সম্বন্ধে নিশ্চিত হওয়ার অনুমতি প্রদান করে৷" - "WiMAX এর স্থিতি পরিবর্তন করুন" + "WiMAX এর স্থিতি পরিবর্তন করুন" "WiMAX নেটওয়ার্কগুলির সাথে ট্যাবলেটটির সংযোগ স্থাপন করতে এবং সংযোগ বিচ্ছিন্ন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷" "টিভিকে WiMAX এ সংযোগ করতে এবং সংযোগ বিচ্ছিন্ন করার কাজটি করতে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷" "WiMAX নেটওয়ার্কগুলির সাথে ফোনটির সংযোগ স্থাপন করতে এবং সংযোগ বিচ্ছিন্ন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷" @@ -485,7 +485,7 @@ "অ্যাপ্লিকেশানকে টাচ স্ক্রীণের ক্রমাঙ্গন প্যারামিটার সংশোধন করতে দেয়৷ সাধারণ অ্যাপ্লিকেশানগুলির জন্য দরকারী নয়৷" "DRM শংসাপত্রগুলি অ্যাক্সেস করে" "DRM শংসাপত্রগুলির বিধান এবং ব্যবহারা করার অনুমতি দিন৷ সাধারণ অ্যাপ্লিকেশানগুলির জন্য কোনোদিন প্রয়োজন হয় না৷" - "Android বীম স্থানান্তর স্থিতি গ্রহণ করুন" + "Android বীম স্থানান্তর স্থিতি গ্রহণ করুন" "এই অ্যাপ্লিকেশানকে বর্তমান Android বীম স্থানান্তর সম্বন্ধে তথ্য গ্রহণ করার অনুমিত দেয়" "DRM শংসাপত্রগুলি সরান" "কোনো অ্যাপ্লিকেশানকে DRM শংসাপত্রগুলি সরানোর অনুমতি দেয়। সাধারণ অ্যাপ্লিকেশানগুলির জন্য কখনো প্রয়োজন হয় না।" @@ -1091,11 +1091,11 @@ "ফরম্যাট করা হচ্ছে..." "ঢোকানো হয় নি" "কোনো সমরূপ কার্যকলাপ খুঁজে পাওয়া যায়নি৷" - "মিডিয়া আউটপুট রুট করুন" + "মিডিয়া আউটপুট রুট করুন" "অ্যাপ্লিকেশানটিকে অন্যান্য বহিরাগত ডিভাইসে মিডিয়া আউটপুট রুট করার অনুমতি দেয়৷" - "ইনস্টল সেশন পড়ুন" + "ইনস্টল সেশন পড়ুন" "কোনো অ্যাপ্লিকেশানকে সেশনগুলি পড়ার অনুমতি দেয়। এটি সক্রিয় প্যাকেজ ইনস্টলেশনের বিশদ বিবরণ দেখতে দেয়।" - "প্যাকেজগুলি ইনস্টল করার অনুরোধ" + "প্যাকেজগুলি ইনস্টল করার অনুরোধ" "একটি অ্যাপ্লিকেশানকে প্যাকেজগুলির ইনস্টল করার অনুরোধ জানাতে অনুমতি দেয়৷" "জুম নিয়ন্ত্রণের জন্য দুবার স্পর্শ করুন" "উইজেট যোগ করা যায়নি৷" diff --git a/core/res/res/values-br-rFR/cm_strings.xml b/core/res/res/values-br-rFR/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-br-rFR/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-br-rFR/strings.xml b/core/res/res/values-br-rFR/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-br-rFR/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-bs-rBA/cm_strings.xml b/core/res/res/values-bs-rBA/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-bs-rBA/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml new file mode 100644 index 0000000000000..58b884b1c46df --- /dev/null +++ b/core/res/res/values-bs-rBA/strings.xml @@ -0,0 +1,1627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ca-watch/strings.xml b/core/res/res/values-ca-watch/strings.xml index b44703ee8134d..1d2d96e126737 100644 --- a/core/res/res/values-ca-watch/strings.xml +++ b/core/res/res/values-ca-watch/strings.xml @@ -21,4 +21,5 @@ "Aplicació %1$d de %2$d." + "Sensors" diff --git a/core/res/res/values-ca/cm_strings.xml b/core/res/res/values-ca/cm_strings.xml new file mode 100644 index 0000000000000..38d14a514a94d --- /dev/null +++ b/core/res/res/values-ca/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Captura de pantalla + + rebre SMS protegits + + Permet a l\'aplicació rebre un SMS entrant protegit. + + modifica la llista d\'SMS protegits + + Permet a l\'aplicació modificar la llista d\'adreces d\'SMS protegits. + + Seguretat + + Permisos relacionats amb la informació de seguretat del dispositiu. + + llegeix la llista negra del telèfon + + Permet a una aplicació llegir informació sobre números de telèfon que estan bloquejats per a trucades entrants o missatges. + + canvia la llista negra del telèfon + + Permet a una aplicació canviar els números de telèfon que estan bloquejats per a trucades entrants o missatges. + + estableix el fons de la pantalla de bloqueig + + Permet que una aplicació estableixi el fons de la pantalla de bloqueig. + + Reinicia + + Actual + + + Reinicia + + Recuperació + + Bootloader + + Descàrrega + + Reinici ràpid + + Reinicia + + La teva tauleta es reiniciarà. + El teu telèfon es reiniciarà. + + S\'està reiniciant\u2026 + + Aplicació matada + + ADB sobre xarxa habilitat + + ADB sobre USB i xarxa habilitat + + Toca per deshabilitar la depuració. + + ADB - %1$s + USB & xarxa + USB + Xarxa + + interceptar el llançament d\'una aplicació + + %s no està instal·lat + + Prioritat + Cap + + S\'ha deshabilitat el punt d\'accés Wi-Fi degut a un canvi en la subscripció de la SIM + + Apaga el Wi-Fi + + activa o desactiva el guarda de privacitat + Permet a l\'aplicació fer el canvi d\'estat de privacitat d\'una altra aplicació. Quan una aplicació s\'executa amb el guarda de privacitat, no tindrà accés a les dades personals com els contactes, registres de trucades, o missatges. + Guarda de privacitat actiu + %1$s no tindrà accés a dades personals + Guarda de privacitat + %1$s voldria %2$s. + + Recorda la meva elecció + + accedir a la càmera + accedir a la teva ubicació + llegir les teves notificacions + activa una VPN + iniciar-se a l\'engegar + esborrar el teu registre de trucades + esborrar els teus contactes + esborrar els teus missatges MMS + esborrar els teus missatges SMS + dibuixar finestres en primer pla + obtenir estadístiques d\'ús d\'aplicacions + mantenir el teu dispositiu encès + fer una trucada + actualitzar el teu calendari + actualitzar el registre de trucades + modificar el portapapers + actualitzar els teus contactes + actualitza la configuració del sistema + silencia/encen el micròfon + reproduir so + publicar una notificació + projectar contingut multimèdia + llegir el teu calendari + llegir el registre de trucades + llegir el portapapers + llegir els teus contactes + llegir els teus missatges MMS + llegir els teus missatges SMS + rebre un missatge SMS + enregistrar so + enviar un missatge MMS + enviar un missatge SMS + iniciar-se a l\'engegar + mostra missatges emergents + canviar el Bluetooth + commuta les dades mòbils + canviar NFC + canviar Wi-Fi + controlar el volum de l\'alarma + controlar el focus del so + controlar el volum del Bluetooth + controlar el volum principal + utilitzar els botons multimèdia + controlar el volum multimèdia + controlar el volum de les notificacions + controlar el volum del to de trucada + utilitzar resposta hàptica + controlar el volum de la veu de la trucada + escriure un missatge MMS + escriure un missatge SMS + utilitzar l\'empremta digital + afegir un missatge de veu + accedir a l\'estat del telèfon + escannejar xarxes Wi-Fi + canviar el fons de pantalla + utilitzar estructures d\'assistència + prendre una captura de pantalla + utilitzar sensors pel cos + llegir radio difusions + simular l\'ubicació + llegir d\'un emmagatzematge extern + escriure en un emmagatzematge extern + encendre la pantalla + obtenir els comptes del dispositiu + canviar l\'estat del Wi-Fi + obtenir accés de superusuari + + Per desancorar aquesta pantalla, toca i aguanta el botó Enrera. + + Cap dispositiu connectat + %1$s dispositiu connectat + %1$s dispositius connectats + + + + Execució de l\'activitat bloquejada + %1$s està protegit de ser executada. Clica per autentificar i executar l\'aplicació. + + Bateria completament carregada + Desconnecta el teu dispositiu del carregador per millorar la longevitat de la bateria. + + reinicia les estadístiques de la bateria + + Permet a una aplicació reiniciar les dades actuals de baix nivell d\'us de la bateria. + + Les targetes SIM s\'han canviat + Pica per establir les preferències de la targeta SIM predeterminada + diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 7d973a75e2ebd..c21680f3f1cd6 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -254,7 +254,7 @@ "Inclou dades personals com ara números de targetes de crèdit i contrasenyes." "desactivar o modificar la barra d\'estat" "Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema." - "barra d\'estat" + "aparèixer a la barra d\'estat" "Permet que l\'aplicació sigui la barra d\'estat." "desplega/contrau la barra d\'estat" "Permet que l\'aplicació desplegui o replegui la barra d\'estat." @@ -282,7 +282,7 @@ "Permet que l\'aplicació rebi i processi missatges WAP. Aquest permís inclou la capacitat de controlar o de suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls." "recupera les aplicacions en execució" "Permet que l\'aplicació recuperi informació sobre les tasques que s\'executen actualment i les que s\'han executat recentment. Aquesta acció pot permetre que l\'aplicació descobreixi informació sobre les aplicacions que s\'utilitzen al dispositiu." - "Gestionar els propietaris del perfil i del dispositiu" + "gestionar els propietaris del perfil i del dispositiu" "Permet que les aplicacions defineixin els propietaris del perfil i del dispositiu." "canvia l\'ordre de les aplicacions en execució" "Permet que l\'aplicació desplaci tasques en primer o segon pla. L\'aplicació pot fer-ho sense que tu ho indiquis." @@ -324,7 +324,7 @@ "Permet que l\'aplicació modifiqui el registre de trucades de la teva tauleta, incloses les dades de les trucades entrants i sortints. És possible que les aplicacions malicioses ho utilitzin per eliminar o per modificar el teu registre de trucades." "Permet que l\'aplicació modifiqui el registre de trucades del televisor, com ara les dades de les trucades entrants i sortints. És possible que les aplicacions malicioses l\'utilitzin per esborrar o modificar les dades del registre de trucades." "Permet que l\'aplicació modifiqui el registre de trucades del teu telèfon, incloses les dades de les trucades entrants i sortints. És possible que les aplicacions malicioses ho utilitzin per eliminar o per modificar el teu registre de trucades." - "sensors corp. (monitors freq. cardíaca)" + "accedir a sensors corporals (p. ex., monitors de freqüència cardíaca)" "Permet que l\'aplicació accedeixi a les dades dels sensors que supervisen el teu estat físic, com ara la freqüència cardíaca." "llegeix els esdeveniments del calendari més informació confidencial" "Permet que l\'aplicació llegeixi tots els esdeveniments del calendari emmagatzemats a la tauleta, inclosos els dels amics o dels companys de feina. Aquesta acció pot permetre que l\'aplicació comparteixi o desi les dades del teu calendari, sense tenir en compte la confidencialitat." @@ -336,15 +336,15 @@ "Permet que l\'aplicació afegeixi, elimini o canviï esdeveniments que pots modificar al telèfon, inclosos els d\'amics o de companys de feina. Aquesta acció pot permetre que l\'aplicació enviï missatges que sembli que provinguin dels propietaris del calendari o que modifiqui esdeveniments sense el coneixement dels propietaris." "accedir a ordres del proveïdor d\'ubicació addicionals" "Permet que l\'aplicació accedeixi a ordres addicionals del proveïdor d\'ubicacions; per tant, és possible que l\'aplicació pugui interferir en el funcionament del GPS o d\'altres fonts d\'ubicacions." - "ubicació precisa (basada en GPS i xarxa)" + "accedir a la ubicació precisa (basada en el GPS i en la xarxa)" "Permet que l\'aplicació obtingui la teva ubicació precisa mitjançant un sistema de posicionament global (GPS) o fonts d\'ubicació de xarxa, com ara torres de telefonia mòbil i Wi-Fi. Aquests serveis d\'ubicació s\'han d\'activar i han d\'estar disponibles al dispositiu perquè l\'aplicació els pugui fer servir. Les aplicacions poden utilitzar aquestes dades per determinar aproximadament on et trobes i pot ser que consumeixin més bateria." - "ubicació aproximada (basada en xarxa)" + "accedir a la ubicació aproximada (basada en la xarxa)" "Permet que l\'aplicació obtingui la teva ubicació aproximada. Aquesta ubicació prové dels serveis d\'ubicació que utilitzen fonts d\'ubicació de la xarxa, com ara torres de telefonia mòbil i Wi-Fi. Aquests serveis d\'ubicació s\'han d\'activar i han d\'estar disponibles al dispositiu perquè l\'aplicació els pugui fer servir. Les aplicacions poden utilitzar aquestes dades per determinar aproximadament on et trobes." "canviar la configuració d\'àudio" "Permet que l\'aplicació modifiqui la configuració d\'àudio general, com ara el volum i l\'altaveu de sortida que es fa servir." "enregistrar àudio" "Permet que l\'aplicació enregistri àudio amb el micròfon. Aquest permís permet que l\'aplicació enregistri àudio en qualsevol moment sense la teva confirmació." - "comunicació SIM" + "enviar ordres a la SIM" "Permet que l\'aplicació enviï ordres a la SIM. Això és molt perillós." "fer fotos i vídeos" "Permet que l\'aplicació faci fotos i vídeos amb la càmera. Aquest permís permet que l\'aplicació utilitzi la càmera en qualsevol moment sense la teva confirmació." @@ -382,7 +382,7 @@ "Permet que l\'aplicació obtingui la llista de comptes coneguts pel telèfon. Això pot incloure tots els comptes que hagin creat les aplicacions que tens instal·lades." "veure connexions de xarxa" "Permet que l\'aplicació visualitzi informació sobre connexions de xarxa, com ara quines xarxes hi ha i quines estan connectades." - "accés total a la xarxa" + "tenir accés complet a la xarxa" "Permet que l\'aplicació creï sòcols de xarxa i que utilitzi protocols de xarxa personalitzats. El navegador i altres aplicacions proporcionen mitjans per enviar dades a Internet, de manera que aquest permís no és obligatori per enviar-n\'hi." "canviar la connectivitat de xarxa" "Permet que l\'aplicació pugui canviar l\'estat de connectivitat de la xarxa." @@ -402,7 +402,7 @@ "Permet que l\'aplicació configuri el telèfon Bluetooth local i que detecti dispositius remots i s\'hi vinculi." "connecta i desconnecta de WiMAX" "Permet que l\'aplicació determini si WiMAX està activat i que vegi la informació sobre totes les xarxes WiMAX que estan connectades." - "Canvia l\'estat de WiMAX" + "canvia l\'estat de WiMAX" "Permet que l\'aplicació connecti i desconnecti la tauleta de les xarxes WiMAX." "Permet que l\'aplicació connecti el televisor a xarxes WiMAX, o bé que el desconnecti." "Permet que l\'aplicació connecti i desconnecti el telèfon de les xarxes WiMAX." @@ -485,7 +485,7 @@ "Permet que l\'aplicació modifiqui els paràmetres de calibratge de la pantalla tàctil. No ha de ser mai necessari per a aplicacions normals." "accedir als certificats de DRM" "Permet que una aplicació proporcioni i utilitzi certificats de gestió de drets digitals (DRM, Digital Rights Management). No ha de ser mai necessari per a aplicacions normals." - "Rep l\'estat de la transferència d\'Android Beam" + "rebre l\'estat de la transferència d\'Android Beam" "Permet que aquesta aplicació rebi informació sobre les transferències d\'Android Beam actuals." "suprimir els certificats DRM" "Permet que una aplicació suprimeixi els certificats DRM. No ha de ser mai necessari per a aplicacions normals." @@ -1091,11 +1091,11 @@ "S\'està formatant..." "No s\'ha inserit" "No s\'ha trobat cap activitat coincident." - "Indicació de ruta de sortida de contingut multimèdia" + "indicar la sortida del fitxer multimèdia" "Permet que una aplicació indiqui la ruta de sortida de contingut multimèdia a altres dispositius externs." - "Lectura de les instal·lacions de sessió" + "llegir les sessions d\'instal·lació" "Permet que una aplicació llegeixi les sessions d\'instal·lació i això permet veure detalls sobre les instal·lacions de paquet actives." - "Sol·licitar la instal·lació de paquets" + "sol·licitar la instal·lació de paquets" "Permet que una aplicació sol·liciti la instal·lació de paquets." "Toca dos cops per controlar el zoom" "No s\'ha pogut afegir el widget." diff --git a/core/res/res/values-cs-watch/strings.xml b/core/res/res/values-cs-watch/strings.xml index 89c9dee7324ab..c0871735422d6 100644 --- a/core/res/res/values-cs-watch/strings.xml +++ b/core/res/res/values-cs-watch/strings.xml @@ -21,4 +21,5 @@ "Aplikace %1$d%2$d." + "Senzory" diff --git a/core/res/res/values-cs/cm_strings.xml b/core/res/res/values-cs/cm_strings.xml new file mode 100644 index 0000000000000..acfb108a5f017 --- /dev/null +++ b/core/res/res/values-cs/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Snímek obrazovky + + přijímat chráněné SMS + + Umožňuje přijímat příchozí chráněné SMS. + + upravit seznam chráněných SMS + + Umožňuje aplikaci upravit seznam adres chráněných SMS. + + Zabezpečení + + Oprávnění vztahující se k informacím o zabezpečení zařízení. + + čtení černé listiny telefonu + + Umožňuje čtení informací o telefonních číslech, která jsou blokována pro příjem hovorů nebo zpráv. + + změnit černou listinu telefonu + + Umožňuje změnit telefonní čísla, která jsou blokována pro příjem hovorů nebo zpráv. + + nastavit tapetu zámku kláves + + Umožní změnit tapetu zámku obrazovky. + + Restartovat + + Aktuální + + + Reboot + + Recovery + + Bootloader + + Download + + Soft reboot + + Restartovat + + Tablet bude restartován. + Telefon bude restartován. + + Restart\u2026 + + Aplikace byla ukončena + + ADB po síti povoleno + + ADB přes USB a po síti povoleno + + Dotykem zakázat ladění. + + ADB - %1$s + USB a síť + USB + Síť + + zachytit spuštění aplikace + + Aplikace %s není nainstalována + + Priorita + Žádný + + Hotspot Wi\u2011Fi byl kvůli změně připojení SIM vypnut + + Vypnout Wi\u2011Fi + + povolit či zakázat Ochranu soukromí + Umožní změnit pravidla, zda bude některá aplikace spuštěna v režimu Ochrany soukromí. Pokud je aplikace spuštěna v režimu Ochrany soukromí, tato aplikace nemá umožněn přístup k osobním datům jako jsou kontakty, historie volání nebo zprávy. + Ochrana soukromí aktivní + Aplikaci %1$s nebude umožněn přístup k osobním údajům + Ochrana soukromí + Aplikace %1$s se pokouší %2$s. + + Zapamatovat si volbu + + používat fotoaparát + zjišťovat polohu + číst upozornění + aktivovat VPN + spustit při startu + smazat historii hovorů + smazat kontakty + smazat MMS zprávy + smazat SMS zprávy + vykreslit okna navrchu + získat statistiky využití aplikace + udržovat zařízení probuzené + vytvářet telefonní hovory + měnit kalendář + měnit výpisy hovorů + měnit schránku + měnit kontakty + aktualizovat systémové nastavení + vypnout/zapnout mikrofon + přehrávat zvuk + posílat upozornění + promítání médií + číst kalendář + číst výpisy hovorů + číst schránku + číst kontakty + číst zprávy MMS + číst zprávy SMS + přijímat zprávy SMS + nahrávat zvuk + zaslat zprávu MMS + zaslat zprávu SMS + spustit při startu + zobrazovat vyskakovací upozornění + přepnout Bluetooth + vypnout/zapnout mobilní data + přepnout NFC + přepnout Wi\u2011Fi + ovládat hlasitost budíku + ovládat zvukové zdroje + ovládat hlasitost Bluetooth + ovládat hlavní hlasitost + použít mediální tlačítka + ovládat hlasitost médií + ovládat hlasitost upozornění + ovládat hlasitost vyzvánění + použít hmatovou odezvu + ovládat hlasitost hovoru + zapsat zprávu MMS + zapsat zprávu SMS + použít otisk prstu + přidat hlasovou zprávu + přístup ke stavu telefonu + prohledávání Wi\u2011Fi sítí + změnit tapetu + použít asistenční strukturu + sejmout obrazovku + použít senzory těla + přečíst zprávy buněk GSM + zfalšovat polohu + přečíst externí úložiště + zapsat na externí úložiště + zapnout obrazovku + získat účty zařízení + změna stavu Wi\u2011Fi + získat root přístup + + Chcete-li odebrat tuto obrazovku, podržte tlačítko Zpět. + + Žádné připojené zařízení + %1$s připojené zařízení + %1$s připojená zařízení + + + + Spuštění aktivity zablokováno + %1$s je chráněna před spuštěním. Dotykem autorizovat spuštění aplikace. + + Baterie je nabitá + Pro zlepšení životnosti baterie odpojte zařízení od nabíječky. + + obnovení statistiky baterie + + Umožní provést obnovení/vyčištění informací o využívání baterie. + + Byly vyměněny SIM karty + Dotykem nastavit výchozí předvolby SIM karty + diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 03f341d9921b3..a2f7b343eedc0 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -256,7 +256,7 @@ "Sledování zahrnuje osobní údaje, jako jsou například čísla kreditních karet a hesla." "zakázání či změny stavového řádku" "Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony." - "stavový řádek" + "vydávání se za stavový řádek" "Umožňuje aplikaci být stavovým řádkem." "rozbalení a sbalení stavového řádku" "Umožňuje aplikaci rozbalit či sbalit stavový řádek." @@ -284,7 +284,7 @@ "Umožňuje aplikaci přijmout a zpracovat zprávy WAP. Toto oprávnění umožňuje sledovat přijaté zprávy nebo je smazat, aniž by se vám zobrazily." "načtení spuštěných aplikací" "Umožňuje aplikaci získat informace o aktuálně a naposledy spuštěných úlohách. Aplikace s tímto oprávněním může odhalit informace o aplikacích, které se v zařízení používají." - "Správa vlastníků profilu a zařízení" + "správa vlastníků profilu a zařízení" "Umožňuje aplikacím nastavit vlastníky profilu a vlastníka zařízení." "změna uspořádání spuštěných aplikací" "Umožňuje aplikaci přesunout úlohy na popředí nebo pozadí. Aplikace tak může činit bez vašeho zásahu." @@ -326,7 +326,7 @@ "Umožňuje aplikaci upravovat seznam hovorů vašeho tabletu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů." "Umožňuje aplikaci upravovat seznam hovorů vaší televize včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů." "Umožňuje aplikaci upravovat seznam hovorů vašeho telefonu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů." - "tělesné senzory (například snímače tepu)" + "přístup k tělesným senzorům (např. snímače tepu)" "Umožňuje aplikaci používat data ze senzorů, které sledují vaši fyzickou kondici, například tepovou frekvenci." "čtení událostí kalendáře a důvěrné informace" "Umožňuje aplikaci číst všechny události kalendáře uložené v tabletu, včetně událostí přátel nebo spolupracovníků. Aplikace s tímto oprávněním může sdílet nebo ukládat údaje v kalendáři bez ohledu na důvěrnost nebo citlivost těchto údajů." @@ -338,15 +338,15 @@ "Umožňuje aplikaci přidat, odebrat nebo změnit události, které můžete v telefonu upravovat, a to včetně událostí přátel a spolupracovníků. Toto oprávnění umožňuje aplikaci odesílat zprávy, které budou zdánlivě přicházet od vlastníků kalendářů, nebo upravovat události bez vědomí vlastníků." "přístup k dalším příkazům poskytovatele polohy" "Umožňuje aplikaci přístup k dalším příkazům poskytovatele polohy. To aplikaci umožní zasahovat do fungování systému GPS a dalších zdrojů polohy." - "přesná poloha (pomocí GPS a sítě)" + "přístup k přesné poloze (pomocí GPS a sítě)" "Umožňuje aplikaci zjistit vaši přesnou polohu pomocí systému GPS nebo síťových lokalizačních zdrojů, jako jsou vysílače mobilní sítě a sítě Wi-Fi. Aby aplikace mohla služby určování polohy použít, musejí být zapnuté a musejí být v zařízení k dispozici. Aplikace pomocí těchto informací mohou určit vaši přesnou polohu a mohou spotřebovávat více energie z baterie." - "přibližná poloha (pomocí sítě)" + "přístup k přibližné poloze (pomocí sítě)" "Umožňuje aplikaci získat vaši přibližnou polohu. Polohu stanovují služby určování polohy pomocí síťových zdrojů, jako jsou vysílače mobilních sítí a sítě Wi-Fi. Aby aplikace mohla služby určování polohy použít, musejí být zapnuté a musejí být ve vašem zařízení k dispozici. Aplikace na základě těchto informací mohou zjistit vaši přibližnou polohu." "změna nastavení zvuku" "Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro výstup zvuku." "nahrávání zvuku" "Umožňuje aplikaci zaznamenat zvuk pomocí mikrofonu. Toto oprávnění umožňuje aplikaci kdykoliv zaznamenat zvuk bez vašeho svolení." - "komunikace s kartou SIM" + "odesílání příkazů do SIM karty" "Umožňuje aplikaci odesílat příkazy na kartu SIM. Toto oprávnění je velmi nebezpečné." "pořizování fotografií a videí" "Umožňuje aplikaci pořizovat fotografie a videa pomocí fotoaparátu. Toto oprávnění umožňuje aplikaci používat fotoaparát kdykoliv i bez vašeho svolení." @@ -384,7 +384,7 @@ "Umožňuje aplikaci získat seznam účtů v telefonu. Mohou sem patřit i účty vytvořené aplikacemi, které jste nainstalovali." "zobrazování síťových připojení" "Umožňuje aplikaci zobrazit informace o síťových připojeních, například o tom, které sítě jsou k dispozici a které jsou připojené." - "úplný přístup k síti" + "úplný přístup k síti" "Umožňuje aplikaci vytvářet síťové sokety a používat vlastní síťové protokoly. K odesílání údajů na internet toto oprávnění není nutné, protože údaje lze na internet odesílat prostřednictvím prohlížečů a dalších aplikací." "změna připojení k síti" "Umožňuje aplikaci změnit stav připojení k síti." @@ -404,7 +404,7 @@ "Umožňuje aplikaci konfigurovat místní telefon s rozhraním Bluetooth a vyhledávat a párovat vzdálená zařízení." "připojení a odpojení od sítě WiMAX" "Umožňuje aplikaci zjistit, zda je povoleno připojení WiMAX, a také získat informace o všech připojených sítích WiMAX." - "Změnit stav připojení WiMAX" + "měnit stav připojení WiMAX" "Umožňuje aplikaci připojovat tablet k sítím WiMAX a odpojovat jej od nich." "Umožňuje aplikaci připojovat televizi k sítím WiMAX a také ji od nich odpojovat." "Umožňuje aplikaci připojovat telefon k sítím WiMAX a odpojovat jej od nich." @@ -487,7 +487,7 @@ "Umožňuje aplikaci měnit parametry kalibrace dotykové obrazovky. Běžné aplikace by toto oprávnění neměly nikdy potřebovat." "přístup k certifikátům DRM" "Umožňuje aplikaci vydávat a používat certifikáty DRM. Běžné aplikace by toto oprávnění neměly nikdy potřebovat." - "Příjem stavu přenosů Android Beam" + "příjem stavu přenosů Android Beam" "Umožňuje této aplikaci přijímat informace o aktuálních přenosech pomocí technologie Android Beam" "odstranění certifikátů DRM" "Povoluje aplikaci odstranit certifikáty DRM. Běžné aplikace by toto oprávnění neměly nikdy potřebovat." @@ -1105,11 +1105,11 @@ "Formátování..." "Není vloženo" "Nebyly nalezeny žádné odpovídající aktivity." - "Směrování výstupu médií" + "směrování výstupu médií" "Umožňuje aplikaci směrovat výstup médií do dalších externích zařízení." - "Čtení instalačních relací" + "čtení instalačních relací" "Povoluje aplikaci číst instalační relace. Díky tomu můžete zobrazit podrobnosti o aktivních instalacích balíčku." - "Žádat o instalaci balíčků" + "odesílání žádostí o přístup k instalačním balíčkům" "Umožňuje aplikaci požádat o instalaci balíčků." "Dvojitým dotykem můžete ovládat přiblížení" "Widget nelze přidat." diff --git a/core/res/res/values-csb-rPL/cm_strings.xml b/core/res/res/values-csb-rPL/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-csb-rPL/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-csb-rPL/strings.xml b/core/res/res/values-csb-rPL/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-csb-rPL/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-cy/cm_strings.xml b/core/res/res/values-cy/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-cy/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-cy/strings.xml b/core/res/res/values-cy/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-cy/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-da-watch/strings.xml b/core/res/res/values-da-watch/strings.xml index f1daf30d5fe79..01014aec31975 100644 --- a/core/res/res/values-da-watch/strings.xml +++ b/core/res/res/values-da-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d af %2$d." + "Sensorer" diff --git a/core/res/res/values-da/cm_strings.xml b/core/res/res/values-da/cm_strings.xml new file mode 100644 index 0000000000000..316be92c83781 --- /dev/null +++ b/core/res/res/values-da/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Skærmbillede + + modtag beskyttet SMS + + Tillader at app\'en kan modtage en indgående beskyttet SMS. + + rediger beskyttet SMS liste + + Tillader at app\'en kan ændre den beskyttede SMS adresseliste. + + Sikkerhed + + Tilladelser vedr. enhedens sikkerhedsinformation. + + læs telefonens sortliste + + Tillader en app at læse informationer om telefonnumre, som er blokerede for indgående opkald eller beskeder. + + ændre telefonens sortliste + + Tillader en app at ændre telefonnumre, som er blokerede for indgående opkald eller beskeder. + + angive baggrund til keyguard + + Tillader en app at ændre baggrund for skærmlåsen. + + Genstart + + Aktuel + + + Genstart + + Recovery + + Bootloader + + Download + + Blød genstart + + Genstart + + Din tablet vil genstarte. + Din telefon vil genstarte. + + Genstarter\u2026 + + App lukket + + ADB via netværk aktiveret + + ADB via USB & netværk aktiveret + + Tryk for at deaktivere fejlretning. + + ADB - %1$s + USB & netværk + USB + Netværk + + afbryd app-opstart + + %s er ikke installeret + + Prioritet + Ingen + + Deaktiverede Wi-Fi hotspot på grund af en ændring af dit SIM abonnement + + Slå Wi-Fi fra + + aktivér eller deaktivér privatlivsvagt + Tillader app\'en at ændre, om en anden app kører med Privatlivsvagt. Når en app kører med Privatlivsvagt, vil den ikke have adgang til personlige data såsom kontakter, opkaldslister eller beskeder. + Privatlivsvagt aktiv + %1$s vil ikke kunne tilgå personlige data + Privatlivsvagt + %1$s ønsker at %2$s. + + Husk mit valg + + tilgå kameraet + tilgå din placering + læse dine meddelelser + aktivér en VPN + starte ved opstart + slet din opkaldsliste + slet dine kontakter + slet dine MMS beskeder + slet dine SMS beskeder + tegn vinduer øverst + få brugsstatistik for app + holde din enhed vågen + foretage opkald + opdatere din kalender + opdatere opkaldslisten + ændre udklipsholderen + opdatere dine kontakter + opdatere systemindstillinger + Slå mikrofon til/fra + afspille lyd + vise en meddelelse + projekt medie + læse din kalender + læse opkaldsliste + læse udklipsholderen + læse dine kontakter + læse dine MMS-beskeder + læse dine SMS-beskeder + modtage en SMS-besked + optage lyd + sende en MMS-besked + sende en SMS-besked + starte ved opstart + vis toast beskeder + tænde/slukke Bluetooth + slå mobildata til/fra + NFC til/fra + Wi-Fi til/fra + kontrollere lydstyrken for alarmer + kontrollere lydfokus + kontrollere lydstyrken for Bluetooth + kontrollere systemlydstyrken + bruge medieknapperne + kontrollere lydstyrken for medier + kontrollere lydstyrken for meddelelser + kontrollere lydstyrken for ringetonen + bruge haptisk feedback + styre lydstyrken for stemmeopkald + skrive en MMS-besked + skrive en SMS-besked + brug fingeraftryk + tilføj en voicemail + tilgå telefon status + skan Wi-Fi-netværk + skift baggrund + brug hjælpe struktur + tag et skærmbillede + brug kropssensorer + læs celle beskeder + immitér din placering + læs eksternt lager + skriv eksternt lager + tænd skærmen + hent enhedskonti + ændre Wi-Fi tilstand + få root-adgang + + For at frigøre denne skærm, tryk og hold Tilbage-knappen nede. + + Ingen tilsluttet enhed + %1$s tilsluttet enhed + %1$s tilsluttede enheder + + + + Aktivitetsstart blokeret + %1$s er beskyttet mod at blive startet. Tryk for at godkende og starte programmet. + + Batteriet er fuldt opladet + Afbryd din enhed fra opladeren for at forbedre batteriets levetid. + + nulstil batteristatistik + + Tillader en app at nulstille den aktuelle statistik over batteriforbruget. + + SIM-kort er ændret + Tryk for at angive standardindstillinger for SIM-kortet + diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 24e1ac11202af..e0365422de6e5 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -254,7 +254,7 @@ "Dette omfatter personlige data såsom kreditkortnumre og adgangskoder." "deaktiver eller rediger statuslinje" "Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner." - "statusbjælke" + "vær statusbjælken" "Tillader, at appen er statusbjælken." "udvid/skjul statuslinje" "Tillader, at appen kan udvide og skjule statusbjælken." @@ -282,7 +282,7 @@ "Tillader, at appen kan modtage og behandle WAP-beskeder. Denne tilladelse omfatter muligheden for at overvåge eller slette de beskeder, der sendes til dig, uden at vise dem til dig." "hente kørende apps" "Tillader, at appen kan hente oplysninger om nuværende og seneste opgaver. Med denne tilladelse kan appen finde oplysninger om, hvilke applikationer der bruges på enheden." - "Administrer profil- og enhedsejere" + "administrer profil- og enhedsejere" "Tillader, at apps konfigurerer profilejerne og enhedens ejer." "omorganisere kørende apps" "Tillader, at appen kan flytte opgaver til forgrunden og baggrunden. Appen kan gøre dette uden din bekræftelse." @@ -324,7 +324,7 @@ "Tillader, at appen ændrer din tablets opkaldsliste, f.eks. data om indgående og udgående opkald. Ondsindede apps kan bruge dette til at slette eller ændre din opkaldsliste." "Giver appen lov til at ændre opkaldslisten på dit tv, herunder data om indgående og udgående opkald. Ondsindede apps kan bruge dette til at slette eller ændre din opkaldsliste." "Tillader, at appen ændrer telefonens opkaldsliste, f.eks. data om indgående og udgående opkald. Ondsindede apps kan bruge dette til at slette eller ændre din opkaldsliste." - "kropssensorer (f.eks. pulsmålere)" + "få adgang til kropssensorer (f.eks. pulsmålere)" "Giver appen adgang til data fra sensorer, der overvåger din fysiske tilstand, f.eks. din puls." "læse kalenderbegivenheder og fortrolige oplysninger" "Tillader, at appen kan læse alle de kalenderbegivenheder, der er gemt på din tablet, f.eks. venners eller kollegers. Med denne tilladelse kan appen dele eller gemme dine kalenderdata, uanset fortrolighed eller følsomhed." @@ -336,15 +336,15 @@ "Tillader, at appen kan tilføje, fjerne og ændre begivenheder, som du kan redigere på din telefon, f.eks. venners eller kollegers. Med denne tilladelse kan appen sende meddelelser, der synes at komme fra ejere af kalendere, eller ændre begivenheder uden ejernes viden." "få adgang til yderligere kommandoer for placeringsudbyder" "Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre placeringskilder." - "præcis placering (GPS- og netværksbaseret)" + "få adgang til nøjagtig placering (baseret på GPS og netværk)" "Tillader, at appen henter din præcise placering ved hjælp af GPS (Global Positioning System) eller netværksplaceringskilder, såsom mobilmaster og Wi-Fi. Disse placeringstjenester skal være aktiverede og tilgængelige på din enhed, for at appen kan bruge dem. Apps kan bruge dette til at fastslå, hvor du er, og kan eventuelt bruge ekstra batterikapacitet." - "omtrentlig position (netværksbaseret)" + "få adgang til omtrentlig placering (netværksbaseret)" "Tillader, at appen henter din omtrentlige placering. Denne placering er udledt via placeringstjenester, der bruger netværksplaceringskilder, som f.eks. mobilmaster og Wi-Fi. Disse placeringstjenester skal være aktiverede og tilgængelige på din enhed, for at appen kan bruge dem. Apps kan bruge dette til at fastslå, hvor du omtrent er." "skifte dine lydindstillinger" "Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output." "optage lyd" "Tillader, at appen kan optage lyd med mikrofonen. Med denne tilladelse kan appen til enhver tid optage lyd uden din bekræftelse." - "SIM-kommunikation" + "send kommandoer til SIM" "Tillader, at appen sender kommandoer til SIM-kortet. Dette er meget farligt." "tage billeder og optage video" "Tillader, at appen kan tage billeder og videoer med kameraet. Med denne tilladelse kan appen til enhver tid bruge kameraet uden din bekræftelse." @@ -382,7 +382,7 @@ "Tillader, at appen kan hente listen over konti, der er kendt af telefonen. Dette kan omfatte alle konti, der er oprettet af de applikationer, som du har installeret." "se netværksforbindelser" "Tillader, at appen kan læse oplysninger om netværksforbindelser, f.eks. eksisterende og forbundne netværk." - "fuld netværksadgang" + "få fuld netværksadgang" "Tillader, at appen kan oprette netværkssockets og bruge tilpassede netværksprotokoller. Browseren og andre applikationer indeholder midler til at sende data til internettet, så med denne tilladelse er der ingen forpligtelse til at sende data til internettet." "skifte netværksforbindelse" "Tillader, at appen kan ændre netværksforbindelsens tilstand." @@ -402,7 +402,7 @@ "Tillader, at appen kan konfigurere den lokale Bluetooth-telefon samt finde og parre med eksterne enheder." "tilslut og afbryd fra WiMAX" "Tillader, at appen kan fastslå, hvorvidt WiMAX er aktiveret, og oplysninger om eventuelle WiMAX-netværk, der er forbundet." - "Skift WiMAX-tilstand" + "skifte WiMAX-tilstand" "Tillader, at appen kan oprette forbindelse fra tabletten og afbryde forbindelsen til tabletten på WiMAX-netværk." "Giver appen lov til at oprette og afbryde fjernsynets forbindelse til WiMAX-netværk." "Tillader, at appen kan oprette forbindelse fra telefonen og afbryde forbindelsen til telefonen på WiMAX-netværk." @@ -485,7 +485,7 @@ "Tillader, at appen ændrer kalibreringsparametrene for berøringsskærmen. Dette bør aldrig være nødvendigt for almindelige apps." "få adgang til DRM-certifikater" "Tillader, at en applikation leverer og anvender DRM-certfikater. Dette bør aldrig være nødvendigt for almindelige apps." - "Modtag staus for Android Beam-overførsler" + "modtag status for Android Beam-overførsler" "Tillader, at applikationen modtager oplysninger om aktuelle Android Beam-overførsler" "fjerne DRM-certifikater" "Tillader, at en app fjerner DRM-certifikater. Dette bør aldrig være nødvendigt for almindelige apps." @@ -1091,11 +1091,11 @@ "Formaterer…" "Ikke isat" "Der blev ikke fundet nogen matchende aktiviteter." - "Viderefør medieoutput" + "viderefør medieoutput" "Tillader, at en applikation viderefører medieoutput til andre eksterne enheder." - "Læs installationssessioner" + "læs installationssessioner" "Tillader, at en applikation læser installationssessioner. Dermed kan applikationen se oplysninger om aktive pakkeinstallationer." - "Anmod om installation af pakker" + "anmod om installation af pakker" "Tillader, at en app anmoder om installation af pakker." "Tryk to gange for zoomstyring" "Widget kunne ikke tilføjes." diff --git a/core/res/res/values-de-watch/strings.xml b/core/res/res/values-de-watch/strings.xml index 52a21bacea31b..db87a0b771b8d 100644 --- a/core/res/res/values-de-watch/strings.xml +++ b/core/res/res/values-de-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d von %2$d" + "Sensoren" diff --git a/core/res/res/values-de/cm_strings.xml b/core/res/res/values-de/cm_strings.xml new file mode 100644 index 0000000000000..5209a36af4db8 --- /dev/null +++ b/core/res/res/values-de/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Bildschirmfoto + + geschützte SMS empfangen + + Ermöglicht der App, eine eingehende geschützte SMS zu empfangen. + + Liste der geschützten SMS ändern + + Ermöglicht der App, die Adressliste der geschützten SMS zu ändern. + + Sicherheit + + Berechtigungen im Zusammenhang mit der Gerätesicherheit. + + Sperrliste lesen + + Ermöglicht der App, gesperrte Telefonnummern für eingehende Anrufe oder Nachrichten zu lesen. + + Sperrliste ändern + + Ermöglicht der App, gesperrte Telefonnummern für eingehende Anrufe oder Nachrichten zu ändern. + + Sperrbildschirm-Hintergrund ändern + + Ermöglicht der App, den Sperrbildschirm-Hintergrund zu ändern. + + Neu starten + + Aktuell + + + Neu starten + + Recovery + + Bootloader + + Download + + Warmstart + + Neu starten + + Ihr Tablet wird neu gestartet. + Ihr Telefon wird neu gestartet. + + Neustart wird durchgeführt\u2026 + + Anwendung beendet + + ADB über Netzwerk aktiviert + + ADB über USB & Netzwerk aktiviert + + Berühren, um Debugging zu deaktivieren. + + ADB: %1$s + USB und Netzwerk + USB + Netzwerk + + App-Start verhindern + + %s ist nicht installiert + + Wichtig + Keine + + Der WLAN-Hotspot wurde aufgrund einer SIM-Abonnementänderung deaktiviert. + + WLAN ausschalten + + Datenschutz aktivieren oder deaktivieren + Ermöglicht der App, den Datenschutz für andere Apps zu aktivieren oder deaktivieren. Eine App mit aktiviertem Datenschutz hat keinen Zugriff auf persönliche Daten wie Kontakte, Nachrichten oder das Anrufprotokoll. + Datenschutz aktiv + %1$s hat keinen Zugriff auf persönliche Daten + Datenschutz + %1$s versucht, %2$s. + + Meine Auswahl merken + + auf die Kamera zuzugreifen + den Standort abzurufen + auf Benachrichtigungen zuzugreifen + ein VPN zu aktivieren + automatisch zu starten + Ihre Anrufliste zu löschen + Ihre Kontakte zu löschen + Ihre MMS-Nachrichten zu löschen + Ihre SMS zu löschen + sich im Vordergrund einzublenden + Nutzungsstatistiken von Apps abrufen + den Ruhezustand zu deaktivieren + Anrufe zu tätigen + Ihren Kalender zu aktualisieren + die Anrufliste zu ändern + die Zwischenablage zu ändern + Kontakte zu ändern + Einstellungen zu ändern + das Mikrofon zu aktivieren/deaktivieren + Audio wiederzugeben + eine Benachrichtigung zu erstellen + Medien zu projizieren + Kalendereinträge zu lesen + die Anrufliste zu lesen + die Zwischenablage zu lesen + Kontakte zu lesen + MMS zu lesen + Ihre SMS zu lesen + eine SMS zu empfangen + Audio aufzuzeichnen + eine MMS zu senden + eine SMS zu senden + beim Einschalten zu starten + Toast-Nachrichten anzuzeigen + Bluetooth ein-/auszuschalten + Mobile Daten ein-/ausschalten + NFC ein-/auszuschalten + WLAN ein-/auszuschalten + die Weckerlautstärke zu ändern + den Audiofokus zu ändern + die Bluetooth-Laustärke zu ändern + die Gesamtlautstärke zu ändern + die Medienschaltflächen zu nutzen + die Medienlautstärke zu ändern + die Benachrichtigungslautstärke zu ändern + die Klingeltonlautstärke zu ändern + den Vibrationsalarm zu steuern + die Sprachlautstärke zu ändern + eine MMS zu schreiben + eine SMS zu schreiben + den Fingerabdruck zu nutzen + eine Sprachnachricht hinzuzufügen + auf Telefon-Status zuzugreifen + WLAN-Netzwerke zu scannen + Hintergrundbild zu ändern + Unterstützungsstruktur zu verwenden + Bildschirmfoto aufzunehmen + Körpersensoren zu verwenden + Cell-Broadcasts zu lesen + Ihren Standort zu simulieren + externen Speicher zu lesen + externen Speicher zu beschreiben + den Bildschirm einzuschalten + Geräte-Konten abzurufen + WLAN-Status zu ändern + Root-Zugriff zu erhalten + + Zum Lösen dieser Ansicht drücken und halten Sie die Zurück-Taste. + + Kein verbundenes Gerät + %1$s verbundenes Gerät + %1$s verbundene Geräte + + + + Start der Aktivität blockiert + %1$s ist vom Starten abgehalten worden. Tippen Sie, um sich zu authentifizieren und die App zu starten. + + Akku vollständig aufgeladen + Trennen Sie Ihr Gerät jetzt vom Ladegerät, um die Lebensdauer des Akkus nicht zu beeinträchtigen. + + Akku-Verlaufsdetails zurücksetzen + + Ermöglicht einer App, die Akku-Verlaufsdetails zurückzusetzen. + + SIM-Karten haben sich geändert + Tippen, um die Standardeinstellungen für die SIM-Karte festzulegen + diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index cf96923f805da..404abdf27eaa3 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -254,7 +254,7 @@ "Einschließlich personenbezogener Daten wie Kreditkartennummern und Passwörter." "Statusleiste deaktivieren oder ändern" "Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen" - "Statusleiste" + "Statusleiste darstellen" "Ermöglicht der App, zur Statusleiste zu werden" "Statusleiste ein-/ausblenden" "Ermöglicht der App, die Statusleiste ein- oder auszublenden" @@ -282,7 +282,7 @@ "Ermöglicht der App, WAP-Nachrichten zu empfangen und zu verarbeiten. Mit der Berechtigung können Nachrichten, die an Sie gesendet wurden, überwacht und gelöscht werden, bevor sie Ihnen angezeigt werden." "Aktive Apps abrufen" "Ermöglicht der App, Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Damit kann die App möglicherweise ermitteln, welche Apps auf Ihrem Gerät zum Einsatz kommen." - "Profilinhaber und Geräteeigentümer verwalten" + "Profilinhaber und Geräteeigentümer verwalten" "Ermöglicht Apps das Einrichten der Profilinhaber und des Geräteeigentümers" "Aktive Apps neu ordnen" "Ermöglicht der App, Aufgaben in den Vorder- und Hintergrund zu verschieben, ohne dass dazu ein Eingreifen Ihrerseits notwendig ist." @@ -324,7 +324,7 @@ "Ermöglicht der App, die Anrufliste Ihres Tablets zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so Ihre Anrufliste löschen oder ändern." "Ermöglicht der App, die Anrufliste Ihres Fernsehers zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so Ihre Anrufliste löschen oder ändern." "Ermöglicht der App, die Anrufliste Ihres Telefons zu ändern, einschließlich der Daten über ein- und ausgehende Anrufe. Schädliche Apps können so Ihre Anrufliste löschen oder ändern." - "Körpersensoren (wie Pulsmonitore)" + "Auf Körpersensoren wie z. B. Herzfrequenzmesser zugreifen" "Ermöglicht der App, auf Daten von Sensoren zuzugreifen, die Ihre körperliche Verfassung überwachen, beispielsweise Ihren Puls" "Kalendertermine sowie vertrauliche Informationen lesen" "Ermöglicht der App, alle auf Ihrem Tablet gespeicherten Kalendertermine zu lesen, einschließlich der von Freunden und Kollegen. Damit kann die App möglicherweise Ihre Kalenderdaten unabhängig von der Vertraulichkeit weiterleiten oder speichern." @@ -336,15 +336,15 @@ "Ermöglicht der App, Termine, die Sie auf Ihrem Telefon ändern können, hinzuzufügen, zu entfernen und zu ändern, einschließlich der von Freunden und Kollegen. Damit kann die App Nachrichten senden, die so erscheinen, als stammten sie vom jeweiligen Kalenderinhaber, oder Termine ohne Wissen des Inhabers ändern." "Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen" "Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen." - "Genauer Standort (GPS- und netzwerkbasiert)" + "Auf genauen Standort zugreifen (GPS- und netzwerkbasiert)" "Ermöglicht der App, Ihre genaue Position anhand von GPS-Daten (Global Positioning System) oder über Netzwerkstandortquellen wie Sendemasten oder WLAN zu ermitteln. Diese Standortdienste müssen auf Ihrem Gerät verfügbar und aktiviert sein, damit die App sie verwenden kann. Apps können Ihren Standort anhand dieser Daten ermitteln und verbrauchen eventuell zusätzliche Akkuleistung." - "Ungefährer Standort (netzwerkbasiert)" + "Auf den ungefähren Standort zugreifen (netzwerkbasiert)" "Ermöglicht der App, Ihren ungefähren Standort zu ermitteln. Diese Standortangabe stammt von Standortdiensten, die Netzwerkstandortquellen wie etwa Sendemasten oder WLAN verwenden. Diese Standortdienste müssen auf Ihrem Gerät verfügbar und aktiviert sein, damit die App sie verwenden kann. Apps können Ihren ungefähren Standort anhand dieser Daten ermitteln." "Audio-Einstellungen ändern" "Ermöglicht der App, globale Audio-Einstellungen zu ändern, etwa die Lautstärke und den Lautsprecher für die Ausgabe." "Audio aufnehmen" "Ermöglicht der App, Ton mithilfe des Mikrofons aufzunehmen. Die Berechtigung erlaubt der App, Tonaufnahmen jederzeit und ohne Ihre Bestätigung durchzuführen." - "SIM-Kommunikation" + "Befehle an die SIM senden" "Ermöglicht der App das Senden von Befehlen an die SIM-Karte. Dies ist äußerst risikoreich." "Bilder und Videos aufnehmen" "Ermöglicht der App, Bilder und Videos mit der Kamera aufzunehmen. Die Berechtigung erlaubt der App, die Kamera jederzeit und ohne Ihre Bestätigung zu nutzen." @@ -382,7 +382,7 @@ "Ermöglicht der App, eine Liste der dem Telefon bekannten Konten abzurufen. Dabei kann es sich um Konten handeln, die von installierten Apps erstellt wurden." "Netzwerkverbindungen abrufen" "Ermöglicht der App, Informationen zu Netzwerkverbindungen abzurufen, etwa welche Netzwerke existieren und verbunden sind." - "Voller Netzwerkzugriff" + "Auf alle Netzwerke zugreifen" "Ermöglicht der App die Erstellung von Netzwerk-Sockets und die Verwendung benutzerdefinierter Netzwerkprotokolle. Der Browser und andere Apps bieten die Möglichkeit, Daten über das Internet zu versenden. Daher ist diese Berechtigung nicht erforderlich, um Daten über das Internet versenden zu können." "Netzwerkkonnektivität ändern" "Ermöglicht der App, den Status der Netzwerkkonnektivität zu ändern" @@ -402,7 +402,7 @@ "Ermöglicht der App, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen" "WiMAX-Verbindungen herstellen und trennen" "Ermöglicht der App festzustellen, ob WiMAX aktiviert ist. Zudem kann sie Informationen zu verbundenen WiMAX-Netzwerken abrufen." - "WiMAX-Status ändern" + "WiMAX-Status ändern" "Ermöglicht der App, eine Verbindung zwischen dem Tablet und WiMAX-Netzwerken herzustellen und solche zu trennen." "Ermöglicht der App, eine Verbindung zwischen dem Fernseher und WiMAX-Netzwerken herzustellen und diese zu trennen" "Ermöglicht der App, eine Verbindung zwischen dem Telefon und WiMAX-Netzwerken herzustellen und solche zu trennen." @@ -485,7 +485,7 @@ "Ermöglicht der App, die Kalibrierungsparameter des Touchscreens zu ändern. Für normale Apps sollte dies nie erforderlich sein." "Auf DRM-Zertifikate zugreifen" "Ermöglicht einer App die Bereitstellung und Nutzung von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden." - "Status von Android Beam-Übertragungen erhalten" + "Status von Android Beam-Übertragungen erhalten" "Ermöglicht dieser App, Informationen zu aktuellen Android Beam-Übertragungen zu erhalten" "DRM-Zertifikate entfernen" "Ermöglicht einer App das Entfernen von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden." @@ -1091,11 +1091,11 @@ "Wird formatiert..." "Nicht eingelegt" "Keine passenden Aktivitäten gefunden" - "Medienausgabe umleiten" + "Medienausgabe umleiten" "Ermöglicht der App, die Medienausgabe auf andere externe Geräte umzuleiten." - "Installationssitzungen lesen" + "Installationssitzungen lesen" "Ermöglicht der App, Installationssitzungen zu lesen. Dadurch kann sie Details aktiver Paketinstallationen abrufen." - "Installation von Paketen anfordern" + "Installation von Paketen anfordern" "Ermöglicht der App, die Installation von Paketen anzufordern" "Für Zoomeinstellung zweimal berühren" "Widget konnte nicht hinzugefügt werden." diff --git a/core/res/res/values-el-watch/strings.xml b/core/res/res/values-el-watch/strings.xml index 81a7451b5ae01..b142adb482028 100644 --- a/core/res/res/values-el-watch/strings.xml +++ b/core/res/res/values-el-watch/strings.xml @@ -21,4 +21,5 @@ "Εφαρμογή %1$d από %2$d." + "Αισθητήρες" diff --git a/core/res/res/values-el/cm_strings.xml b/core/res/res/values-el/cm_strings.xml new file mode 100644 index 0000000000000..a872602970f1b --- /dev/null +++ b/core/res/res/values-el/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Στιγμιότυπο οθόνης + + λήψη προστατευμένων SMS + + Επιτρέπει στην εφαρμογή να λαμβάνει εισερχόμενα προστατευμένα SMS. + + τροποποίηση λίστας προστατευμένων SMS + + Επιτρέπει στην εφαρμογή την τροποποίηση της λίστας προστατευμένων SMS. + + Ασφάλεια + + Δικαιώματα που σχετίζονται με την ασφάλεια των πληροφοριών της συσκευής. + + ανάγνωση της μαύρης λίστας τηλεφώνου + + Επιτρέπει σε μια εφαρμογή την ανάγνωση πληροφοριών σχετικά με τους αριθμούς τηλεφώνου που έχουν αποκλειστεί για εισερχόμενες κλήσεις ή μηνύματα. + + αλλαγή της μαύρης λίστας τηλεφώνου + + Επιτρέπει σε μια εφαρμογή την αλλαγή των αριθμών τηλεφώνου που έχουν αποκλειστεί για εισερχόμενες κλήσεις ή μηνύματα. + + ορισμός ταπετσαρίας οθόνης κλειδώματος + + Επιτρέπει σε μια εφαρμογή την αλλαγή της ταπετσαρίας της οθόνης κλειδώματος. + + Επανεκκίνηση + + Τρέχων + + + Επανεκκίνηση + + Recovery + + Bootloader + + Download + + Γρήγορη επανεκκίνηση + + Επανεκκίνηση + + Το tablet σας θα κάνει επανεκκίνηση. + Το τηλέφωνό σας θα κάνει επανεκκίνηση. + + Επανεκκίνηση\u2026 + + Η εφαρμογή τερματίστηκε + + ADB μέσω δικτύου ενεργοποιημένο + + ADB μέσω USB & δικτύου ενεργοποιημένο + + Αγγίξτε για απενεργοποίηση του εντοπισμού σφαλμάτων. + + ADB - %1$s + USB & δίκτυο + USB + Δίκτυο + + παρεμπόδιση έναρξης εφαρμογών + + Το %s δεν είναι εγκατεστημένο + + Προτεραιότητα + Κανένα + + Το Wi-Fi hotspot απενεργοποιήθηκε λόγω αλλαγής συνδρομής SIM + + Απενεργοποίηση Wi-Fi + + ενεργοποίηση ή απενεργοποίηση της Προστασίας Απορρήτου + Επιτρέπει στην εφαρμογή τον χειρισμό άλλων εφαρμογών με την Προστασία Απορρήτου. Όταν μια εφαρμογή τρέχει με την Προστασία Απορρήτου, δεν θα έχει πρόσβαση στα προσωπικά σας δεδομένα όπως επαφές, μηνύματα ή το αρχείο κλήσεων. + Προστασία Απορρήτου ενεργή + %1$s δεν θα μπορεί να έχει πρόσβαση στα προσωπικά σας δεδομένα + Προστασία Απορρήτου + Το %1$s ζητά: %2$s. + + Απομνημόνευση της επιλογής μου + + πρόσβαση στην φωτογρ. μηχανή + πρόσβαση στην τοποθεσία σας + ανάγνωση των ειδοποιήσεών σας + ενεργοποίηση ενός VPN + άνοιγμα κατά την εκκίνηση + διαγραφή του ιστορικού κλήσεων σας + διαγραφή των επαφών σας + διαγραφή των μηνυμάτων MMS σας + διαγραφή των μηνυμάτων SMS σας + εμφάνιση παραθύρων στην κορυφή + λήψη στατιστικών χρήσης εφαρμογών + διατήρηση της συσκευής σας σε αφύπνιση + πραγματοποίηση μιας τηλεφωνικής κλήσης + ενημέρωση του ημερολογίου σας + ενημέρωση του αρχείου κλήσεων + τροποποίηση του προχείρου + ενημέρωση των επαφών σας + ενημέρωση των ρυθμίσεων συστήματος + σίγαση/κατάργηση σίγασης του μικροφώνου + αναπαραγωγή ήχου + εμφάνιση μιας ειδοποίησης + εμφάνιση πολυμέσων + ανάγνωση του ημερολογίου σας + ανάγνωση του αρχείου κλήσεων + ανάγνωση του προχείρου + ανάγνωση των επαφών σας + ανάγνωση των μηνυμάτων MMS σας + ανάγνωση των μηνυμάτων SMS σας + λήψη ενός μηνύματος SMS + εγγραφή ήχου + αποστολή ενός μηνύματος MMS + αποστολή ενός μηνύματος SMS + άνοιγμα κατά την εκκίνηση + εμφάνιση αναδυόμενων μηνυμάτων + εναλλαγή Bluetooth + εναλλαγή δεδομένων κινητής τηλεφωνίας + εναλλαγή NFC + εναλλαγή Wi-Fi + έλεγχο έντασης ξυπνητηριού + έλεγχο της εστίασης ήχου + έλεγχο της έντασης Bluetooth + έλεγχο της κύριας έντασης + χρήση των πλήκτρων μέσων + έλεγχο της έντασης μέσων + έλεγχο της έντασης ειδοποιήσεων + έλεγχο της έντασης ήχου κλήσης + χρήση απτικής ανάδρασης + έλεγχο της έντασης φωνητικής κλήσης + εγγραφή ενός μηνύματος MMS + εγγραφή ενός μηνύματος SMS + χρήση δακτυλικού αποτυπώματος + προσθήκη φωνητικού μηνύματος + πρόσβαση στην κατάσταση τηλεφώνου + σάρωση δίκτυων Wi-Fi + αλλαγή της ταπετσαρίας + χρήση της βοηθητικής εφαρμογής + λήψη στιγμιότυπου οθόνης + χρήση αισθητήρων σώματος + ανάγνωση εκπομπών κινητής τηλεφωνίας + αναφορά ψευδής τοποθεσίας + ανάγνωση εξωτερικού αποθ. χώρου + εγγραφή εξωτερικού αποθ. χώρου + ενεργοποίηση της οθόνης + ανάγνωση λογαριασμών συσκευής + αλλαγή κατάστασης Wi-Fi + πρόσβαση root + + Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε και κρατήστε πατημένο το πλήκτρο Πίσω. + + Καμία συνδεδεμένη συσκευή + %1$s συνδεδεμένη συσκευή + %1$s συνδεδεμένες συσκευές + + + + Η εκκίνηση της δραστηριότητας αποκλείστηκε + Η εφαρμογή %1$s είναι προστατευμένη. Πιέστε για έλεγχο ταυτότητας και εκκίνηση της εφαρμογής. + + Μπαταρία πλήρως φορτισμένη + Αποσυνδέστε τη συσκευή από το φορτιστή για να βελτιώσετε τη μακροζωία της μπαταρίας. + + επαναφορά στατιστικών μπαταρίας + + Επιτρέπει σε μια εφαρμογή να κάνει επαναφορά τα χαμηλού επιπέδου δεδομένα χρήσης μπαταρίας. + + Οι κάρτες SIM έχουν αλλάξει + Πατήστε για να ορίσετε τις προεπιλεγμένες προτιμήσεις των καρτών + diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 0aca5dbb98cfb..84ce62346b928 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -254,7 +254,7 @@ "Περιλαμβάνει προσωπικά δεδομένα, όπως είναι οι αριθμοί πιστωτικών καρτών και οι κωδικοί πρόσβασης." "απενεργοποίηση ή τροποποίηση γραμμής κατάστασης" "Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος." - "γραμμή κατάστασης" + "ορισμός ως γραμμής κατάστασης" "Επιτρέπει στην εφαρμογή να αποτελεί τη γραμμή κατάστασης." "ανάπτυξη/σύμπτυξη γραμμής κατάστασης" "Επιτρέπει στην εφαρμογή να αναπτύξει ή να συμπτύξει τη γραμμή κατάστασης." @@ -282,7 +282,7 @@ "Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων WAP. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς." "ανάκτηση εκτελούμενων εφαρμογών" "Επιτρέπει στην εφαρμογή την ανάκτηση πληροφοριών σχετικά με τρέχουσες και πρόσφατα εκτελούμενες εργασίες. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να ανακαλύπτει πληροφορίες σχετικά με το ποιες εφαρμογές χρησιμοποιούνται στη συσκευή." - "Διαχείριση προφίλ και κατόχων συσκευής" + "διαχείριση προφίλ και κατόχων συσκευής" "Επιτρέπει σε εφαρμογές να ορίζουν τους κατόχους προφίλ και τον κάτοχο της συσκευής." "αναδιάταξη εκτελούμενων εφαρμογών" "Επιτρέπει στην εφαρμογή τη μετακίνηση εργασιών στο προσκήνιο και το παρασκήνιο. Η εφαρμογή μπορεί να το κάνει αυτό χωρίς να καταχωρίσετε δεδομένα εισόδου." @@ -324,7 +324,7 @@ "Επιτρέπει στην εφαρμογή να τροποποιεί το αρχείο καταγραφής κλήσεων του tablet σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Οι κακόβουλες εφαρμογές μπορεί να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν το αρχείο καταγραφής κλήσεων." "Επιτρέπει στην εφαρμογή να τροποποιεί το αρχείο καταγραφής κλήσεων της τηλεόρασής σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Κακόβουλες εφαρμογές μπορεί να χρησιμοποιήσουν αυτήν τη δυνατότητα, για να διαγράψουν ή να τροποποιήσουν το αρχείο καταγραφής κλήσεων." "Επιτρέπει στην εφαρμογή να τροποποιεί το αρχείο καταγραφής κλήσεων του τηλεφώνου σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Οι κακόβουλες εφαρμογές μπορεί να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν το αρχείο καταγραφής κλήσεων." - "αισθητήρες λειτουργιών (π.χ. καρδιακό ρυθμό)" + "πρόσβαση στους αισθητήρες λειτουργιών (π.χ. παρακολούθηση καρδιακού παλμού)" "Επιτρέπει στην εφαρμογή να αποκτήσει πρόσβαση στα δεδομένα των αισθητήρων που παρακολουθούν τη φυσική σας κατάσταση, όπως τον καρδιακό ρυθμό σας." "ανάγνωση συμβάντων ημερολογίου και εμπιστευτικών πληροφοριών" "Επιτρέπει στην εφαρμογή την ανάγνωση όλων των συμβάντων ημερολογίου που είναι αποθηκευμένα στο tablet σας, συμπεριλαμβανομένων εκείνων των φίλων ή των συναδέλφων σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να μοιράζεται ή να αποθηκεύει τα δεδομένα του ημερολογίου σας, ανεξάρτητα από το βαθμό εμπιστευτικότητας ή ευαισθησίας τους." @@ -336,15 +336,15 @@ "Επιτρέπει στην εφαρμογή την προσθήκη, την κατάργηση και την αλλαγή συμβάντων που μπορείτε να τροποποιήσετε στο τηλέφωνό σας, συμπεριλαμβανομένων εκείνων των φίλων ή των συναδέλφων σας. Αυτό μπορεί να επιτρέπει στην εφαρμογή να αποστέλλει μηνύματα που φαίνεται ότι προέρχονται από κατόχους ημερολογίων ή να τροποποιεί συμβάντα χωρίς να το γνωρίζουν οι κάτοχοι." "πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας" "Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας." - "ακριβής θέση (GPS και βάσει δικτύου)" + "πρόσβαση στην ακριβή τοποθεσία (με βάση το GPS και το δίκτυο)" "Επιτρέπει στην εφαρμογή να λαμβάνει την ακριβή θέση σας με τη χρήση του Παγκόσμιου Συστήματος Εντοπισμού (GPS) ή πηγών τοποθεσίας δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην συσκευή σας, ώστε να μπορούν να χρησιμοποιηθούν από την εφαρμογή. Οι εφαρμογές ενδέχεται να τις χρησιμοποιήσουν για να προσδιορίσουν τη θέση σας και ενδέχεται να καταναλώσουν επιπλέον ισχύ μπαταρίας." - "κατά προσέγγιση θέση (βάσει δικτύου)" + "πρόσβαση στην τοποθεσία κατά προσέγγιση (με βάση το δίκτυο)" "Επιτρέπει στην εφαρμογή τη λήψη της κατά προσέγγιση τοποθεσίας σας. Αυτή η τοποθεσία προκύπτει από τις υπηρεσίες τοποθεσίας με τη χρήση πηγών τοποθεσίας δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην συσκευή σας, ώστε να μπορούν να χρησιμοποιηθούν από την εφαρμογή. Οι εφαρμογές ενδέχεται να τις χρησιμοποιήσουν για να προσδιορίσουν κατά προσέγγιση τη θέση σας." "αλλαγή των ρυθμίσεων ήχου" "Επιτρέπει στην εφαρμογή την τροποποίηση καθολικών ρυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χρησιμοποιείται για έξοδο." "εγγραφή ήχου" "Επιτρέπει στην εφαρμογή την εγγραφή ήχου με το μικρόφωνο. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να εγγράφει ήχο ανά πάσα στιγμή χωρίς την έγκρισή σας." - "επικοινωνία με κάρτα sim" + "στέλνει εντολές στην κάρτα SIM" "Επιτρέπει στην εφαρμογή την αποστολή εντολών στην κάρτα SIM. Αυτό είναι εξαιρετικά επικίνδυνο." "λήψη φωτογραφιών και βίντεο" "Επιτρέπει στην εφαρμογή τη λήψη φωτογραφιών και βίντεο με τη φωτογραφική μηχανή. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να χρησιμοποιεί τη φωτογραφική μηχανή ανά πάσα στιγμή χωρίς την έγκρισή σας." @@ -382,7 +382,7 @@ "Επιτρέπει στην εφαρμογή τη λήψη της λίστας λογαριασμών που υπάρχουν στο τηλέφωνο. Μπορεί να περιλαμβάνονται τυχόν λογαριασμοί που δημιουργήθηκαν από εφαρμογές που έχετε εγκαταστήσει." "προβολή συνδέσεων δικτύου" "Επιτρέπει στην εφαρμογή την προβολή πληροφοριών σχετικά με συνδέσεις δικτύου, όπως ποια δίκτυα υπάρχουν και είναι συνδεδεμένα." - "πλήρης πρόσβαση στο δίκτυο" + "πλήρης πρόσβαση στο δίκτυο" "Επιτρέπει στην εφαρμογή τη δημιουργία θέσεων δικτύου και τη χρήση προσαρμοσμένων πρωτοκόλλων δικτύου. Το πρόγραμμα περιήγησης και άλλες εφαρμογές παρέχουν μέσα για την αποστολή δεδομένων στο διαδίκτυο, επομένως η συγκεκριμένη άδεια δεν είναι απαραίτητη για την αποστολή δεδομένων στο διαδίκτυο." "αλλαγή συνδεσιμότητας δικτύου" "Επιτρέπει στην εφαρμογή την αλλαγή της κατάστασης συνδεσιμότητας δικτύου." @@ -402,7 +402,7 @@ "Επιτρέπει στην εφαρμογή τη διαμόρφωση του τοπικού tablet Bluetooth, τον εντοπισμό και τη σύζευξη με απομακρυσμένες συσκευές." "σύνδεση και αποσύνδεση από το WiMAX" "Επιτρέπει στην εφαρμογή να προσδιορίζει εάν το WiMAX είναι ενεργοποιημένο και πληροφορίες σχετικά με τυχόν δίκτυα WiMAX που είναι συνδεδεμένα." - "Αλλαγή κατάστασης WiMAX" + "αλλαγή κατάστασης WiMAX" "Επιτρέπει στην εφαρμογή τη σύνδεση στο tablet και την αποσύνδεση από αυτό, από δίκτυα WiMAX." "Επιτρέπει στην εφαρμογή να συνδέει και να αποσυνδέει την τηλεόραση από δίκτυα WiMAX." "Επιτρέπει στην εφαρμογή τη σύνδεση στο τηλέφωνο και την αποσύνδεση από αυτό, από δίκτυα WiMAX." @@ -485,7 +485,7 @@ "Επιτρέπει στην εφαρμογή να τροποποιεί τις παραμέτρους βαθμονόμησης της οθόνης αφής. Δεν απαιτείται για τις κανονικές εφαρμογές." "πρόσβαση σε πιστοποιητικά DRM" "Επιτρέπει σε μια εφαρμογή να παρέχει και να χρησιμοποιεί πιστοποιητικά DRM. Δεν θα χρειαστεί ποτέ για κανονικές εφαρμογές." - "Λήψη κατάστασης μεταφοράς Android Beam" + "λήψη κατάστασης μεταφοράς Android Beam" "Επιτρέπει σε αυτήν την εφαρμογή να λαμβάνει πληροφορίες σχετικά με τις τρέχουσες μεταφορές Android Beam" "κατάργηση πιστοποιητικών DRM" "Επιτρέπει σε μια εφαρμογή την κατάργηση πιστοποιητικών DRM. Δεν χρειάζεται ποτέ για κανονικές εφαρμογές." @@ -1091,11 +1091,11 @@ "Διαμόρφωση…" "Δεν έχει εισαχθεί" "Δεν βρέθηκαν δραστηριότητες που να συμφωνούν με τα κριτήρια." - "Διαγραφή διαδρομής δεδομένων εξόδου μέσων" + "δρομολόγηση εξόδου μέσων" "Επιτρέπει σε μια εφαρμογή τη διαγραφή διαδρομής δεδομένων εξόδου μέσων σε άλλες εξωτερικές συσκευές." - "Ανάγνωση περιόδων σύνδεσης εγκατάστασης" + "ανάγνωση περιόδων σύνδεσης εγκατάστασης" "Επιτρέπει σε μια εφαρμογή την ανάγνωση των περιόδων σύνδεσης εγκατάστασης. Αυτό της επιτρέπει να βλέπει λεπτομέρειες σχετικά με τις εγκαταστάσεις του ενεργού πακέτου." - "Αίτημα εγκατάστασης πακέτων." + "αίτημα εγκατάστασης πακέτων" "Επιτρέπει σε μια εφαρμογή να ζητά εγκατάσταση πακέτων." "Αγγίξτε δύο φορές για έλεγχο εστίασης" "Δεν ήταν δυνατή η προσθήκη του γραφικού στοιχείου." diff --git a/core/res/res/values-en-rAU-watch/strings.xml b/core/res/res/values-en-rAU-watch/strings.xml index 6734cd38ec6fe..ac7b671f80ab2 100644 --- a/core/res/res/values-en-rAU-watch/strings.xml +++ b/core/res/res/values-en-rAU-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d of %2$d." + "Sensors" diff --git a/core/res/res/values-en-rAU/cm_strings.xml b/core/res/res/values-en-rAU/cm_strings.xml new file mode 100644 index 0000000000000..1ccf5e4f82ed8 --- /dev/null +++ b/core/res/res/values-en-rAU/cm_strings.xml @@ -0,0 +1,159 @@ + + + + + + Screenshot + + receive protected SMS + + Allows the app to receive an incoming protected SMS. + + modify protected SMS list + + Allows the app to modify the protected SMS address list. + + Security + + Permissions related to device security information. + + read phone blacklist + + Allows an app to read information about phone numbers that are blocked for incoming calls or messages. + + change phone blacklist + + Allows an app to change the phone numbers that are blocked for incoming calls or messages. + + set keyguard wallpaper + + Allows an app to change the lock screen wallpaper. + + Reboot + + Current + + + Reboot + + Recovery + + Bootloader + + Download + + Soft reboot + + Reboot + + Your tablet will reboot. + Your phone will reboot. + + Rebooting\u2026 + + App killed + + ADB over network enabled + + ADB over USB & network enabled + + Touch to disable debugging. + + + intercept app launch + + %s is not installed + + + + + enable or disable Privacy Guard + Allows the app to change whether another app runs with Privacy Guard. When an app is running with Privacy Guard, it will not have access to personal data such as contacts, call logs, or messages. + Privacy Guard active + %1$s will not be able to access personal data + Privacy Guard + %1$s would like to %2$s. + + Remember my choice + + access the camera + access your location + read your notifications + activate a VPN + start at power up + delete your call log + delete your contacts + delete your MMS messages + delete your SMS messages + draw windows on top + get app usage stats + keep your device awake + make a phone call + update your calendar + update the call log + modify the clipboard + update your contacts + update system settings + mute/unmute the microphone + play audio + post a notification + project media + read your calendar + read the call log + read the clipboard + read your contacts + read your MMS messages + read your SMS messages + receive an SMS message + record audio + send an MMS message + send an SMS message + start at power up + display toast messages + toggle Bluetooth + toggle NFC + control alarm volume + control the audio focus + control the Bluetooth volume + control the master volume + use the media buttons + control the media volume + control the notification volume + control the ringtone volume + use haptic feedback + control the voice call volume + write an MMS message + write an SMS message + get root access + + + No connected device + %1$s connected device + %1$s connected devices + + + + + + + + diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index f85f8653382bb..2f0169d4c6b89 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -254,7 +254,7 @@ "Includes personal data such as credit card numbers and passwords." "disable or modify status bar" "Allows the app to disable the status bar or add and remove system icons." - "status bar" + "be the status bar" "Allows the app to be the status bar." "expand/collapse status bar" "Allows the app to expand or collapse the status bar." @@ -282,7 +282,7 @@ "Allows the app to receive and process WAP messages. This permission includes the ability to monitor or delete messages sent to you without showing them to you." "retrieve running apps" "Allows the app to retrieve information about currently and recently running tasks. This may allow the app to discover information about which applications are used on the device." - "Manage profile and device owners" + "manage profile and device owners" "Allows apps to set the profile owners and the device owner." "re-order running apps" "Allows the app to move tasks to the foreground and background. The app may do this without your input." @@ -324,7 +324,7 @@ "Allows the app to modify your tablet\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." "Allows the app to modify your TV\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." "Allows the app to modify your phone\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." - "body sensors (like heart rate monitors)" + "access body sensors (like heart rate monitors)" "Allows the app to access data from sensors that monitor your physical condition, such as your heart rate." "read calendar events plus confidential information" "Allows the app to read all calendar events stored on your tablet, including those of friends or co-workers. This may allow the app to share or save your calendar data, regardless of confidentiality or sensitivity." @@ -336,15 +336,15 @@ "Allows the app to add, remove and change events that you can modify on your phone, including those of friends or co-workers. This may allow the app to send messages that appear to come from calendar owners, or modify events without the owners\' knowledge." "access extra location provider commands" "Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources." - "precise location (GPS and network-based)" + "access precise location (GPS and network-based)" "Allows the app to get your precise location using the Global Positioning System (GPS) or network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine where you are, and may consume additional battery power." - "approximate location (network-based)" + "access approximate location (network-based)" "Allows the app to get your approximate location. This location is derived by location services using network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine approximately where you are." "change your audio settings" "Allows the app to modify global audio settings such as volume and which speaker is used for output." "record audio" "Allows the app to record audio with the microphone. This permission allows the app to record audio at any time without your confirmation." - "SIM communication" + "send commands to the SIM" "Allows the app to send commands to the SIM. This is very dangerous." "take pictures and videos" "Allows the app to take pictures and videos with the camera. This permission allows the app to use the camera at any time without your confirmation." @@ -382,7 +382,7 @@ "Allows the app to get the list of accounts known by the phone. This may include any accounts created by applications that you have installed." "view network connections" "Allows the app to view information about network connections such as which networks exist and are connected." - "full network access" + "have full network access" "Allows the app to create network sockets and use customised network protocols. The browser and other applications provide means to send data to the Internet, so this permission is not required to send data to the Internet." "change network connectivity" "Allows the app to change the state of network connectivity." @@ -402,7 +402,7 @@ "Allows the app to configure the local Bluetooth phone and to discover and pair with remote devices." "connect and disconnect from WiMAX" "Allows the app to determine whether WiMAX is enabled and information about any WiMAX networks that are connected." - "Change WiMAX state" + "change WiMAX state" "Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks." "Allows the app to connect the TV to and disconnect the TV from WiMAX networks." "Allows the app to connect the phone to and disconnect the phone from WiMAX networks." @@ -485,7 +485,7 @@ "Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps." "access DRM certificates" "Allows an application to provision and use DRM certficates. Should never be needed for normal apps." - "Receive Android Beam transfer status" + "receive Android Beam transfer status" "Allows this application to receive information about current Android Beam transfers" "remove DRM certificates" "Allows an application to remove DRM certficates. Should never be needed for normal apps." @@ -1091,11 +1091,11 @@ "Formatting…" "Not inserted" "No matching activities found." - "Route media output" + "route media output" "Allows an application to route media output to other external devices." - "Read install sessions" + "read install sessions" "Allows an application to read install sessions. This allows it to see details about active package installations." - "Request install packages" + "request install packages" "Allows an application to request installation of packages." "Touch twice for zoom control" "Couldn\'t add widget." diff --git a/core/res/res/values-en-rGB-watch/strings.xml b/core/res/res/values-en-rGB-watch/strings.xml index 6734cd38ec6fe..ac7b671f80ab2 100644 --- a/core/res/res/values-en-rGB-watch/strings.xml +++ b/core/res/res/values-en-rGB-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d of %2$d." + "Sensors" diff --git a/core/res/res/values-en-rGB/cm_strings.xml b/core/res/res/values-en-rGB/cm_strings.xml new file mode 100644 index 0000000000000..34be26cabeebe --- /dev/null +++ b/core/res/res/values-en-rGB/cm_strings.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + toggle mobile data + + + + + + + + + + diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index f85f8653382bb..2f0169d4c6b89 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -254,7 +254,7 @@ "Includes personal data such as credit card numbers and passwords." "disable or modify status bar" "Allows the app to disable the status bar or add and remove system icons." - "status bar" + "be the status bar" "Allows the app to be the status bar." "expand/collapse status bar" "Allows the app to expand or collapse the status bar." @@ -282,7 +282,7 @@ "Allows the app to receive and process WAP messages. This permission includes the ability to monitor or delete messages sent to you without showing them to you." "retrieve running apps" "Allows the app to retrieve information about currently and recently running tasks. This may allow the app to discover information about which applications are used on the device." - "Manage profile and device owners" + "manage profile and device owners" "Allows apps to set the profile owners and the device owner." "re-order running apps" "Allows the app to move tasks to the foreground and background. The app may do this without your input." @@ -324,7 +324,7 @@ "Allows the app to modify your tablet\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." "Allows the app to modify your TV\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." "Allows the app to modify your phone\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." - "body sensors (like heart rate monitors)" + "access body sensors (like heart rate monitors)" "Allows the app to access data from sensors that monitor your physical condition, such as your heart rate." "read calendar events plus confidential information" "Allows the app to read all calendar events stored on your tablet, including those of friends or co-workers. This may allow the app to share or save your calendar data, regardless of confidentiality or sensitivity." @@ -336,15 +336,15 @@ "Allows the app to add, remove and change events that you can modify on your phone, including those of friends or co-workers. This may allow the app to send messages that appear to come from calendar owners, or modify events without the owners\' knowledge." "access extra location provider commands" "Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources." - "precise location (GPS and network-based)" + "access precise location (GPS and network-based)" "Allows the app to get your precise location using the Global Positioning System (GPS) or network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine where you are, and may consume additional battery power." - "approximate location (network-based)" + "access approximate location (network-based)" "Allows the app to get your approximate location. This location is derived by location services using network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine approximately where you are." "change your audio settings" "Allows the app to modify global audio settings such as volume and which speaker is used for output." "record audio" "Allows the app to record audio with the microphone. This permission allows the app to record audio at any time without your confirmation." - "SIM communication" + "send commands to the SIM" "Allows the app to send commands to the SIM. This is very dangerous." "take pictures and videos" "Allows the app to take pictures and videos with the camera. This permission allows the app to use the camera at any time without your confirmation." @@ -382,7 +382,7 @@ "Allows the app to get the list of accounts known by the phone. This may include any accounts created by applications that you have installed." "view network connections" "Allows the app to view information about network connections such as which networks exist and are connected." - "full network access" + "have full network access" "Allows the app to create network sockets and use customised network protocols. The browser and other applications provide means to send data to the Internet, so this permission is not required to send data to the Internet." "change network connectivity" "Allows the app to change the state of network connectivity." @@ -402,7 +402,7 @@ "Allows the app to configure the local Bluetooth phone and to discover and pair with remote devices." "connect and disconnect from WiMAX" "Allows the app to determine whether WiMAX is enabled and information about any WiMAX networks that are connected." - "Change WiMAX state" + "change WiMAX state" "Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks." "Allows the app to connect the TV to and disconnect the TV from WiMAX networks." "Allows the app to connect the phone to and disconnect the phone from WiMAX networks." @@ -485,7 +485,7 @@ "Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps." "access DRM certificates" "Allows an application to provision and use DRM certficates. Should never be needed for normal apps." - "Receive Android Beam transfer status" + "receive Android Beam transfer status" "Allows this application to receive information about current Android Beam transfers" "remove DRM certificates" "Allows an application to remove DRM certficates. Should never be needed for normal apps." @@ -1091,11 +1091,11 @@ "Formatting…" "Not inserted" "No matching activities found." - "Route media output" + "route media output" "Allows an application to route media output to other external devices." - "Read install sessions" + "read install sessions" "Allows an application to read install sessions. This allows it to see details about active package installations." - "Request install packages" + "request install packages" "Allows an application to request installation of packages." "Touch twice for zoom control" "Couldn\'t add widget." diff --git a/core/res/res/values-en-rIN-watch/strings.xml b/core/res/res/values-en-rIN-watch/strings.xml index 6734cd38ec6fe..ac7b671f80ab2 100644 --- a/core/res/res/values-en-rIN-watch/strings.xml +++ b/core/res/res/values-en-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d of %2$d." + "Sensors" diff --git a/core/res/res/values-en-rIN/cm_strings.xml b/core/res/res/values-en-rIN/cm_strings.xml new file mode 100644 index 0000000000000..7a726eb89a043 --- /dev/null +++ b/core/res/res/values-en-rIN/cm_strings.xml @@ -0,0 +1,186 @@ + + + + + + Screenshot + + receive protected SMS + + Allows the app to receive an incoming protected SMS. + + modify protected SMS list + + Allows the app to modify the protected SMS address list. + + Security + + Permissions related to device security information. + + read phone blacklist + + Allows an app to read information about phone numbers that are blocked for incoming calls or messages. + + change phone blacklist + + Allows an app to change the phone numbers that are blocked for incoming calls or messages. + + set keyguard wallpaper + + Allows an app to change the lock screen wallpaper. + + Reboot + + Current + + + Reboot + + Recovery + + Bootloader + + Download + + Soft reboot + + Reboot + + Your tablet will reboot. + Your phone will reboot. + + Rebooting\u2026 + + App killed + + ADB over network enabled + + ADB over USB & network enabled + + Touch to disable debugging. + + ADB - %1$s + USB & network + USB + Network + + intercept app launch + + %s is not installed + + Priority + None + + Disabled Wi-Fi hotspot due to SIM subscription change + + Turn Wi-Fi off + + enable or disable Privacy Guard + Allows the app to change whether another app runs with Privacy Guard. When an app is running with Privacy Guard, it will not have access to personal data such as contacts, call logs, or messages. + Privacy Guard active + %1$s will not be able to access personal data + Privacy Guard + %1$s would like to %2$s. + + Remember my choice + + access the camera + access your location + read your notifications + activate a VPN + start at power up + delete your call log + delete your contacts + delete your MMS messages + delete your SMS messages + draw windows on top + get app usage stats + keep your device awake + make a phone call + update your calendar + update the call log + modify the clipboard + update your contacts + update system settings + mute/unmute the microphone + play audio + post a notification + project media + read your calendar + read the call log + read the clipboard + read your contacts + read your MMS messages + read your SMS messages + receive an SMS message + record audio + send an MMS message + send an SMS message + start at power up + display toast messages + toggle Bluetooth + toggle NFC + toggle Wi-Fi + control alarm volume + control the audio focus + control the Bluetooth volume + control the master volume + use the media buttons + control the media volume + control the notification volume + control the ringtone volume + use haptic feedback + control the voice call volume + write an MMS message + write an SMS message + use fingerprint + add a voicemail + access phone state + scan Wi-Fi networks + change the wallpaper + use assist structure + take a screenshot + use body sensors + read cell broadcasts + mock your location + read external storage + write external storage + turn the screen on + get device accounts + change Wi-Fi state + get root access + + To unpin this screen, touch and hold the Back button. + + No connected device + %1$s connected device + %1$s connected devices + + + + + + reset battery statistics + + Allows an application to reset the current low-level battery use data. + + diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index f85f8653382bb..2f0169d4c6b89 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -254,7 +254,7 @@ "Includes personal data such as credit card numbers and passwords." "disable or modify status bar" "Allows the app to disable the status bar or add and remove system icons." - "status bar" + "be the status bar" "Allows the app to be the status bar." "expand/collapse status bar" "Allows the app to expand or collapse the status bar." @@ -282,7 +282,7 @@ "Allows the app to receive and process WAP messages. This permission includes the ability to monitor or delete messages sent to you without showing them to you." "retrieve running apps" "Allows the app to retrieve information about currently and recently running tasks. This may allow the app to discover information about which applications are used on the device." - "Manage profile and device owners" + "manage profile and device owners" "Allows apps to set the profile owners and the device owner." "re-order running apps" "Allows the app to move tasks to the foreground and background. The app may do this without your input." @@ -324,7 +324,7 @@ "Allows the app to modify your tablet\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." "Allows the app to modify your TV\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." "Allows the app to modify your phone\'s call log, including data about incoming and outgoing calls. Malicious apps may use this to erase or modify your call log." - "body sensors (like heart rate monitors)" + "access body sensors (like heart rate monitors)" "Allows the app to access data from sensors that monitor your physical condition, such as your heart rate." "read calendar events plus confidential information" "Allows the app to read all calendar events stored on your tablet, including those of friends or co-workers. This may allow the app to share or save your calendar data, regardless of confidentiality or sensitivity." @@ -336,15 +336,15 @@ "Allows the app to add, remove and change events that you can modify on your phone, including those of friends or co-workers. This may allow the app to send messages that appear to come from calendar owners, or modify events without the owners\' knowledge." "access extra location provider commands" "Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources." - "precise location (GPS and network-based)" + "access precise location (GPS and network-based)" "Allows the app to get your precise location using the Global Positioning System (GPS) or network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine where you are, and may consume additional battery power." - "approximate location (network-based)" + "access approximate location (network-based)" "Allows the app to get your approximate location. This location is derived by location services using network location sources such as mobile towers and Wi-Fi. These location services must be turned on and available to your device for the app to use them. Apps may use this to determine approximately where you are." "change your audio settings" "Allows the app to modify global audio settings such as volume and which speaker is used for output." "record audio" "Allows the app to record audio with the microphone. This permission allows the app to record audio at any time without your confirmation." - "SIM communication" + "send commands to the SIM" "Allows the app to send commands to the SIM. This is very dangerous." "take pictures and videos" "Allows the app to take pictures and videos with the camera. This permission allows the app to use the camera at any time without your confirmation." @@ -382,7 +382,7 @@ "Allows the app to get the list of accounts known by the phone. This may include any accounts created by applications that you have installed." "view network connections" "Allows the app to view information about network connections such as which networks exist and are connected." - "full network access" + "have full network access" "Allows the app to create network sockets and use customised network protocols. The browser and other applications provide means to send data to the Internet, so this permission is not required to send data to the Internet." "change network connectivity" "Allows the app to change the state of network connectivity." @@ -402,7 +402,7 @@ "Allows the app to configure the local Bluetooth phone and to discover and pair with remote devices." "connect and disconnect from WiMAX" "Allows the app to determine whether WiMAX is enabled and information about any WiMAX networks that are connected." - "Change WiMAX state" + "change WiMAX state" "Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks." "Allows the app to connect the TV to and disconnect the TV from WiMAX networks." "Allows the app to connect the phone to and disconnect the phone from WiMAX networks." @@ -485,7 +485,7 @@ "Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps." "access DRM certificates" "Allows an application to provision and use DRM certficates. Should never be needed for normal apps." - "Receive Android Beam transfer status" + "receive Android Beam transfer status" "Allows this application to receive information about current Android Beam transfers" "remove DRM certificates" "Allows an application to remove DRM certficates. Should never be needed for normal apps." @@ -1091,11 +1091,11 @@ "Formatting…" "Not inserted" "No matching activities found." - "Route media output" + "route media output" "Allows an application to route media output to other external devices." - "Read install sessions" + "read install sessions" "Allows an application to read install sessions. This allows it to see details about active package installations." - "Request install packages" + "request install packages" "Allows an application to request installation of packages." "Touch twice for zoom control" "Couldn\'t add widget." diff --git a/core/res/res/values-en-rPT/cm_strings.xml b/core/res/res/values-en-rPT/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-en-rPT/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-en-rPT/strings.xml b/core/res/res/values-en-rPT/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-en-rPT/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-eo/cm_strings.xml b/core/res/res/values-eo/cm_strings.xml new file mode 100644 index 0000000000000..842c264c7a300 --- /dev/null +++ b/core/res/res/values-eo/cm_strings.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Reto + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-eo/strings.xml b/core/res/res/values-eo/strings.xml new file mode 100644 index 0000000000000..67cf790311a18 --- /dev/null +++ b/core/res/res/values-eo/strings.xml @@ -0,0 +1,1784 @@ + + + + + + B + + kB + + MB + + GB + + TB + + PB + + + %1$d tagoj + + %1$d tago + %2$d horoj + + %1$d tago + %2$d horo + + %1$d horoj + + + + + + + + + + <Sentitola> + + (Neniu telefonnumero) + + Nekonata + + + + + + + + + + + + + Malĝusta pasvorto. + + + + + + + + + + + IMEI + + MEID + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %s + + %s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Mi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aviadila reĝimo + + + + Agordoj + + + + + 999+ + + Sekura reĝimo + + + + + Kontaktoj + + + Loko + + + Kalendaro + + + + + + + Mikrofono + + + + + Telefono + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fermi aliajn aplikaĵojn + + + + + + + + + + + + + + + + + + + + legi viajn kontaktojn + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Propra + + + + + + + + + + + + + + + + + + + + + + Propra + + Naskiĝtago + + Datreveno + + + Propra + + + + + + Propra + + + + + Propra + + + + + Propra + + + + + + + + + + + + + Propra + + Propra + + + Frato + + + + Patro + + Amiko + + + Patrino + + + + + + Fratino + + + Propra + + + + + + + + + + + + + + + + + + + + + + + + + + Reprovi + + Reprovi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pasvorto + + + + + + Malŝlosi + + + + + + + + + + + + Malplena + + + + + + + + + + + + + + + + + + + + + + + + + + vorto + + + + "%-l%P" + + "%-l%p" + + + + + + + + + + + + + + + + + + \u0020 + + + ,\u0020 + + + + + + + + + + country|location|国|国家 + + + + + + + + + + + user.?name|user.?id|vollständiger.?name|用户名 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Neniam + + + + + + + + forigi + + + + Serĉi + + + Serĉi + + + + + + + + + + + + + + + + + tago + + tagoj + + horo + + horoj + + + + + + semajno + + semajnoj + + jaro + + jaroj + + + 1 sekundo + %d sekundoj + + + + + + + + + "%1$s, %2$s" + + + + + + %1$02d:%2$02d + + %1$d:%2$02d:%3$02d + + + Eltondi + + Kopii + + Alglui + + + Forigi + + + + + + Forigi + + + + + + + + + + Nuligi + + + Nuligi + + + Ŝarĝado\u2026 + + + + + + Malfermi per + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Permesi + + Malpermesi + + + + + + + Sendi + + Nuligi + + + + + + + + + + + + + + + + + Agordi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aparataro + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Forigita + + + + + + + + + + + + + + + + + + + + + Ek + + Serĉi + + Sendi + + + + + + + + + + + + Permesi + Malpermesi + + + + + + Alirebleco + + + + + + + + + + + + + + + + Elekti dosieron + + + + + + + + + + + + + + + + + + + Konigi + + + + + + + + + Jes + + Ne + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Nuligi + + Forigi + + + + + + + + + + + + + + + + + + + + %1$s, %2$s + + + + SD-karto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fingrospuroj: + + + + + + + ", " + + + + + Ĉiam + + + + + + Telefono + + + + + Sistemo + + + + + + + + Agordoj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pasvorto + + + + + + + + + + + + + + + + + " \u2014 " + + Forigi + + + + + + + + Posedanto + + Eraro + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Nuligita + + + nekonata + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-es-rCO/cm_strings.xml b/core/res/res/values-es-rCO/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-es-rCO/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-es-rCO/strings.xml b/core/res/res/values-es-rCO/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-es-rCO/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-es-rMX/cm_strings.xml b/core/res/res/values-es-rMX/cm_strings.xml new file mode 100644 index 0000000000000..f1ca093001262 --- /dev/null +++ b/core/res/res/values-es-rMX/cm_strings.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + conmutar datos móviles + conmutar Wi-Fi + usar huella digital + añadir un mensaje de voz + acceder al estado del teléfono + buscar redes Wi-Fi + cambiar fondo de pantalla + usar estructura de asistencia + tomar captura de pantalla + usar sensores corporales + leer transmisiones celulares + simular ubicación + leer almacenamiento externo + escribir en almacenamiento externo + encender la pantalla + obtener cuentas del dispositivo + cambiar el estado de Wi-Fi + + + + + + Lanzamiento de la actividad bloqueado + %1$s está protegido de ser lanzado. Haz clic para autenticar e iniciar la aplicación. + + Batería completamente cargada + Desconecte su dispositivo del cargador para mejorar la longevidad de la batería. + + + + Las tarjetas SIM han cambiado + Toca para establecer preferencias por defecto de la tarjeta SIM + diff --git a/core/res/res/values-es-rMX/strings.xml b/core/res/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-es-rMX/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-es-rUS-watch/strings.xml b/core/res/res/values-es-rUS-watch/strings.xml index 763b24dff1ee1..35d123f4c9f31 100644 --- a/core/res/res/values-es-rUS-watch/strings.xml +++ b/core/res/res/values-es-rUS-watch/strings.xml @@ -21,4 +21,5 @@ "Aplicación %1$d de %2$d" + "Sensores" diff --git a/core/res/res/values-es-rUS/cm_strings.xml b/core/res/res/values-es-rUS/cm_strings.xml new file mode 100644 index 0000000000000..74e70ab2500c4 --- /dev/null +++ b/core/res/res/values-es-rUS/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Captura de pantalla + + recibir SMS protegidos + + Permite que la aplicación reciba mensajes SMS entrantes protegidos. + + modificar lista de SMS protegidos + + Permite que la aplicación modifique la lista de contactos SMS protegida. + + Seguridad + + Permisos relacionados con la información de seguridad del dispositivo. + + leer lista negra del teléfono + + Permite que la aplicación lea la información sobre los números de teléfono bloqueados de llamadas o mensajes entrantes. + + cambiar la lista negra del teléfono + + Permite que la aplicación cambie los números de teléfono bloqueados de llamadas o mensajes entrantes. + + establecer fondo de pantalla de bloqueo + + Permite que una aplicación establezca el fondo de pantalla bloqueada. + + Reiniciar + + Actual + + + Reiniciar + + Modo Recovery + + Modo Bootloader + + Descargas + + Reinicio rápido + + Reiniciar + + Tu tablet se reiniciará. + Tu teléfono se reiniciará. + + Reiniciando\u2026 + + Aplicación finalizada + + ADB sobre red activado + + ADB sobre USB y red activado + + Toca para desactivar la depuración. + + ADB - %1$s + USB y red + USB + Red + + interceptar la ejecución de aplicaciones + + %s no está instalado + + Prioridad + Ninguno + + Zona Wi-Fi desactivada debido a un cambio de suscripción en la SIM + + Desactivar Wi-Fi + + activar o desactivar Privacy Guard + Permite que la aplicación modifique si otra aplicación se ejecuta con Privacy Guard. Cuando una aplicación se ejecuta con Privacy Guard, no tendrá acceso a datos personales como contactos, registros de llamadas o mensajes. + Privacy Guard activada + %1$s no podrá acceder a los datos personales + Privacidad + %1$s quisiera %2$s. + + Recordar mi elección + + acceder a la cámara + acceder a tu ubicación + leer tus notificaciones + activar VPN + ejecutarse al inicio + borrar el registro de llamadas + borrar tus contactos + borrar tus mensajes MMS + borrar tus mensajes SMS + dibujar arriba + obtener estadísticas de uso de aplicaciones + mantener el dispositivo activado + hacer una llamada telefónica + actualizar el calendario + actualizar el registro de llamadas + modificar el portapapeles + actualizar tus contactos + actualizar configuración del sistema + silenciar / activar el micrófono + reproducir el audio + publicar una notificación + proyectar medios + leer el calendario + leer el registro de llamadas + leer el portapapeles + leer contactos + leer mensajes MMS + leer mensajes SMS + recibir un mensaje SMS + grabar audio + enviar un mensaje MMS + enviar un mensaje SMS + iniciar en el encendido + mostrar mensajes toast + activar/desactivar la conexión Bluetooth + conmutar los datos móviles + activar/desactivar el NFC + activar/desactivar Wi-Fi + controlar del volumen de la alarma + controlar el foco de audio + controlar el volumen del Bluetooth + controlar el volumen principal + usar los botones multimedia + controlar el volumen multimedia + controlar el volumen de notificaciones + controlar el volumen del tono de llamada + usar la respuesta háptica + controlar el volumen de las llamadas de voz + escribir un mensaje MMS + escribir un mensaje SMS + usar huella digital + añadir un mensaje de voz + acceder al estado del teléfono + buscar redes Wi-Fi + cambiar el fondo de pantalla + utilizar estructura de asistencia + tomar una captura de pantalla + utilizar sensores corporales + leer transmisiones celulares + simular ubicación + leer en almacenamiento externo + escribir en almacenamiento externo + encender la pantalla + obtener cuentas del dispositivo + cambiar el estado de Wi-Fi + obtener acceso root + + Para desanclar esta pantalla, mantén pulsado el botón Atrás. + + Ningún dispositivo conectado + %1$s dispositivo conectado + %1$s dispositivos conectados + + + + Inicio de actividad bloqueado + El inicio de %1$s está protegido. Hacer clic para autenticar e iniciar la aplicación. + + Batería completamente cargada + Desconectar el dispositivo del cargador para mejorar la vida útil de la batería. + + restablecer estadísticas de batería + + Permite que la aplicación restablezca los datos actuales de uso de la batería. + + Las tarjetas SIM han cambiado + Pulsar para establecer preferencias predeterminadas de tarjeta SIM + diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 3bed012a754bb..751c8b73e564f 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -254,7 +254,7 @@ "Incluye datos personales, como números de tarjeta de crédito y contraseñas." "desactivar o modificar la barra de estado" "Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema." - "barra de estado" + "aparecer en la barra de estado" "Permite que la aplicación sea la barra de estado." "expandir o reducir la barra de estado" "Permite que la aplicación muestre y oculte la barra de estado." @@ -282,7 +282,7 @@ "Permite que la aplicación reciba y procese mensajes WAP, lo que significa que podría controlar o eliminar mensajes enviados al usuario sin mostrártelos." "recuperar aplicaciones en ejecución" "Permite que la aplicación recupere información sobre las tareas que se estén ejecutando en ese momento o que se hayan ejecutado recientemente. La aplicación puede utilizar este permiso para descubrir cuáles son las aplicaciones que se utilizan en el dispositivo." - "Administrar perfiles de propietarios y propietario del dispositivo" + "administrar perfiles de propietarios y propietario del dispositivo" "Permite que las aplicaciones configuren los perfiles de propietarios y el propietario del dispositivo." "reorganizar aplicaciones en ejecución" "Permite que la aplicación mueva tareas a segundo o a primer plano. La aplicación puede utilizar este permiso para realizar estos movimientos sin indicártelo." @@ -324,7 +324,7 @@ "Permite que la aplicación modifique el registro de llamadas de la tablet, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas." "Permite que la aplicación modifique el registro de llamadas de la TV, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas." "Permite que la aplicación modifique el registro de llamadas del dispositivo, incluidos los datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas." - "sensores corporales (frec. card)" + "acceder a los sensores corporales (como los monitores de frecuencia cardíaca)" "Permite que la aplicación acceda a datos de sensores que controlan tu condición física, como el ritmo cardíaco." "leer eventos de calendario e información confidencial" "Permite que la aplicación consulte todos los eventos de calendario almacenados en la tablet, incluidos los de amigos y compañeros de trabajo. La aplicación puede utilizar este permiso para compartir o guardar datos del calendario del usuario sin tener en cuenta si son privados o confidenciales." @@ -336,15 +336,15 @@ "Permite que la aplicación agregue, elimine y cambie eventos que se pueden modificar en el dispositivo, incluidos los de amigos o compañeros de trabajo. La aplicación puede utilizar este permiso para enviar mensajes que parezcan proceder de propietarios de un calendario o para modificar los eventos sin el consentimiento de los propietarios." "acceder a comandos adicionales del proveedor del lugar" "Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación." - "ubicación precisa (según el GPS y la red)" + "acceder a la ubicación precisa (según el GPS y la red)" "Permite a la aplicación obtener tu ubicación precisa mediante el Sistema de Posicionamiento Global (GPS) o las fuentes de ubicación de red, como las torres de celulares y Wi-Fi. Estos servicios de ubicación deben estar encendidos y disponibles en tu dispositivo para que los use la aplicación. Las aplicaciones pueden usarlo para determinar tu ubicación, lo cual puede consumir más batería." - "ubicación aproximada (según la red)" + "acceder a la ubicación aproximada (según la red)" "Permite a la aplicación obtener tu ubicación aproximada. Esta ubicación deriva de los servicios de ubicación que usan fuentes de ubicación de red, como torres de celulares y Wi-Fi. Estos servicios de ubicación deben estar encendidos y disponibles en tu dispositivo para que los use la aplicación. Las aplicaciones pueden usarlo para determinar tu ubicación aproximada." "cambiar tu configuración de audio" "Permite que la aplicación modifique la configuración de audio global, por ejemplo, el volumen y el altavoz de salida." "grabar audio" "Permite que la aplicación grabe audio con el micrófono. La aplicación puede utilizar este permiso para grabar audio en cualquier momento sin tener tu confirmación." - "Comunicación con tarjeta SIM" + "enviar comandos a la tarjeta SIM" "Permite que la aplicación envíe comandos a la tarjeta SIM. Usar este permiso es peligroso." "tomar fotografías y grabar videos" "Permite que la aplicación saque fotos o grabe videos con la cámara. Este permiso autoriza a la aplicación a utilizar la cámara en cualquier momento sin tu confirmación." @@ -382,7 +382,7 @@ "Permite que la aplicación obtenga una lista de las cuentas reconocidas por el dispositivo, entre las que se pueden incluir las cuentas creadas por las aplicaciones que hayas instalado." "ver conexiones de red" "Permite que la aplicación vea información sobre las conexiones de red, por ejemplo, qué redes existen y están conectadas." - "acceso completo a la red" + "permitir acceso completo a la red" "Permite que la aplicación cree sockets de red y utilice protocolos de red personalizados. El navegador y otras aplicaciones proporcionan los medios necesarios para el envío de datos a Internet, por lo que no hace falta utilizar este permiso para eso." "cambiar la conectividad de la red" "Permite que la aplicación cambie el estado de la conectividad de red." @@ -402,7 +402,7 @@ "Permite que la aplicación configure el dispositivo Bluetooth local y descubra y se sincronice con dispositivos remotos." "conectarse y desconectarse de WiMAX" "Permite que la aplicación determine si está activada la conexión WiMAX y que obtenga información sobre las redes WiMAX que están conectadas." - "Cambiar el estado de WiMAX" + "cambiar estado de WiMAX" "Permite que la aplicación conecte la tablet a una red WiMAX y que la desconecte de ella." "Permite que la aplicación conecte la TV a las redes WiMAX y que la desconecte de ellas." "Permite que la aplicación conecte el dispositivo a una red WiMAX y que lo desconecte de ella." @@ -485,7 +485,7 @@ "Permite que la aplicación modifique los parámetros de calibración de la pantalla táctil. Las aplicaciones normales no deberían necesitar este permiso." "Acceder a certificados DRM" "Permite que una aplicación proporcione y utilice certificados DRM. Las aplicaciones normales no deberían necesitar este permiso." - "Recibir estado de transferencias de Android Beam" + "recibir estado de transferencias de Android Beam" "Permite que esta aplicación reciba información sobre las transferencias actuales de Android Beam" "eliminar certificados DRM" "Permite que una aplicación elimine certificados DRM. Las aplicaciones normales no deberían necesitar este permiso." @@ -1091,11 +1091,11 @@ "Formateando…" "No se insertó" "No se encontraron actividades coincidentes." - "Dirigir salida de medios" + "dirigir salida de medios" "Permite que la aplicación dirija salidas de medios a otros dispositivos externos." - "Leer sesiones de instalación" + "leer sesiones de instalación" "Permite que una aplicación lea sesiones de instalación. Esto le permite ver detalles acerca de instalaciones de paquetes activas." - "Solicitar la instalación de paquetes" + "solicitar la instalación de paquetes" "Permite que una aplicación solicite la instalación de paquetes." "Toca dos veces para acceder al control de zoom." "No se pudo agregar el widget." diff --git a/core/res/res/values-es-watch/strings.xml b/core/res/res/values-es-watch/strings.xml index d9ea0fe252a20..5e52823477cac 100644 --- a/core/res/res/values-es-watch/strings.xml +++ b/core/res/res/values-es-watch/strings.xml @@ -21,4 +21,5 @@ "Aplicación %1$d de %2$d." + "Sensores" diff --git a/core/res/res/values-es/cm_strings.xml b/core/res/res/values-es/cm_strings.xml new file mode 100644 index 0000000000000..e602fd4cb0439 --- /dev/null +++ b/core/res/res/values-es/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Captura de pantalla + + recibir SMS protegidos + + Permite que la aplicación reciba mensajes SMS entrantes protegidos. + + modificar lista de SMS protegidos + + Permite que la aplicación modifique la lista de contactos SMS protegidos. + + Seguridad + + Permisos relacionados con la seguridad de la información del dispositivo. + + leer lista negra del teléfono + + Permite que la aplicación lea la información sobre los números de teléfono bloqueados para llamadas o mensajes entrantes. + + cambiar la lista negra del teléfono + + Permite que la aplicación cambie los números de teléfono bloqueados de llamadas o mensajes entrantes. + + establecer fondo de pantalla de bloqueo + + Permite que la aplicación establezca el fondo de pantalla de bloqueo. + + Reiniciar + + Actual + + + Reiniciar + + Recovery + + Modo Bootloader + + Descargar + + Reinicio rápido + + Reiniciar + + El tablet se reiniciará. + El teléfono se reiniciará. + + Reiniciando\u2026 + + Aplicación finalizada + + ADB sobre red activado + + ADB sobre USB y red activado + + Toca para desactivar la depuración. + + ADB - %1$s + USB y red + USB + Red + + interceptar la ejecución de aplicaciones + + %s no está instalada + + Prioridad + Ninguno + + Zona Wi-Fi desactivada debido a un cambio de suscripción en la SIM + + Desactivar Wi-Fi + + activar o desactivar el protector de privacidad + Permite que la aplicación cambie el estado de privacidad de otra. Cuando una aplicación se ejecuta con la privacidad activada, no podrá acceder a los datos personales, tales como contactos, mensajes o registros de llamadas. + Privacidad activada + %1$s no podrá acceder a los datos personales + Privacidad + %1$s quiere %2$s. + + Recordar mi elección + + acceder a la cámara + acceder a tu ubicación + leer tus notificaciones + activar VPN + ejecutar al inicio + borrar el registro de llamadas + borrar tus contactos + eliminar tus mensajes MMS + eliminar tus mensajes MMS + dibujar ventanas encima + obtener estadísticas de uso de la aplicación + mantener tu dispositivo encendido + realizar una llamada + actualizar tu calendario + actualizar el registro de llamadas + modificar el portapapeles + actualizar tus contactos + actualizar los ajustes del sistema + activar/desactivar el micrófono + reproducir sonido + publicar una notificación + proyectar medios + leer tu calendario + leer el registro de llamadas + leer el portapapeles + leer tus contactos + leer tus mensajes MMS + leer tus mensajes SMS + recibir un mensaje SMS + grabar sonido + enviar un mensaje MMS + enviar un mensaje SMS + ejecutar al inicio + mostrar notificaciones emergentes + alternar Bluetooth + conmutar datos móviles + alternar NFC + alternar Wi-Fi + controlar el volumen de la alarma + controlar volumen del sonido + controlar el volumen de Bluetooth + controlar el volumen + usar los botones multimedia + controlar el volumen multimedia + controlar el volumen de notificaciones + controlar el volumen del tono de llamada + usar la respuesta háptica + controlar el volumen del teléfono + escribir un mensaje MMS + escribir un mensaje SMS + usar huella digital + añadir un mensaje de voz + acceder al estado del móvil + escanear redes Wi-Fi + cambiar el fondo de pantalla + utilizar estructura de asistencia + tomar una captura de pantalla + utilizar sensores corporales + leer transmisiones celulares + simular tu ubicación + leer almacenamiento externo + escribir el almacenamiento externo + encender la pantalla + obtener cuentas de dispositivo + cambiar estado de Wi-Fi + obtener acceso administrativo + + Para liberar esta pantalla, mantén pulsado el botón Atrás. + + Ningún dispositivo conectado + %1$s dispositivo conectado + %1$s dispositivos conectados + + + + Lanzamiento de la actividad bloqueado + %1$s tiene protección para ser ejecutado. Haz clic para autenticar e iniciar la aplicación. + + Batería completamente cargada + Desconecta tu dispositivo del cargador para mejorar la vida útil de la batería. + + restablecer estadísticas de batería + + Permite que la aplicación restablezca los datos actuales de uso de la batería. + + Las tarjetas SIM han cambiado + Toca para establecer las preferencias por defecto de la tarjeta SIM + diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 0a1a7d7dc04fa..0a4f7a87407cd 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -254,7 +254,7 @@ "Incluye datos personales como números de tarjetas de crédito y contraseñas." "inhabilitar o modificar la barra de estado" "Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema." - "barra de estado" + "aparecer en la barra de estado" "Permite que la aplicación aparezca en la barra de estado." "expandir/contraer la barra de estado" "Permite que la aplicación expanda o contraiga la barra de estado." @@ -282,7 +282,7 @@ "Permite que la aplicación reciba y procese mensajes WAP, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al usuario sin mostrárselos." "recuperar aplicaciones en ejecución" "Permite que aplicación recupere información sobre tareas que se están ejecutando en ese momento o que se han ejecutado recientemente. La aplicación puede utilizar este permiso para descubrir cuáles son las aplicaciones que se utilizan en el dispositivo." - "Administrar propietarios del perfil y del dispositivo" + "administrar propietarios del perfil y del dispositivo" "Permite que las aplicaciones establezcan los propietarios del perfil y del dispositivo." "reorganizar aplicaciones en ejecución" "Permite que la aplicación mueva tareas a segundo o a primer plano. La aplicación puede utilizar este permiso para realizar estos movimientos sin que se lo indique el usuario." @@ -324,7 +324,7 @@ "Permite que la aplicación modifique el registro de llamadas del tablet, incluidos datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas." "Permite que la aplicación modifique el registro de llamadas de la TV, incluidos datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar el registro de llamadas." "Permite que la aplicación modifique el registro de llamadas del teléfono, incluidos datos sobre llamadas entrantes y salientes. Las aplicaciones malintencionadas pueden usar este permiso para borrar o modificar el registro de llamadas." - "sensores corporales (como monitores de frecuencia cardíaca)" + "sensores corp. (como monitores frec. cardíaca)" "Permite que la aplicación acceda a datos de sensores que controlan tu condición física, como la frecuencia cardíaca." "leer eventos de calendario e información confidencial" "Permite que la aplicación consulte todos los eventos de calendario almacenados en el tablet, incluidos los de amigos y compañeros de trabajo. La aplicación puede utilizar este permiso para compartir o guardar datos del calendario del usuario sin tener en cuenta si son privados o confidenciales." @@ -336,15 +336,15 @@ "Permite que la aplicación añada, elimine y cambie eventos que se pueden modificar en el teléfono, incluidos los de amigos o compañeros de trabajo. La aplicación puede utilizar este permiso para enviar mensajes que parezcan proceder de propietarios de un calendario o para modificar eventos sin conocimiento de los propietarios." "acceder a comandos de proveedor de ubicación adicional" "Permite que la aplicación acceda a otros comandos del proveedor de ubicación. De esta forma, la aplicación podrá interferir en el funcionamiento del GPS o de otras fuentes de ubicación." - "ubicación precisa (basada en redes y GPS)" + "acceder a tu ubicación precisa (basada en red y GPS)" "Permite que la aplicación obtenga tu ubicación precisa mediante el Sistema de posicionamiento global (GPS) o fuentes de ubicación de red, como torres de telefonía y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles para que la aplicación pueda utilizarlos. Las aplicaciones pueden utilizar este permiso para determinar tu ubicación y es posible que el dispositivo consuma más batería." - "ubicación aproximada (basada en redes)" + "acceder a tu ubicación aproximada (basada en red)" "Permite que la aplicación obtenga tu ubicación aproximada. Esta ubicación se deriva de los servicios de ubicación que utilizan fuentes de ubicación de red, como torres de telefonía y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles para que la aplicación pueda utilizarlos. Las aplicaciones pueden utilizar este permiso para determinar tu ubicación de forma aproximada." "cambiar la configuración de audio" "Permite que la aplicación modifique la configuración de audio global (por ejemplo, el volumen y el altavoz de salida)." "grabar sonido" "Permite que la aplicación grabe audio con el micrófono. La aplicación puede utilizar este permiso para grabar audio en cualquier momento sin tener la confirmación del usuario." - "comunicación con la tarjeta SIM" + "enviar comandos a la tarjeta SIM" "Permite que la aplicación envíe comandos a la tarjeta SIM. Este permiso es muy peligroso." "realizar fotografías y vídeos" "Permite que la aplicación haga fotos o grabe vídeos con la cámara. Este permiso autoriza a la aplicación a utilizar la cámara en cualquier momento sin tu confirmación." @@ -382,7 +382,7 @@ "Permite que la aplicación obtenga una lista de cuentas reconocidas por el teléfono, entre las que se pueden incluir las cuentas creadas por las aplicaciones que hayas instalado." "ver conexiones de red" "Permite que la aplicación vea información sobre conexiones de red (por ejemplo, qué redes existen y están conectadas)." - "acceso completo a la red" + "tener acceso completo a la red" "Permite que la aplicación cree sockets de red y utilice protocolos de red personalizados. El navegador y otras aplicaciones proporcionan los medios necesarios para el envío de datos a Internet, por lo que no hace falta utilizar este permiso para eso." "cambiar la conectividad de red" "Permite que la aplicación modifique el estado de la conectividad de red." @@ -402,7 +402,7 @@ "Permite que la aplicación configure el teléfono Bluetooth local y que detecte dispositivos remotos y se vincule con ellos." "conectarse a WiMAX y desconectarse de esta red" "Permite que la aplicación determine si está habilitada la conexión WiMAX y obtenga información sobre las redes WiMAX que están conectadas." - "Cambiar estado de WiMAX" + "cambiar estado de WiMAX" "Permite que la aplicación conecte el tablet a redes WiMAX y lo desconecte de ellas." "Permite que la aplicación conecte la TV a una red WiMAX y la desconecte." "Permite que la aplicación conecte el teléfono a redes WiMAX y lo desconecte de ellas." @@ -485,7 +485,7 @@ "Permite que la aplicación modifique los parámetros de calibración de la pantalla táctil. No debe ser necesario para las aplicaciones normales." "acceder a certificados DRM" "Permite que una aplicación proporcione y utilice certificados DRM. Las aplicaciones normales no deberían necesitar este permiso." - "Recibir estado de transferencias de Android Beam" + "recibir estado de transferencias de Android Beam" "Permite que esta aplicación reciba información sobre las transferencias actuales de Android Beam" "eliminar certificados DRM" "Permite a una aplicación eliminar los certificados DRM. Las aplicaciones normales no deberí­an necesitar este permiso." @@ -1091,11 +1091,11 @@ "Formateando…" "No insertado" "No se ha encontrado ninguna actividad coincidente." - "Dirigir salida de medio" + "dirigir salida de medio" "Permite que la aplicación dirija salidas de medios a otros dispositivos externos." - "Consultar sesiones de instalación" + "consultar sesiones de instalación" "Permite que una aplicación consulte sesiones de instalación para ver detalles sobre instalaciones de paquetes activos." - "Solicitar instalación de paquetes" + "solicitar instalación de paquetes" "Permite a una aplicación solicitar la instalación de paquetes." "Toca dos veces para acceder al control de zoom." "No se ha podido añadir el widget." diff --git a/core/res/res/values-et-rEE-watch/strings.xml b/core/res/res/values-et-rEE-watch/strings.xml index 0adb487acfe36..fc9b98aa9109d 100644 --- a/core/res/res/values-et-rEE-watch/strings.xml +++ b/core/res/res/values-et-rEE-watch/strings.xml @@ -21,4 +21,5 @@ "Rakendus %1$d/%2$d." + "Andurid" diff --git a/core/res/res/values-et-rEE/cm_strings.xml b/core/res/res/values-et-rEE/cm_strings.xml new file mode 100644 index 0000000000000..3873fe7a7fd47 --- /dev/null +++ b/core/res/res/values-et-rEE/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Ekraanipilt + + saa kaitstud SMSe + + Lubab rakendusel vastu võtta sissetuleva kaitstud SMSi. + + muuda kaitstud SMS nimekirja + + Lubab rakendusel muuta kaitstud SMS aadressiloendit. + + Turvalisus + + Õigused on seotud seadme turvalisuse teabega. + + lugeda telefoni musta nimekirja + + Lubab rakendusel lugeda teavet telefoninumbrite kohta, mis on sissetulevate kõnede ja sõnumite jaoks blokeeritud. + + muuta telefoni musta nimekirja + + Annab rakendusele õiguse muuta sissetulevate kõnede ja sõnumite jaoks blokeeritud numbreid. + + muuta lukuekraani pilti + + Lubab rakendusel muuta lukustusekraani taustapilti. + + Taaskäivitamine + + Praegune + + + Taaskäivita + + Recovery + + Bootloader + + Download režiim + + Poolik taaskäivitus + + Taaskäivita + + Teie tahvelarvuti taaskäivitub. + Teie telefon taaskäivitub. + + Taaskäivitamine\u2026 + + Rakendus suletud + + ADB üle võrgu aktiveeritud + + ADB üle USB & võrgu aktiveeritud + + Puuduta silumise lõpetamiseks. + + ADB - %1$s + USB & võrk + USB + Võrk + + rakenduse käivitamise katkestamine + + %s ei ole installitud + + Prioriteet + Puudub + + WiFi hotspot lülitati välja kuna muutus SIM kaardi teenused + + Lülita WiFi välja + + lubada või keelata privaatsuskaitset + Sellega lubate muuta mõne muu rakenduse käivitumist Privaatsuskaitsega. Kui rakendus töötab sisselülitatud Privaatsuskaitsega, puudub rakendusel ligipääs isiklikele andmetele nagu kontaktid, kõnelogid või sõnumid. + Privaatsuskaitse aktiveeritud + %1$s ei pääse ligi isiklikele andmetele + Privaatsuskaitse + %1$s tahab %2$s. + + Jäta meelde minu valik + + kontrollida kaamerat + kontrollida asukohta + lugeda teateid + aktiveeri VPN + käivitada sisselülitamisel + kustutada kõnelogi + kustutada kontakte + kustutada MMS sõnumeid + kustutada SMS sõnumeid + joonistada aknaid peale + saada rakenduse kasutamise statistikat + hoida seade ärkvel + teha telefoni kõnet + värskendada kalendrit + värskendada kõnelogi + muuta lõikelauda + värskendada kontakte + värskendada süsteemiseadeid + välja/sisse lülitada mikrofoni + mängida heli + postitada teateid + projekteerida meediat + vaadata kalendrit + vaadata kõnelogi + vaadata lõikelauda + vaadata kontakte + lugeda MMS sõnumeid + lugeda SMS sõnumeid + võtta vastu SMS sõnum + salvestada heli + saata MMS sõnum + saata SMS sõnum + käivitada sisselülitamisel + näidata lühisõnumeid + lülitada Bluetooth\'i + lülita mobiilne andmeside sisse-välja + lülitada NFC + lülita Wi-Fi sisse-välja + muuta alarmi helitugevust + muuta audio fookust + muuta Bluetooth heli tugevust + muuta üldist helitugevust + kasutada meedia nuppe + muuta meedia helitugevust + muuta teavituse helitugevust + muuta helina tugevust + kasutada puute vibratsiooni + muuta telefoni kõne helitugevust + kirjutada MMS sõnumit + kirjutada SMS sõnumit + kasuta sõrmejälge + lisa kõnepost + juurdepääs telefoni olekule + otsida Wi-Fi võrke + muuta taustapilti + kasuta assisteeritud struktuuri + kuvatõmmise tegemine + kasutada biosensoreid + lugeda võrguteateid + teeskle asukohta + lugeda väliselt andmekandjalt + kirjutada välisele andmekandjale + lülitada ekraan sisse + lugeda seadme kasutajaid + muuta Wi-Fi olekut + saada root ligipääsu + + Selle ekraani vabastamiseks puudutage ja hoidke all Tagasi nuppu. + + Pole ühtegi ühendatud seadet + %1$s ühendatud seade + %1$s ühendatud seadet + + + + Tegevuse käivitamine blokeeriti + %1$s keelati käivitamast. Koputage rakenduse autentimiseks ja käivitamiseks. + + Aku täis + Ühenda telefon laadijast, et parandada aku eluiga. + + nullida aku statistikat + + Lubab rakendusel nullida aku praeguse madala-tasemelise kasutuse andmed. + + SIM-kaardid on muutunud + Koputa, et muuta SIM-kaardi vaikesätteid + diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index ddf5a6da135d7..cd88275dd2d36 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -254,7 +254,7 @@ "Sisaldab isiklikke andmeid, nt krediitkaardi numbreid ja paroole." "keela või muuda olekuriba" "Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone." - "olekuriba" + "olekuribana kuvamine" "Võimaldab rakendusel olla olekuriba." "laienda/ahenda olekuriba" "Võimaldab rakendusel laiendada või ahendada olekuriba." @@ -282,7 +282,7 @@ "Võimaldab rakendusel vastu võtta ja töödelda WAP-sõnumeid. See luba hõlmab võimet jälgida või kustutada teile saadetud sõnumeid neid teile näitamata." "Käitatud rakenduste toomine" "Võimaldab rakendusel tuua teavet praegu ja hiljuti käitatud ülesannete kohta. See võib lubada rakendusel avastada teavet selle kohta, milliseid rakendusi seadmes kasutatakse." - "Profiili- ja seadmeomanike haldamine" + "profiilide ja seadme omanike haldamine" "Võimaldab rakendustel määrata profiiliomanikud ja seadmeomaniku." "käitatud rakenduste ümberjärjestamine" "Võimaldab rakendusel teisaldada ülesanded esiplaanile ja taustale. Rakendus võib seda teha teie sisendita." @@ -324,7 +324,7 @@ "Lubab rakendusel muuta tahvelarvuti kõnelogi, sh sissetulevate ja väljaminevate kõnede andmeid. Pahatahtlikud rakendused võivad kasutada seda kõnelogi kustutamiseks või muutmiseks." "Lubab rakendusel muuta teleri kõnelogi, sh sissetulevate ja väljaminevate kõnede andmeid. Pahatahtlikud rakendused võivad kasutada seda kõnelogi kustutamiseks või muutmiseks." "Lubab rakendusel muuta telefoni kõnelogi, sh sissetulevate ja väljaminevate kõnede andmeid. Pahatahtlikud rakendused võivad kasutada seda kõnelogi kustutamiseks või muutmiseks." - "kehaandurid (nt pulsilugeja)" + "juurdepääs kehaanduritele (nt pulsilugeja)" "Lubab rakendusel hankida juurdepääsu andmetele anduritest, mis jälgivad teie füüsilist seisundit, nt südame löögisagedust." "kalendrisündmuste lugemine ja konfidentsiaalne teave" "Võimaldab rakendusel lugeda kõiki tahvelarvutisse salvestatud kalendrisündmusi, sh sõprade või töökaaslaste omi. See võib lubada rakendusel jagada või salvestada teie kalendriandmeid, hoolimata konfidentsiaalsusest või tundlikkusest." @@ -336,15 +336,15 @@ "Võimaldab rakendusel lisada, eemaldada ja muuta sündmusi, mida saate muuta oma telefonis, sh sõprade ja töökaaslaste omi. See võib võimaldada rakendusel saata sõnumeid, mis näivad tulevat kalendri omanikelt, või muuta sündmusi omaniku teadmata." "juurdepääs asukohapakkuja lisakäskudele" "Võimaldab rakendusel juurde pääseda asukohapakkuja erikäskudele. See võib lubada rakendusel mõjutada GPS-i või muude asukohaallikate tööd." - "täpne asukoht (GPS- ja võrgupõhine)" + "juurdepääs täpsele asukohale (GPS-i ja võrgupõhine)" "Lubab rakendusel hankida teie täpse asukoha globaalse positsioneerimissüsteemi (GPS) või võrgu asukohaallikate (nt mobiilimastide ja WiFi) järgi. Need asukohateenused peavad olema sisse lülitatud ja teie seadme jaoks saadaval, et rakendus saaks neid kasutada. Rakendused võivad kasutada seda teie asukoha tuvastamiseks ja tarbida akut." - "ligikaudne asukoht (võrgupõhine)" + "juurdepääs ligikaudsele asukohale (võrgupõhine)" "Lubab rakendusel hankida juurdepääsu ligikaudsele asukohale. Asukoht tuletatakse asukohateenuste järgi, kasutades võrgu asukohaallikaid, nt mobiilimastid ja WiFi. Need asukohateenused peavad olema sisse lülitatud ja teie seadme jaoks saadaval, et rakendus saaks neid kasutada. Rakendused võivad kasutada seda teie ligikaudse asukoha tuvastamiseks." "muuda heliseadeid" "Võimaldab rakendusel muuta üldiseid heliseadeid, näiteks helitugevust ja seda, millist kõlarit kasutatakse väljundiks." "salvesta heli" "Võimaldab rakendusel salvestada mikrofoniga heli. See luba võimaldab rakendusel salvestada heli igal ajal ilma teie kinnituseta." - "side SIM-kaardiga" + "SIM-kaardile käskluste saatmine" "Lubab rakendusel saata käske SIM-kaardile. See on väga ohtlik." "piltide ja videote tegemine" "Võimaldab rakendusel teha kaameraga pilte ja videoid. See luba võimaldab rakendusel kasutada kaamerat mis tahes ajal teie kinnituseta." @@ -382,7 +382,7 @@ "Võimaldab rakendusel hankida telefonile teadaolevaid kontoloendeid. See võib hõlmata mis tahes kontosid, mille on loonud teie installitud rakendused." "vaadake võrguühendusi" "Lubab rakendusel vaadata teavet võrguühenduste kohta, näiteks seda, millised võrgud on olemas ja ühendatud." - "täielik juurdepääs võrgule" + "täielik juurdepääs võrgule" "Võimaldab rakendusel luua võrgupesasid ja kasutada kohandatud võrguprotokolle. Brauser ja teised rakendused annavad vahendid andmete saatmiseks Internetti, nii et seda luba ei ole vaja andmete saatmiseks Internetti." "muuda võrguühenduvust" "Võimaldab rakendusel muuta võrguühenduvuse olekut." @@ -402,7 +402,7 @@ "Võimaldab rakendusel seadistada kohalikku Bluetooth-telefoni ning leida ja siduda seda kaugseadmetega." "WiMAX-iga ühenduse loomine ja ühenduse katkestamine" "Võimaldab rakendusel määrata, kas WiMAX on lubatud, ja vaadata teavet kõikide ühendatud WiMAX-võrkude kohta." - "WiMAX-i oleku muutmine" + "WiMAX-i oleku muutmine" "Võimaldab rakendusel luua ja katkestada tahvelarvuti ühenduse WiMAX-i võrkudega." "Lubab rakendusel ühendada teleri WiMAX-i võrku ja ühenduse katkestada." "Võimaldab rakendusel luua ja katkestada telefoni ühenduse WiMAX-i võrkudega." @@ -485,7 +485,7 @@ "Lubab rakendusel muuta puuteekraani kalibreerimisparameetreid. Ei tohiks kunagi olla vajalik tavaliste rakenduste puhul." "juurdepääs DRM-i sertifikaatidele" "Lubab rakendusel ette valmistada ja kasutada DRM-i sertifikaate. Tavarakenduste puhul ei tohiks see vajalik olla." - "Android Beami ülekande oleku vastuvõtmine" + "Android Beami ülekande oleku vastuvõtmine" "Lubab rakendusel saada teavet praeguste Android Beami ülekannete kohta" "DRM-sertifikaatide eemaldamine" "Lubab rakendusel eemaldada DRM-sertifikaate. Pole kunagi vajalik tavaliste rakenduste puhul." @@ -1091,11 +1091,11 @@ "Vormindamine ..." "Pole sisestatud" "Sobivat tegevust ei leitud" - "Meediaväljundi teekonna koostamine" + "meediaväljundi marsruutimine" "Võimaldab rakendusel koostada teekonna meediaväljundist teistesse välistesse seadmetesse." - "Installiseansside lugemine" + "installiseansside lugemine" "Lubab rakendusel lugeda installiseansse. See võimaldab näha aktiivse paketi installimise üksikasju." - "Installipakettide taotlemine" + "installipakettide taotlemine" "Võimaldab rakendusel pakettide installimist taotleda." "Suumi juhtimiseks puudutage kaks korda" "Vidinat ei saanud lisada." diff --git a/core/res/res/values-eu-rES-watch/strings.xml b/core/res/res/values-eu-rES-watch/strings.xml index 9c13ef9ef4a95..670bc04f10a32 100644 --- a/core/res/res/values-eu-rES-watch/strings.xml +++ b/core/res/res/values-eu-rES-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d/%2$d aplikaz." + "Sentsoreak" diff --git a/core/res/res/values-eu-rES/cm_strings.xml b/core/res/res/values-eu-rES/cm_strings.xml new file mode 100644 index 0000000000000..847aafccb8fde --- /dev/null +++ b/core/res/res/values-eu-rES/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Pantaila-argazkia + + jaso SMS babestua + + SMS mezu babestua jasotzea ahalbidetzen dio aplikazioari. + + aldatu SMS babestuen zerrenda + + SMS babestuen helbide zerrenda aldatzea ahalbidetzen dio aplikazioari. + + Segurtasuna + + Gailuaren segurtasun informazioarekin erlazionaturiko baimenak. + + Telefonoaren zerrenda beltza irakurri + + Sarrera dei edo SMS mezuak blokeatuta dituzten telefono zenbakien informazioa irakurtzea ahalbidetzen dio aplikazioari. + + aldatu telefonoen zerrenda beltza + + Sarrera deiak eta SMS mezuak blokeatuta dituzten zenbakien zerrenda aldatzea ahalbidetzen dio aplikazioari. + + Ezarri blokeo-pantailarako horma-papera + + Blokeo-pantailarako horma-papera aldatzea ahalbidetzen dio aplikazioari. + + Berrabiarazi + + Oraingoa + + + Berrabiarazi + + Berreskuratzea + + Abiarazlea + + Deskarga + + Berrabiatze leuna + + Berrabiarazi + + Tableta berrabiarazi egingo da. + Telefonoa berrabiarazi egingo da. + + Berrabiarazten\u2026 + + Aplikazioa eten da + + Sare gaineko ADB gaitua + + USB eta sare gaineko ADB gaitua + + Sakatu arazketa ezgaitzeko. + + ADB - %1$s + USB eta sarea + USB + Sarea + + Eragotzi aplikazioak abiaraztea + + %s ez dago instalatuta + + Lehentasuna + Bat ere ez + + Wi-Fi gunea desgaitu da SIM harpidetza aldatu delako + + Ezgaitu Wi-Fia + + gaitu edo ezgaitu Privacy Guard + Beste aplikazio bat Privacy Guard menpean dagoen aldatzea ahalbidetzen dio aplikazioari. Aplikazio bat Privacy Guard menpean dagoenean ezin izango du datu pertsonalik ikusi, ez kontakturik, ez dei erregistrorik, ezta mezurik ere. + Privacy Guard aktibo + %1$s aplikazioak ezingo du datu pertsonalik irakurri + Privacy Guard + %1$s aplikazioak %2$s ahal izatea nahi du. + + Gogoratu nire aukera + + kamera atzitu + zure kokalekua atzitu + zure jakinarazpenak irakurri + VPN bat aktibatu + abioan exekutatu + zure dei egunkaria ezabatu + zure kontaktuak ezabatu + zure MMS mezuak ezabatu + zure SMS mezuak ezabatu + leihoak besteen gainetik marraztu + aplikazioen erabilera estatistikak jaso + gailua esnatuta mantendu + telefono dei bat egin + egutegia eguneratu + dei erregistroa eguneratu + arbela aldatu + zure kontaktuak eguneratu + eguneratu sistemaren ezarpenak + mikrofonoa mututu/desmututu + soinua erreproduzitu + jakinarazpen bat argitaratu + multimedia proiektatu + zure egutegia irakurri + dei erregistroa irakurri + arbela irakurri + zure kontaktuak irakurri + zure MMS mezuak irakurri + zure SMS mezuak irakurri + SMS mezu bat jaso + soinua grabatu + MMS mezu bat bidali + SMS mezu bat bidali + exekutatu abioan + laster-leihoa mezuak bistaratu + Bluetooth txandakatu + txandakatu datu mugikorrak + NFC txandakatu + Wi-Fia txandakatu + alarmen bolumena kontrolatu + audio fokua kontrolatu + Bluetooth bolumena kontrolatu + bolumen orokorra kontrolatu + multimedia botoiak erabili + multimedia bolumena kontrolatu + jakinarazpen bolumena kontrolatu + dei doinuaren bolumena kontrolatu + erantzun haptikoa erabili + ahots deiaren bolumena kontrolatu + MMS mezu bat idatzi + SMS mezu bat idatzi + hatz-marka erabili + gehitu ahots postontzia + telefonoaren egoera atzitu + eskaneatu Wi-Fi sareak + aldatu horma-irudia + estruktura lagungarria erabili + egin pantaila-argazkia + erabili gorputz sentsoreak + zelulen banaketa mezuak irakurri + kokapena faltsutu + kanpo biltegiratzea irakurri + kanpo biltegiratzean idatzi + pantaila piztu + eskuratu gailuaren kontuak + Wi-Fiaren egoera aldatu + root sarbidea eskuratu + + Pantaila hau desiltzatzeko sakatu eta mantendu atzera botoia. + + Ez da gailurik konektatu + gailu %1$s konektatuta + %1$s gailu konektatuta + + + + Aktibitatea abiatzea blokeatu da + %1$s abiatzeko babestuta dago. Sakatu nortasuna egiaztatzeko eta aplikazioa abiatzeko. + + Bateria erabat kargatuta + Deskonektatu zure gailua kargagailutik bateriaren bizitza luzatzeko. + + ezabatu bateriaren estatistikak + + Bateriaren maila baxuko erabilera datuak leheneratzea ahalbidetzen dio aplikazioari. + + SIM txartelak aldatu dira + Sakatu SIM txartelaren lehenetsitako hobespenak ezartzeko + diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index 5bf8f2000647b..4e0f32d80b2fb 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -254,7 +254,7 @@ "Ez da salbuespenik egiten datu pertsonalekin, hala nola, kreditu-txartelen zenbakiekin eta pasahitzekin." "Desgaitu edo aldatu egoera-barra" "Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei." - "egoera-barra" + "Bihurtu egoera-barra" "Egoera-barra izatea baimentzen die aplikazioei." "zabaldu/tolestu egoera-barra" "Egoera-barra zabaltzea edo tolestea baimentzen die aplikazioei." @@ -282,7 +282,7 @@ "WAP mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak, besteak beste, gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe." "Eskuratu abian diren aplikazioak" "Unean edo duela gutxi exekutatutako zereginei buruzko informazioa lortzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailuan erabiltzen ari diren aplikazioei buruzko informazioa ezagut dezake." - "Kudeatu profilen eta gailuen jabeak" + "Kudeatu profilen eta gailuen jabeak" "Profilaren eta gailuaren jabeak zehazteko baimena ematen die aplikazioei." "Ordenatu abian diren aplikazioak" "Zereginak aurreko eta atzeko planora eramateko baimena ematen die aplikazioei. Aplikazioak zuk ezer egin gabe egin dezake hori." @@ -324,7 +324,7 @@ "Tabletaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete." "Telebistako deien erregistroa aldatzea baimentzen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete." "Telefonoaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Aplikazio gaiztoek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete." - "Gorputzaren sentsoreak (adibidez, bihotz-erritmoaren monitoreak)" + "Atzitu gorputzaren sentsoreak (adibidez, bihotz-maiztasunarenak)" "Zure egoera fisikoa kontrolatzen duten sentsoreetako datuak (adibidez, bihotz-maiztasuna) atzitzea baimentzen die aplikazioei." "irakurri egutegiko gertaerak eta isilpeko informazioa" "Tabletan gordetako egunkari-gertaera guztiak irakurtzeko baimena ematen die aplikazioei, lagunenak eta lankideenak barne. Horrela, aplikazioak egutegiko datuak parteka edo gorde ditzake, isilpekotasuna edo konfidentzialtasuna kontuan izan gabe." @@ -336,15 +336,15 @@ "Telefonoan alda ditzakezun gertaerak gehitzeko, kentzeko eta aldatzeko baimena ematen die aplikazioei, lagunenak eta lankideenak barne. Horrela, aplikazioak egutegi-jabeenak diruditen mezuak bidal ditzake, edo gertaerak alda ditzake jabeak jakin gabe." "atzitu kokapen-hornitzaileen komando gehigarriak" "Kokapen-hornitzailearen agindu gehigarriak atzitzea baimentzen die aplikazioei. Horrela, agian aplikazioek GPSaren edo bestelako kokapenaren iturburuen funtzionamenduan eragina izan dezakete." - "kokapena zehatza (GPSan eta sarean oinarrituta)" + "Atzitu kokapen zehatza (GPS sisteman eta sarean oinarrituta)" "GPSaren edo sarearen kokapenaren iturburuak (adibidez telefonia mugikorreko dorreak eta Wi-Fi sarea) erabilita kokapen zehatza lortzeko baimena ematen die aplikazioei. Kokapen-zerbitzu horiek gailuan aktibatuta eta erabilgarri egon behar dute, aplikazioak erabil ditzan. Aplikazioek baimen hori erabil dezakete gutxi gorabehera non zauden jakiteko, eta bateria gehiago behar izan daiteke." - "Gutxi gorabeherako kokapena (sarean oinarrituta)" + "Atzitu gutxi gorabeherako kokapena (sarean oinarrituta)" "Zure gutxi gorabeherako kokapena lortzeko baimena ematen dio aplikazioari. Kokapena kokapen-zerbitzuetatik lortzen da sarearen kokapenaren iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sarea) erabilita. Kokapen-zerbitzu horiek gailuan aktibatuta eta erabilgarri egon behar dute, aplikazioak erabil ditzan. Aplikazioek baimen hori erabil dezakete gutxi gorabehera non zauden jakiteko." "aldatu audio-ezarpenak" "Audio-ezarpen orokorrak aldatzeko baimena ematen dio; besteak beste, bolumena eta irteerarako zer bozgorailu erabiltzen den." "grabatu audioa" "Mikrofonoarekin audioa grabatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioak audioa edonoiz graba dezake zure baimenik gabe." - "Komunikatu SIMarekin" + "Bidali aginduak SIM txartelera" "SIM txartelera aginduak bidaltzeko aukera ematen die aplikazioei. Oso arriskutsua da." "atera argazkiak eta grabatu bideoak" "Kamerarekin argazkiak ateratzeko eta bideoak grabatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioak kamera edonoiz erabil dezake zure baimenik gabe." @@ -382,7 +382,7 @@ "Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barne." "sare-konexioak ikustea" "Sare-konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta." - "sare osorako sarbidea" + "Izan sarerako sarbide osoa" "Sare-socketak sortzeko eta sare-protokolo pertsonalizatuak erabiltzeko baimena ematen die aplikazioei. Arakatzaileak eta beste aplikazio batzuek Internetera konektatzeko moduak eskaintzen dituzte, beraz, baimen hori ez da beharrezkoa datuak Internetera bidaltzeko." "aldatu sarearen konektagarritasuna" "Sarearen konexioaren egoera aldatzea baimentzen die aplikazioei." @@ -402,7 +402,7 @@ "Tokiko Bluetooth telefonoa konfiguratzea eta urruneko gailuak detektatzea eta haiekin parekatzea baimentzen die aplikazioei." "WiMAX sarera konektatzea eta deskonektatzea" "WiMAX gaituta dagoen zehazteko eta konektatutako WiMAX sareei buruzko informazioa ikusteko baimena ematen die aplikazioei." - "WiMAX egoera aldatzea" + "Aldatu WiMAX egoera" "Tableta WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei." "Telebista WiMAX sareetara konektatzea edo haietatik deskonektatzea baimentzen die aplikazioei." "Telefonoa WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei." @@ -485,7 +485,7 @@ "Ukipen-pantailaren kalibrazio-parametroak aldatzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko." "Atzitu DRM ziurtagiriak" "DRM ziurtagiriak hornitzea eta erabiltzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko." - "Jaso Android Beam transferentzien egoera" + "Jaso Android Beam transferentzien egoera" "Uneko Android Beam transferentziei buruzko informazioa jasotzea baimentzen die aplikazioei" "kendu DRM ziurtagiriak" "DRM ziurtagiriak kentzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko." @@ -1091,11 +1091,11 @@ "Formateatzen…" "Ez dago sartuta" "Ez da bat datorren jarduerarik aurkitu." - "Multimedia-irteera bideratzea" + "Bideratu multimedia-irteera" "Multimedia elementuak kanpoko gailuetara bideratzeko baimena ematen die aplikazioei." - "Irakurri instalazio-saioak" + "Irakurri instalazio-saioak" "Instalazio-saioak irakurtzea baimentzen die aplikazioei. Horrela, pakete-instalazio aktiboei buruzko xehetasunak ikus ditzakete." - "Eskatu paketeak instalatzeko" + "Eskatu instalazio-paketeak" "Paketeak instalatzeko eskatzea baimentzen die aplikazioei." "Ukitu birritan zooma kontrolatzeko" "Ezin izan da widgeta gehitu." diff --git a/core/res/res/values-fa-watch/strings.xml b/core/res/res/values-fa-watch/strings.xml index a33d7ecd4279d..1ddb38656978f 100644 --- a/core/res/res/values-fa-watch/strings.xml +++ b/core/res/res/values-fa-watch/strings.xml @@ -21,4 +21,5 @@ "برنامه %1$d از %2$d." + "حسگرها" diff --git a/core/res/res/values-fa/cm_strings.xml b/core/res/res/values-fa/cm_strings.xml new file mode 100644 index 0000000000000..e8278c21aec4c --- /dev/null +++ b/core/res/res/values-fa/cm_strings.xml @@ -0,0 +1,170 @@ + + + + + + تصویر صفحه + + دریافت پیامک محفاظت شده + + به برنامه اجازه می‌دهد پیام محافظت شده‌ای دریافت کند. + + ویرایش لیست پیامک محافظت شده + + به برنامه اجازه می‌دهد لیست آدرس پیامک‌های محافظت شده را تغییردهد. + + امنیت + + مجوزهای مربوط به اطلاعات امنیتی دستگاه. + + مشاهده لیست سیاه گوشی + + به برنامه اجازه می‌دهد اطلاعات مربوط به شماره تلفن‌های مسدود را برای پیام‌ها یا تماس‌های ورودی بخواند. + + تغییر لیست سیاه گوشی + + به برنامه اجازه می‌دهد شماره تلفن‌های مسدود را برای پیام‌ها یا تماس‌های ورودی تغییر دهد. + + تنظیم کاغذدیواری قفل صفحه + + به برنامه اجازه می‌دهد کاغذدیواری قفل صفحه را تغییر دهد. + + راه‌اندازی مجدد + + فعلی + + + معمولی + + ریکاوری + + بوت لودر + + دانلود + + سافت + + راه‌اندازی مجدد + + تبلت شما مجددا راه‌اندازی خواهد شد. + گوشی شما مجددا راه‌اندازی خواهد شد. + + راه‌اندازی مجدد\u2026 + + برنامه بسته شد + + ای‌دی‌بی از طریق شبکه فعال شد + + ای‌دی‌بی از طریق شبکه و یواس‌بی فعال شد + + برای غیرفعال کردن اشکال‌زدایی لمس کنید. + + ای‌دی‌بی - %1$s + شبکه و یواس‌بی + یواس‌بی + شبکه + + جلوگیری از اجرا شدن برنامه + + %s نصب نیست + + اولویت‌دار + هیچ‌کدام + + نقطه اتصال قابل حمل وای‌فای به دلیل تغییر تعرفه سیم کارت، غیرفعال شد + + خاموش کردن وای‌فای + + فعال یا غیرفعال کردن محافظ حریم خصوصی + به برنامه اجازه می‌دهد اجرا شدن برنامه‌های دیگر با محافظ حریم خصوصی را تغییر دهد. هنگامی که یک برنامه با محافظ حریم خصوصی اجرا می‌شود، به اطلاعات شخصی مانند مخاطبین، گزارش‌های تماس یا پیام‌ها دسترسی نخواهد داشت. + محافظ حریم خصوصی فعال است + %1$s به اصلاعات شخصی دسترسی نخواهد داشت + محافظ حریم خصوصی + %1$s می‌خواهد %2$s انجام دهد. + + انتخابم را به یاد داشته باش + + دسترسی به دوربین + دسترسی به مکان شما + مشاهده اعلان‌های شما + فعال کردن وی‌پی‌ان + اجرا هنگام روشن شدن + حذف گزارش تماس شما + حذف مخاطبین شما + حذف پیام‌های ام‌ام‌اس شما + حذف پیامک‌های شما + نمایش در بالای پنجره‌های دیگر + دریافت وضعیت استفاده از برنامه‌ها + بیدار نگه داشتن دستگاه + برقراری تماس + بروز کردن تقویم شما + بروز کردن گزارش تماس + ویرایش کلیپ برد + بروز کردن مخاطبین + بروز کردن تنظیمات سیستمی + قطع/وصل کردن میکروفون + پخش صدا + ارسال اعلان + پخش رسانه + مشاهده تقویم شما + مشاهده گزارش تماس + مشاهده کلیپ برد + مشاهده مخاطبین شما + مشاهده پیام‌های ام‌ام‌اس شما + مشاهده پیامک‌های شما + دریافت پیامک + ضبط صدا + ارسال پیام ام‌ام‌اس + ارسال پیامک + اجرا هنگام روشن شدن + نمایش متن‌های کوچک + روشن و خاموش کردن بلوتوث + روشن و خاموش کردن ان‌اف‌سی + کنترل صدای هشدار + کنترل کانون صدا + کنترل صدای بلوتوث + کنترل صدای اصلی + استفاده از کلیدهای رسانه + کنترل صدای رسانه + کنترل صدای اعلان + کنترل صدای زنگ + استفاده از بازخورد لمسی + کنترل صدای تماس صوتی + نوشتن پیام ام‌ام‌اس + نوشتن پیامک + دریافت دسترسی روت + + برای از سنجاق درآوردن این صفحه، دکمه بازگشت را زده و نگه دارید. + + هیچ دستگاه متصلی وجود ندارد + %1$s دستگاه متصل + %1$s دستگاه متصل + + + + + + تنظیم مجدد آمار کارکرد باتری + + به برنامه اجازه می‌دهد داده‌های مربوط به استفاده از باتری با سطح شارژ پایین را مجددا تنظیم کند. + + diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index f4e7555137b21..b748582677c4c 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -254,7 +254,7 @@ "اطلاعات شخصی مانند شماره کارت اعتباری و گذرواژه‌ها را لحاظ می‌کند." "غیرفعال کردن یا تغییر نوار وضعیت" "‏به برنامه اجازه می‎دهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند." - "نوار وضعیت" + "نوار وضعیت باشد" "‏به برنامه اجازه می‎دهد که تبدیل به نوار وضعیت شود." "گسترش دادن/جمع کردن نوار وضعیت" "‏به برنامه اجازه می‎دهد تا نوار ابزار را جمع کند یا باز کند." @@ -282,7 +282,7 @@ "‏به برنامه اجازه می‌دهد پیام‌های WAP را دریافت و پردازش کند. این مجوز می‌تواند پیام‌های ارسالی به شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند." "‏بازیابی برنامه‎های در حال اجرا" "به برنامه امکان می‌دهد اطلاعات مربوط به کارهای در حال اجرای اخیر و کنونی را بازیابی کند. این ممکن است به برنامه امکان دهد به اطلاعات مربوط به برنامه‌هایی که در دستگاه استفاده می‌شوند دست یابد." - "مدیریت مالکان نمایه و دستگاه" + "مدیریت نمایه و مالکان دستگاه" "به برنامه‌ها امکان می‌دهد، مالکان نمایه و مالک دستگاه را تنظیم کنند." "‏تنظیم مجدد ترتیب برنامه‎های در حال اجرا" "‏به برنامه اجازه می‎دهد تا کارها را به پیش‌زمینه و پس‌زمینه منتقل کند. برنامه‎ ممکن است بدون دخالت شما این کار را انجام دهد." @@ -324,7 +324,7 @@ "‏به برنامه اجازه می‌دهد گزارشات تماس رایانهٔ لوحی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند." "‏به برنامه اجازه می‌دهد گزارشات تماس تلویزیون شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب شاید از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند." "‏به برنامه اجازه می‌دهد گزارشات تماس تلفنی شما، از جمله داده‌هایی درمورد تماس‎های ورودی و خروجی را تغییر دهد. برنامه‌های مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند." - "حسگرهای بدن (مانند پایشگرهای ضربان قلب)" + "دسترسی به حسگرهای بدن (مانند پایشگرهای ضربان قلب)" "به برنامه امکان می‌دهد به اطلاعات حسگرهایی که بر شرایط فیزیکی شما مانند ضربان قلبتان، نظارت دارند، دسترسی داشته باشد." "خواندن رویدادهای تقویم به همراه اطلاعات محرمانه" "به برنامه امکان می‌دهد همه رویدادهای تقویم ذخیره شده در رایانهٔ لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد داده‌های تقویم شما را صرفنظر از محرمانه یا حساس بودن آن‌ها به اشتراک گذاشته یا ذخیره کند." @@ -336,15 +336,15 @@ "به برنامه اجازه می‌دهد رویدادهایی را که می‌توانید در تلفن خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیام‌هایی را که به نظر می‌رسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند." "دسترسی به فرمان‌های بیشتر ارائه دهنده مکان" "‏به برنامه اجازه می‌دهد به دستورات ارائه‌دهنده مکان تکمیلی دسترسی داشته باشد. این کار ممکن است به برنامه امکان دهد با کارکرد GPS یا منابع دیگر مکان تداخل داشته باشد." - "‏موقعیت مکانی دقیق (مبتنی بر GPS و شبکه)" + "‏دسترسی به مکان دقیق (مبتنی بر GPS و شبکه)" "‏به برنامه اجازه می‌دهد که موقعیت مکانی دقیق شما را با استفاده از سیستم موقعیت‌یاب جهانی (GPS) یا منابع موقعیت مکانی شبکه‌ای مانند برج‌های سلولی یا Wi-Fi دریافت کند. این سرویس‌های موقعیت مکانی باید در دستگاه شما برای برنامه‌ای که از آنها استفاده می‌کند، فعال و در دسترس باشد. برنامه‌ها ممکن است از آن برای تعیین جایی که هستید، استفاده کنند و ممکن است نیروی باتری بیشتری مصرف کنند." - "موقعیت مکانی تقریبی (مبتنی بر شبکه)" + "دسترسی به مکان تقریبی (مبتنی بر شبکه)" "‏به برنامه اجازه می‌دهد که موقعیت مکانی تقریبی شما را بدست آورد. این موقعیت مکانی از سرویس‌های موقعیت مکانی که از منابع موقعیت مکانی شبکه‌ای مانند برج‌های سلولی و Wi-Fi استفاده می‌کنند، بدست می‌آید. این سرویس‌های موقعیت مکانی باید در دستگاه شما برای برنامه‌ای که از آنها استفاده می‌کند، فعال و در دسترس باشد. برنامه‌ها ممکن است از آن برای تعیین تقریبی جایی که هستید، استفاده کنند." "تغییر تنظیمات صوتی" "به برنامه امکان می‌دهد تنظیمات صوتی کلی مانند میزان صدا و بلندگوی مورد استفاده برای پخش صدا را اصلاح کند." "ضبط صدا" "به برنامه اجازه می‌دهد صدا را با میکروفن ضبط کند. این مجوز به برنامه اجازه می‌دهد صدا را در هر زمان که بخواهید بدون تأیید شما ضبط کند." - "ارتباطات سیم کارت" + "ارسال فرمان به سیم کارت" "به برنامه اجازه ارسال دستورات به سیم کارت را می‌دهد. این بسیار خطرناک است." "عکسبرداری و فیلمبرداری" "به برنامه اجازه می‌دهد با دوربین به عکسبرداری و فیلمبرداری بپردازد. این مجوز به برنامه اجازه می‌‌دهد از دوربین در هر زمانی بدون تأیید شما استفاده کند." @@ -382,7 +382,7 @@ "به برنامه اجازه می‌دهد به لیست حساب‌های شناخته شده توسط تلفن دسترسی پیدا کند. این ممکن است حسا‌ب‌های ایجاد شده توسط برنامه‌هایی را که نصب کرده‌اید، شامل شود." "مشاهدهٔ اتصالات شبکه" "به برنامه امکان می‌دهد اطلاعات مربوط به اتصالات شبکه مانند شبکه‌های موجود و متصل را مشاهده کند." - "دسترسی کامل به شبکه" + "دسترسی کامل به شبکه" "به برنامه امکان می‌دهد سوکت‌های شبکه را ایجاد کند و از پروتکل‌های شبکه سفارشی استفاده نماید. مرورگر و سایر برنامه‌ها روشی را برای ارسال داده‌ها به اینترنت ارائه می‌کنند بنابراین این مجوز برای ارسال داده به اینترنت ضروری نیست." "تغییر قابلیت اتصال شبکه" "‏به برنامه اجازه می‎دهد تا وضعیت اتصال شبکه را تغییر دهد." @@ -402,7 +402,7 @@ "‏به برنامه اجازه می‎دهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاه‌های راه دور را پیدا کند و با آن‌ها مرتبط‌سازی شود." "‏اتصال و قطع اتصال از WiMAX" "به برنامه امکان می‌دهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکه‌های وایمکس متصل را مشخص کند." - "‏تغییر وضعیت WiMAX" + "‏تغییر وضعیت WiMAX" "به برنامه امکان می‌دهد رایانهٔ لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند." "‏به برنامه اجازه می‌دهد تا تلویزیون را به شبکه‌های WiMAX وصل یا ارتباط آن را با این شبکه‌ها قطع کند." "‏به برنامه امکان می‎دهد تا تلفن را به شبکه‌های وایمکس متصل کرده یا اتصال آنرا از این شبکه‌ها قطع کند." @@ -485,7 +485,7 @@ "به برنامه امکان می‌دهد پارامترهای کالیبراسیون صفحه لمسی را تغییر دهد. هرگز نباید برای برنامه‌های عادی مورد نیاز باشد." "‏دسترسی به گواهی‌های DRM" "‏به یک برنامه کاربردی اجازه ارائه مجوز و استفاده از گواهی‌های DRM را می‌دهد. هرگز برای برنامه‌های عادی مورد نیاز نیست." - "‏دریافت وضعیت انتقال پرتوی Android" + "‏دریافت وضعیت انتقال پرتوی Android" "‏به برنامه امکان می‌دهد تا اطلاعاتی درباره انتقال‌های کنونی پرتوی Android به دست آورد" "‏حذف گواهی‌های DRM" "‏به برنامه امکان می‌دهد گواهی‌های DRM را حذف کند. نباید برای برنامه‌های عادی هیچ‌وقت لازم باشد." @@ -783,7 +783,7 @@ "تنظیم یک هشدار" "‏به برنامه اجازه می‎دهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامه‎های ساعت زنگدار نمی‌‎توانند این ویژگی را اعمال کنند." "افزودن پست صوتی" - "به برنامه اجازه می‌دهد تا پیام‌ها را به صندوق دریافت پست صوتی شما اضافه کند." + "به برنامه اجازه می‌دهد تا پیام‌ها را به صندوق ورودی پست صوتی شما اضافه کند." "تغییر مجوزهای مکان جغرافیایی مرورگر" "‏به برنامه اجازه می‎دهد تا مجوزهای جغرافیایی مرورگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا اطلاعات موقعیت مکانی را به سایت‌های وب کتابخانه بفرستند." "می‌خواهید مرورگر این گذرواژه را به خاطر داشته باشد؟" @@ -1091,11 +1091,11 @@ "درحال قالب‌بندی…" "جاگذاری نشده" "فعالیتی مطابق با این مورد یافت نشد." - "تعیین مسیر خروجی رسانه" + "تعیین مسیر خروجی رسانه" "به یک برنامه اجازه می‌دهد خروجی رسانه را به دستگاه‌های خارجی دیگر تعیین مسیر کند." - "خواندن جلسات نصب" + "خواندن جلسات نصب" "به برنامه اجازه می‌دهد جلسات نصب را بخواند. این کار به برنامه اجازه می‌دهد جزئیات نصب‌های بسته فعال را ببیند." - "درخواست نصب بسته‌بندی" + "درخواست نصب بسته" "به برنامه اجازه می‌دهد درخواست نصب بسته‌بندی کند." "دوبار لمس کنید تا بزرگ‌نمایی کنترل شود" "افزودن ابزارک انجام نشد." diff --git a/core/res/res/values-fi-watch/strings.xml b/core/res/res/values-fi-watch/strings.xml index 89782a5e2acba..3c7b92572ceaf 100644 --- a/core/res/res/values-fi-watch/strings.xml +++ b/core/res/res/values-fi-watch/strings.xml @@ -21,4 +21,5 @@ "Sovellus %1$d/%2$d." + "Anturit" diff --git a/core/res/res/values-fi/cm_strings.xml b/core/res/res/values-fi/cm_strings.xml new file mode 100644 index 0000000000000..db3b930e441e1 --- /dev/null +++ b/core/res/res/values-fi/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Kuvakaappaus + + vastaanota suojattuja tekstiviestejä + + Sallii sovelluksen vastaanottaa suojattuja tekstiviestejä. + + muokkaa suojattujen tekstiviestien listaa + + Sallii sovelluksen muokata suojattujen tekstiviestien osoiteluetteloa. + + Turvallisuus + + Laitteen turvallisuuteen liittyvät oikeudet. + + lue puhelimen mustaa listaa + + Sallii sovelluksen lukea tietoja numeroista, joista saapuvat puhelut ja viestit on estetty. + + muokkaa puhelimen mustaa listaa + + Sallii sovelluksen muokata puhelinnumeroita, joista saapuvat puhelut ja viestit on estetty. + + aseta näppäinlukon taustakuva + + Sallii sovelluksen vaihtaa lukitusnäytön taustakuva. + + Käynnistä uudelleen + + Nykyinen + + + Käynnistä uudelleen + + Recovery-tila + + Bootloader-tila + + Download-tila + + Käynnistä uudelleen (soft) + + Käynnistä uudelleen + + Tabletti käynnistyy uudelleen. + Puhelin käynnistyy uudelleen. + + Käynnistetään uudelleen\u2026 + + Sovellus tapettu + + ADB verkon yli käytössä + + ADB verkon & USB:n kautta käytössä + + Paina poistaaksesi vianetsinnän käytöstä. + + ADB - %1$s + USB & verkko + USB + Verkko + + keskeytä sovelluksen käynnistys + + %s ei ole asennettu + + Prioriteetti + Ei mitään + + Wi-Fi-tukiasema poistettiin käytöstä SIMin vaihdon vuoksi + + Poista Wi-Fi käytöstä + + ota yksityisyyden suojaus käyttöön tai poista se käytöstä + Sallii sovelluksen valita, milloin muut sovellukset käyttävät yksityisyyden suojausta. Kun sovellus käyttää yksityisyyden suojausta, sillä ei ole pääsyä henkilökohtaisiin tietoihin kuten yhteystietoihin, puhelulokeihin tai viesteihin. + Yksityisyyden suojaus käytössä + Sovelluksella %1$s ei ole pääsyä henkilökohtaisiin tietoihin + Yksityisyyden suojaus + %1$s haluaa %2$s. + + Muista valinta + + käyttää kameraa + käyttää sijaintia + lukea ilmoituksiasi + aktivoida VPN-yhteyden + käynnistyä laitetta käynnistettäessä + poistaa puhelulokin + poistaa yhteystietojasi + poistaa multimediaviestejäsi + poistaa tekstiviestejäsi + piirtää ikkunan päälle + käyttää sovelluksen käyttötilastoja + pitää laitteen hereillä + soittaa puhelun + päivittää kalenteria + päivittää puhelulokia + muokata leikepöytää + päivittää yhteystietoja + päivittää järjestelmän asetuksia + mykistä/poista mykistys mikrofonista + toistaa ääntä + lähettää ilmoituksen + heijastaa mediaa + lukea kalenteria + lukea puhelulokia + lukea leikepöytää + lukea yhteystietoja + luekea multimediaviestejä + lukea tekstiviestejä + vastaanottaa tekstiviestejä + tallentaa ääntä + lähettää multimediaviestin + lähettää tekstiviestin + käynnistyä laitetta käynnistettäessä + Näytä toast-ilmoitukset + ottaa Bluetoothin käyttöön + ota mobiilidata käyttöön + ota NFC käyttöön + vaihtaa Wi-Fi-verkkoja + säätää hälytyksen äänenvoimakkuutta + säätää äänen kohdistusta + säätää Bluetoothin äänenvoimakkuutta + säätää pää-äänenvoimakkuutta + käyttää mediapainikkeita + säätää median äänenvoimakkuutta + säätää ilmoitusten äänenvoimakkuutta + säätää soittoäänen voimakkuutta + käyttää haptista palautetta + säätää puhelun äänenvoimakkuutta + kirjoittaa multimediaviestin + kirjoittaa tekstiviestin + käyttää sormenjälkeä + lisätä vastaajaviestin + lukea puhelimen tilan + hakea Wi-Fi-verkkoja + vaihtaa taustakuvan + käyttää apurakennetta + ottaa kuvankaappauksen + käyttää kehon antureita + lukea hätätilalähetyksiä + väärentää sijaintisi + lukea ulkoista tallennustilaa + kirjoittaa ulkoiseen tallennustilaan + kytkeä näytön päälle + lukea laitteen tilejä + vaihtaa Wi-Fi:n tilaa + pääkäyttäjän oikeudet + + Irrottaaksesi tämän näytön, paina ja pidä Takasin-näppäintä pohjassa. + + Ei kytkettyä laitetta + %1$s yhdistetty laite + %1$s yhdistettyä laitetta + + + + Toiminnan käynnistäminen estetty + %1$s on suojattu sovellus. Napauta todentaaksesi ja käynnistääksesi sovelluksen. + + Akku täynnä + Irrota laite laturista pidentääksesi akun käyttöikää. + + nollaa akun tilastot + + Sallii sovelluksen nollata nykyiset alemman tason akun käytön tilastot. + + SIM-kortit ovat muuttuneet + Napauta asettaaksesi SIM-kortin oletusasetukset + diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 5e1ecbefec64e..8855ee29bcf23 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -254,7 +254,7 @@ "Sisältää henkilökohtaisia tietoja, kuten luottokortin numeroita ja salasanoja." "poista tilapalkki käytöstä tai muokkaa tilapalkkia" "Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita." - "tilapalkki" + "sijaita tilapalkissa" "Antaa sovelluksen sijaita tilapalkissa." "laajentaa/tiivistää tilarivin" "Antaa sovelluksen laajentaa tai tiivistää tilarivin." @@ -282,7 +282,7 @@ "Antaa sovelluksen vastaanottaa ja käsitellä WAP-viestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle." "käynnissä olevien sovellusten noutaminen" "Antaa sovelluksen noutaa tietoja käynnissä olevista ja äskettäin suoritetuista tehtävistä. Sovellus voi saada tietoja laitteella käytetyistä sovelluksista." - "Hallinnoi laitteen ja profiilien omistajia" + "hallinnoida laitteen ja profiilien omistajia" "Sallii sovelluksien määrittää laitteen ja profiilien omistajat." "käynnissä olevien sovellusten järjesteleminen" "Antaa sovelluksen siirtää tehtäviä etualalle ja taustalle. Sovellus ei tarvitse toimiin käyttäjän lupaa." @@ -324,7 +324,7 @@ "Antaa sovelluksen muokata tablet-laitteesi puhelulokia, kuten tietoja vastatuista ja soitetuista puheluista. Haitalliset sovellukset voivat poistaa puhelulokisi tai muokata sitä." "Antaa sovelluksen muokata television puhelulokia, kuten tietoja vastatuista ja soitetuista puheluista. Haitalliset sovellukset voivat poistaa puhelulokisi tai muokata sitä." "Antaa sovelluksen muokata puhelimesi puhelulokia, kuten tietoja vastatuista ja soitetuista puheluista. Haitalliset sovellukset voivat poistaa puhelulokisi tai muokata sitä." - "kehon anturit (kuten sykemittarit)" + "käyttää kehon antureita (kuten sykemittareita)" "Antaa sovelluksen käyttää kehosi tilaa seuraavien anturien tietoja, esimerkiksi sykettä." "lue kalenteritapahtumia ja luottamuksellisia tietoja" "Antaa sovelluksen lukea tablet-laitteelle tallennettuja kalenteritapahtumia, myös kavereiden tai työkavereiden tapahtumia. Sovellus voi jakaa tai tallentaa kalenteritietojasi niiden arkaluonteisuudesta huolimatta." @@ -336,15 +336,15 @@ "Antaa sovelluksen lisätä, poistaa ja muuttaa tapahtumia, joita voit muokata puhelimellasi. Näihin kuuluvat myös kavereidesi tai työkavereidesi tapahtumat. Sovellus voi lähettää viestejä, jotka vaikuttavat kalenterin omistajien lähettämiltä, tai muokata tapahtumia ilman niiden omistajien lupaa." "käytä lisää sijainnintarjoajakomentoja" "Antaa sovelluksen käyttää ylimääräisiä sijaintipalvelukomentoja. Sovellus saattaa tällöin häiritä GPS:n tai muiden sijaintilähteiden toimintaa." - "tarkka sijainti (GPS- ja verkkopohjainen)" + "käyttää tarkkaa sijaintia (GPS- ja verkkopohjainen)" "Antaa sovelluksen käyttää tarkkaa sijaintiasi, joka määritetään GPS:n tai verkon sijaintilähteiden kuten radiomastojen ja Wi-Fi-verkkojen avulla. Sijaintipalveluiden täytyy olla käytössä ja laitteesi saatavilla, jotta sovellus voi käyttää niitä. Sovellus voi määrittää tämän luvan avulla sijaintisi ja lisätä akun käyttöä." - "likimääräinen sijainti (verkkopohjainen)" + "käyttää likimääräistä sijaintia (verkkopohjainen)" "Antaa sovelluksen käyttää likimääräistä sijaintiasi. Sijainnin määrittävät sijaintipalvelut verkon sijaintilähteiden kuten radiomastojen ja Wi-Fi-verkkojen avulla. Sijaintipalveluiden täytyy olla käytössä ja laitteesi saatavilla, jotta sovellus voi käyttää niitä. Sovellus voi määrittää tämän luvan avulla likimääräisen sijaintisi." "muuta ääniasetuksia" "Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja käytettävää kaiutinta." "tallentaa ääntä" "Antaa sovelluksen tallentaa ääntä mikrofonin avulla. Sovellus voi tallentaa ääntä milloin tahansa pyytämättä sinulta lupaa." - "SIM-viestintä" + "lähettää komentoja SIM-kortille" "Antaa sovelluksen lähettää komentoja SIM-kortille. Tämä ei ole turvallista." "ota kuvia ja videoita" "Antaa sovelluksen ottaa kuvia ja kuvata videoita kameralla. Sovellus voi käyttää kameraa milloin tahansa ilman lupaasi." @@ -382,7 +382,7 @@ "Antaa sovelluksen tarkastella puhelimeen tallennettuja tilejä. Näihin voivat kuulua myös asentamiesi sovelluksien luomat tilit." "tarkastele verkkoyhteyksiä" "Antaa sovelluksen tarkastella verkkoyhteyksiä koskevia tietoja, kuten mitä verkkoja on olemassa ja mihin on muodostettu yhteys." - "internetin käyttäminen" + "saada täydet verkon käyttöoikeudet" "Antaa sovelluksen luoda verkkovastakkeita ja käyttää muokattuja verkkoprotokollia. Tietoja voidaan lähettää verkkoon selaimen ja muiden sovellusten avulla, joten tätä lupaa ei tarvita tietojen lähettämiseksi." "muuta verkkoyhteyksiä" "Antaa sovelluksen muuttaa verkkoyhteyden tilaa." @@ -402,7 +402,7 @@ "Antaa sovelluksen määrittää paikallisen Bluetooth-puhelimen asetukset sekä tunnistaa muita laitteita ja muodostaa niiden kanssa laitepareja." "muodosta yhteys WiMAXiin ja katkaise yhteys" "Antaa sovelluksen määrittää, onko WiMAX käytössä, sekä saada selville tietoja WiMAX-verkoista, joihin on muodostettu yhteys." - "Vaihda WiMAX-verkon tilaa" + "vaihda WiMAX-verkon tilaa" "Antaa sovelluksen muodostaa tablet-laitteella yhteyden WiMAX-verkkoon ja katkaista yhteyden." "Antaa sovelluksen muodostaa ja katkaista yhteyden television ja WiMAX-verkkojen välillä." "Antaa sovelluksen muodostaa puhelimella yhteyden WiMAX-verkkoon ja katkaista yhteyden." @@ -485,7 +485,7 @@ "Antaa sovelluksen muokata kosketusnäytön kalibrointiparametreja. Ei tavallisten sovellusten käyttöön." "DRM-varmenteiden käyttö" "Antaa sovelluksen käyttää DRM-varmenteita ja hallita niiden käyttäjiä. Ei tavallisten sovellusten käyttöön." - "Vastaanota Android Beam -siirron tilatietoja" + "vastaanottaa Android Beam -siirron tilatietoja" "Antaa sovelluksen vastaanottaa tietoja nykyisistä Android Beam -siirroista" "DRM-varmenteiden poistaminen" "Antaa sovelluksen poistaa DRM-varmenteita. Ei tavallisten sovellusten käyttöön." @@ -1091,11 +1091,11 @@ "Alustetaan…" "Ei liitetty" "Osuvia toimintoja ei löytynyt." - "Median reititys" + "reitittää mediaa" "Antaa sovelluksen reitittää mediaa muihin ulkoisiin laitteisiin." - "Lue asennusistuntoja" + "lukea asennusistuntoja" "Sallii sovelluksen lukea asennusistuntoja. Toiminto sallii sovelluksen lukea aktiivisten asennuspakettien tietoja." - "Pyydä pakettien asennusta" + "pyytää asennuspaketteja" "Antaa sovelluksen pyytää pakettien asennusta." "Ohjaa zoomausta napauttamalla kahdesti" "Widgetin lisääminen epäonnistui." diff --git a/core/res/res/values-fil-rPH/cm_strings.xml b/core/res/res/values-fil-rPH/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-fil-rPH/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-fr-rCA-watch/strings.xml b/core/res/res/values-fr-rCA-watch/strings.xml index ea9c1c27a8a96..6115a59158912 100644 --- a/core/res/res/values-fr-rCA-watch/strings.xml +++ b/core/res/res/values-fr-rCA-watch/strings.xml @@ -21,4 +21,5 @@ "Appli %1$d de %2$d." + "Capteurs" diff --git a/core/res/res/values-fr-rCA/cm_strings.xml b/core/res/res/values-fr-rCA/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-fr-rCA/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 461ad1e2462d3..63c546b14d148 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -254,7 +254,7 @@ "Inclut des données personnelles telles que les numéros de cartes de paiement et les mots de passe." "désactiver ou modifier la barre d\'état" "Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système." - "barre d\'état" + "servir de barre d\'état" "Permet à l\'application de faire office de barre d\'état." "agrandir ou réduire la barre d\'état" "Permet à l\'application de réduire ou de développer la barre d\'état." @@ -282,7 +282,7 @@ "Permet à l\'application de recevoir et de traiter les messages WAP. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer." "récupérer les données des applications en cours d\'exécution" "Permet à l\'application de récupérer des données sur des tâches en cours d\'exécution et récemment exécutées. L\'application est ainsi susceptible d\'obtenir des données concernant les applications utilisées sur l\'appareil." - "Gérer les propriétaires des profils et de l\'appareil" + "gérer les propriétaires des profils et de l\'appareil" "Autoriser les applications à définir les propriétaires des profils et celui de l\'appareil" "réorganiser les applications en cours d\'exécution" "Permet à l\'application de déplacer les tâches au premier plan et en arrière-plan. L\'application peut procéder à ces opérations sans votre intervention." @@ -324,7 +324,7 @@ "Permet à l\'application de lire le journal d\'appels de votre tablette, y compris les données relatives aux appels entrants et sortants. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier votre journal d\'appels." "Permet à l\'application de modifier le journal d\'appels de votre téléviseur, y compris les données sur les appels entrants et sortants. Des applications malveillantes pourraient utiliser cette fonctionnalité pour effacer ou modifier votre journal d\'appels." "Permet à l\'application de lire le journal d\'appels de votre téléphone, y compris les données relatives aux appels entrants et sortants. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier votre journal d\'appels." - "capteurs corporels (tels que les moniteurs de fréquence cardiaque)" + "accéder aux capteurs corporels (comme les moniteurs de fréquence cardiaque)" "Permet à l\'application d\'accéder aux données des capteurs qui surveillent votre condition physique, comme votre rythme cardiaque." "consulter les événements d\'agenda ainsi que les données confidentielles qu\'ils contiennent" "Permet à l\'application de lire tous les événements d\'agenda stockés sur votre tablette, y compris ceux de vos amis ou de vos collègues. Cette autorisation peut lui permettre de partager ou d\'enregistrer vos données d\'agenda, indépendamment de leur caractère confidentiel ou sensible." @@ -336,15 +336,15 @@ "Permet à l\'application d\'ajouter, de supprimer et d\'apporter des modifications aux événements modifiables sur votre téléphone, y compris ceux de vos amis ou de vos collègues. Cette autorisation peut lui permettre d\'envoyer des messages qui semblent provenir de propriétaires de l\'agenda ou de modifier les événements à l\'insu des propriétaires." "accéder aux commandes de fournisseur de position géographique supplémentaires" "Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation." - "position précise (GPS et réseau)" + "accéder à votre position précise (GPS et réseau)" "Permet à l\'application d\'obtenir votre position exacte à l\'aide du récepteur satellite GPS ou des sources de localisation de réseau tels que les points d\'accès Wi-Fi et les antennes-relais. Ces services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puissent déterminer où vous vous trouvez, le cas échéant. Cette autorisation peut entraîner une utilisation accrue de la batterie." - "connaître votre position approximative (réseau)" + "accéder à votre position approximative (réseau)" "Permet à l\'application d\'obtenir votre position approximative. Celle-ci est fournie par des services de localisation sur la base des sources de localisation de réseau tels que les points d\'accès Wi-Fi et les antennes-relais. Ces services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puisse déterminer où vous vous trouvez de façon approximative, le cas échéant." "modifier vos paramètres audio" "Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée." "enregistrer des fichiers audio" "Permet à l\'application d\'enregistrer des contenus audio à l\'aide du microphone. Cette autorisation lui donne la possibilité d\'enregistrer du contenu audio à tout moment sans votre consentement." - "Communication avec la carte SIM" + "envoyer des commandes à la carte SIM" "Permet à l\'application d\'envoyer des commandes à la carte SIM. Cette fonctionnalité est très dangereuse." "prendre des photos et filmer des vidéos" "Permet à l\'application de prendre des photos et de filmer des vidéos avec l\'appareil photo. Cette autorisation lui permet d\'utiliser l\'appareil photo à tout moment sans votre consentement." @@ -382,7 +382,7 @@ "Permet à l\'application d\'obtenir la liste des comptes connus par le téléphone. Il peut s\'agir de n\'importe quel compte créé par les applications que vous avez installées." "afficher les connexions réseau" "Permet à l\'application d\'accéder à des détails concernant les connexions réseau, comme les réseaux existants et connectés." - "bénéficier d\'un accès complet au réseau" + "bénéficier d\'un accès complet au réseau" "Permet à l\'application de créer des interfaces de connexion réseau et d\'utiliser des protocoles réseau personnalisés. Le navigateur et d\'autres applications permettent d\'envoyer des données sur Internet. Cette autorisation n\'est donc pas nécessaire pour envoyer des données sur Internet." "modifier la connectivité réseau" "Permet à l\'application de modifier l\'état de la connectivité réseau." @@ -402,7 +402,7 @@ "Permet à l\'application de configurer le téléphone Bluetooth local, d\'identifier des appareils distants et de les associer au téléphone." "se connecter au réseau WiMAX et s\'en déconnecter" "Permet à l\'application de déterminer si le WiMAX est activé et d\'obtenir des détails sur tous les réseaux WiMAX connectés." - "Modifier l\'état du WiMAX" + "modifier l\'état du WiMAX" "Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter." "Permet à l\'application de se connecter au téléviseur et de le déconnecter de réseaux WiMAX." "Permet à l\'application de connecter le téléphone aux réseaux WiMAX et de l\'en déconnecter." @@ -485,7 +485,7 @@ "Permet à l\'application de modifier les paramètres de calibrage de l\'écran tactile. Ne devrait jamais être nécessaire pour les applications standards." "accéder aux certificats GDN" "Permet à une application de fournir et d\'utiliser les certificats de GDN. Cela ne devrait jamais être nécessaire pour les applications normales." - "Recevoir des données sur l\'état du transfert Android Beam" + "recevoir des données sur l\'état du transfert Android Beam" "Autoriser cette application à recevoir des données sur les transferts Android Beam en cours" "supprimer des certificats GDN" "Permet à une application de supprimer les certificats GDN. Cela ne devrait jamais être nécessaire pour des applications normales." @@ -1091,11 +1091,11 @@ "Formatage en cours..." "Non insérée" "Aucune activité correspondante trouvée." - "Diriger la sortie multimédia" + "diriger la sortie multimédia" "Permet à une application de diriger la sortie multimédia vers d\'autres appareils externes." - "Accéder aux sessions d\'installation" + "accéder aux sessions d\'installation" "Permet à une application d\'accéder aux sessions d\'installation. Cela lui permet de consulter les détails relatifs à l\'installation des paquets actifs." - "Demander l\'installation de paquets" + "demander l\'installation de paquets" "Permet à une application de demander l\'installation de paquets." "Appuyer deux fois pour régler le zoom" "Impossible d\'ajouter le widget." diff --git a/core/res/res/values-fr-watch/strings.xml b/core/res/res/values-fr-watch/strings.xml index 7e616cd061bd4..aab65c0187187 100644 --- a/core/res/res/values-fr-watch/strings.xml +++ b/core/res/res/values-fr-watch/strings.xml @@ -21,4 +21,5 @@ "Appli %1$d sur %2$d" + "Capteurs" diff --git a/core/res/res/values-fr/cm_strings.xml b/core/res/res/values-fr/cm_strings.xml new file mode 100644 index 0000000000000..a4be3cff3f1f5 --- /dev/null +++ b/core/res/res/values-fr/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Capture d\'écran + + recevoir des SMS protégés + + Permet à l\'application de recevoir un SMS protégé. + + modifier la liste des SMS protégés + + Permet à l\'application de modifier la liste des adresses des SMS protégés. + + Sécurité + + Autorisations relatives aux informations de sécurité de l\'appareil. + + lire la liste noire du téléphone + + Permet à l\'application de lire les informations sur les numéros de téléphone qui sont bloqués pour les appels ou les messages entrants. + + modifier la liste noire du téléphone + + Permet à l\'application de modifier les numéros de téléphone qui sont bloqués pour les appels ou les messages entrants. + + Définir le fond d\'écran de verrouillage + + Permet à l\'application de changer le fond de l\'écran de verrouillage. + + Redémarrer + + Actuel + + + Redémarrer + + Récupération + + Bootloader + + Download + + Redémarrage logiciel + + Redémarrer + + Votre tablette va redémarrer + Votre téléphone va redémarrer + + Redémarrage en cours\u2026 + + Application arrêtée + + ADB sur réseau activé + + ADB sur USB et réseau activé + + Appuyez pour désactiver le débogage. + + ADB - %1$s + USB et réseau + USB + Réseau + + intercepter le lancement d\'application + + %s n\'est pas installé + + Priorité + Aucun + + Point d\'accès Wi-Fi désactivé en raison d\'un changement d\'abonnement SIM + + Désactiver le Wi-Fi + + activer ou désactiver la protection des données + Permet à l\'application d\'en exécuter une autre avec la protection des données. Lorsqu\'une application est exécutée avec la protection des données, elle n\'aura pas accès aux données personnelles telles que les contacts, les journaux d\'appels ou les messages. + Protection des données activée + %1$s ne sera pas en mesure d\'accéder aux données personnelles + Protection des données + %1$s voudrait %2$s. + + Se souvenir de mon choix + + accéder à l\'appareil photo + accéder à votre position + lire vos notifications + activer un VPN + démarrer avec le système + supprimer votre journal d\'appels + supprimer vos contacts + supprimer vos messages MMS + supprimer vos messages SMS + déplacer au dessus + obtenir les statistiques d\'utilisation de l\'application + garder votre appareil allumé + passer un appel téléphonique + mettre à jour votre agenda + mettre à jour le journal d\'appels + modifier le presse-papiers + mettre à jour vos contacts + mettre à jour les paramètres du système + activer/désactiver le microphone + lecture audio + afficher une notification + projeter média + lire votre agenda + lire le journal d\'appels + lire le presse-papiers + lire vos contacts + lire vos messages MMS + lire vos messages SMS + recevoir un SMS + enregistrer un son + envoyer un MMS + envoyer un SMS + démarrer avec le système + afficher les messages toast + activer/désactiver le Bluetooth + activer/désactiver les données mobiles + activer/désactiver le NFC + activer/désactiver le Wi-Fi + contrôler le volume des alarmes + contrôler le focus audio + contrôler le volume du Bluetooth + contrôler le volume principal + utiliser les boutons de médias + contrôler le volume des médias + contrôler le volume des notifications + contrôler le volume de la sonnerie + utiliser le retour haptique + contrôler le volume d\'appels + écrire un MMS + écrire un SMS + utiliser les empreintes digitales + ajouter un message vocal + accéder à l\'état du téléphone + rechercher les réseaux Wi-Fi + changer le fond d\'écran + utiliser l\'aide à la structure + prendre une capture d\'écran + utiliser les capteurs corporels + lire les diffusions cellulaires + simuler votre position + lire le stockage externe + écrire sur le stockage externe + allumer l\'écran + obtenir les comptes de l\'appareil + changer l\'état du Wi-Fi + obtenir l\'accès root + + Pour déverrouiller l\'écran, appuyez et maintenez le bouton Retour. + + Aucun appareil connecté + %1$s appareil connecté + %1$s appareils connectés + + + + Lancement d\'activité bloqué + %1$s est protégé contre tout lancement. Toucher pour s\'authentifier et lancer l\'application. + + Batterie entièrement chargée + Débranchez votre chargeur afin d\'améliorer la durée de vie de la batterie. + + réinitialiser les statistiques de la batterie + + Permet à une application de réinitialiser les données actuelles d\'utilisation de la batterie à faible niveau. + + Les cartes SIM ont été modifiées + Appuyer pour définir les préférences par défaut de la carte SIM + diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index ff3e6f77fe20d..d54556c6524e8 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -254,7 +254,7 @@ "Inclut des données personnelles telles que les numéros de cartes de paiement et les mots de passe." "Désactivation ou modification de la barre d\'état" "Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système." - "barre d\'état" + "remplacer la barre d\'état" "Permet à l\'application de faire office de barre d\'état." "Agrandir/réduire la barre d\'état" "Permet à l\'application de réduire ou de développer la barre d\'état." @@ -282,7 +282,7 @@ "Permet à l\'application de recevoir et de traiter les messages WAP. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer." "récupérer les applications en cours d\'exécution" "Permet à l\'application de récupérer des informations sur des tâches en cours d\'exécution et récemment exécutées. L\'application est ainsi susceptible d\'obtenir des informations sur les applications utilisées sur l\'appareil." - "Gérer les propriétaires des profils et de l\'appareil" + "gérer les propriétaires des profils et de l\'appareil" "Autoriser les applications à définir les propriétaires des profils et celui de l\'appareil" "réorganiser les applications en cours d\'exécution" "Permet à l\'application de déplacer les tâches au premier plan et en arrière-plan. L\'application peut procéder à ces opérations sans votre intervention." @@ -324,7 +324,7 @@ "Permet à l\'application de lire le journal d\'appels de votre tablette, y compris les données relatives aux appels entrants et sortants. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier votre journal d\'appels." "Permet à l\'application de lire le journal d\'appels du téléviseur, y compris les données relatives aux appels entrants et sortants. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier votre journal d\'appels." "Permet à l\'application de lire le journal d\'appels de votre téléphone, y compris les données relatives aux appels entrants et sortants. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier votre journal d\'appels." - "capteurs corporels (tels que les cardiofréquencemètres)" + "accéder capteurs corp. (ex : cardiofréquencemètres)" "Permet à l\'application d\'accéder aux données des capteurs qui contrôlent votre condition physique, comme votre rythme cardiaque." "consulter les événements d\'agenda ainsi que les informations confidentielles" "Permet à l\'application de lire tous les événements d\'agenda stockés sur votre tablette, y compris ceux de vos amis ou de vos collègues. Cette autorisation peut lui permettre de partager ou d\'enregistrer vos données d\'agenda, indépendamment de leur caractère confidentiel ou sensible." @@ -336,15 +336,15 @@ "Permet à l\'application d\'ajouter, de supprimer et d\'apporter des modifications aux événements modifiables sur votre téléphone, y compris ceux de vos amis ou de vos collègues. Cette autorisation peut lui permettre d\'envoyer des messages qui semblent provenir de propriétaires de l\'agenda ou de modifier les événements à l\'insu des propriétaires." "Accès aux commandes de fournisseur de position géographique supplémentaires" "Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation." - "connaître votre position précise (GPS et réseau)" + "accéder à votre position précise (GPS et réseau)" "Permet à l\'application d\'obtenir votre position exacte à l\'aide du récepteur satellite GPS ou des sources de localisation de réseau tels que les points d\'accès Wi-Fi et les antennes-relais. Ces services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puisse déterminer où vous vous trouvez, le cas échéant. Cette autorisation peut entraîner une utilisation accrue de la batterie." - "connaître votre position approximative (réseau)" + "accéder à votre position approximative (selon le réseau)" "Permet à l\'application d\'obtenir votre position approximative. Celle-ci est fournie par des services de localisation sur la base des sources de localisation de réseau tels que les points d\'accès Wi-Fi et les antennes-relais. Ces services de localisation doivent être activés et disponibles sur votre appareil pour que l\'application puisse déterminer où vous vous trouvez de façon approximative, le cas échéant." "modifier vos paramètres audio" "Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée." "enregistrer des fichiers audio" "Permet à l\'application d\'enregistrer des contenus audio à l\'aide du microphone. Cette autorisation lui donne la possibilité d\'enregistrer du contenu audio à tout moment sans votre consentement." - "Communication avec la carte SIM" + "envoyer des commandes à la carte SIM" "Autoriser l\'envoi de commandes à la carte SIM via l\'application. Cette fonctionnalité est très risquée." "prendre des photos et enregistrer des vidéos" "Permet à l\'application de prendre des photos et de filmer des vidéos avec l\'appareil photo. Cette autorisation lui permet d\'utiliser l\'appareil photo à tout moment sans votre consentement." @@ -382,7 +382,7 @@ "Permet à l\'application d\'obtenir la liste des comptes connus par le téléphone. Il peut s\'agir de n\'importe quel compte créé par les applications que vous avez installées." "afficher les connexions réseau" "Permet à l\'application d\'accéder à des informations sur les connexions réseau, comme les réseaux existants et connectés." - "bénéficier d\'un accès complet au réseau" + "bénéficier d\'un accès complet au réseau" "Permet à l\'application de créer des sockets réseau et d\'utiliser des protocoles réseau personnalisés. Le navigateur et d\'autres applications permettent d\'envoyer des données sur Internet. Cette autorisation n\'est donc pas nécessaire pour envoyer des données sur Internet." "modifier la connectivité réseau" "Permet à l\'application de modifier l\'état de la connectivité du réseau." @@ -402,7 +402,7 @@ "Permet à l\'application de configurer le téléphone Bluetooth local, d\'identifier des appareils distants et de les associer au téléphone." "se connecter au réseau WiMAX et s\'en déconnecter" "Permet à l\'application de déterminer si le WiMAX est activé et d\'obtenir des informations sur tous les réseaux WiMAX connectés." - "Modifier l\'état du WiMAX" + "modifier l\'état du WiMAX" "Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter." "Permet à l\'application de connecter le téléviseur et de le déconnecter des réseaux WiMAX." "Permet à l\'application de connecter le téléphone aux réseaux WiMAX et de l\'en déconnecter." @@ -420,7 +420,7 @@ "Autoriser l\'application à utiliser le matériel d\'empreintes digitales pour l\'authentification" "Empreinte numérique partiellement détectée. Veuillez réessayer." "Impossible de reconnaître l\'empreinte numérique. Veuillez réessayer." - "Le capteur d\'empreintes numériques est sale. Veuillez le nettoyer, puis réessayer." + "Le lecteur d\'empreintes numériques est sale. Veuillez le nettoyer, puis réessayer." "Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer." "Vous avez déplacé votre doigt trop lentement. Veuillez réessayer." @@ -485,7 +485,7 @@ "Permettre à l\'application de modifier les paramètres de calibrage de l\'écran tactile. Ne devrait jamais être nécessaire pour les applications standards." "accéder aux certificats de GDN" "Permettre à une application de fournir et d\'utiliser des certificats de GDN. Ne devrait jamais être nécessaire pour les applications standards." - "Recevoir des informations sur l\'état du transfert Android Beam" + "recevoir des informations sur l\'état du transfert Android Beam" "Autoriser cette application à recevoir des informations sur les transferts Android Beam en cours" "supprimer les certificats de GDN" "Permet à une application de supprimer les certificats de GDN. Ne devrait jamais être nécessaire pour les applications standards." @@ -1091,11 +1091,11 @@ "Formatage en cours…" "Non inséré" "Aucune activité correspondante trouvée." - "Diriger la sortie multimédia" + "diriger la sortie multimédia" "Permet à une application de diriger la sortie multimédia vers d\'autres appareils externes." - "Accéder aux sessions d\'installation" + "accéder aux sessions d\'installation" "Permet à une application d\'accéder aux sessions d\'installation. Cela lui permet de consulter les détails relatifs à l\'installation des packages actifs." - "Demander l\'installation de packages" + "demander l\'installation de packages" "Permet à une application de demander l\'installation de packages." "Appuyez deux fois pour régler le zoom." "Impossible d\'ajouter le widget." diff --git a/core/res/res/values-frp-rIT/cm_strings.xml b/core/res/res/values-frp-rIT/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-frp-rIT/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-frp-rIT/strings.xml b/core/res/res/values-frp-rIT/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-frp-rIT/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-fy-rNL/cm_strings.xml b/core/res/res/values-fy-rNL/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-fy-rNL/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-fy-rNL/strings.xml b/core/res/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-fy-rNL/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ga-rIE/cm_strings.xml b/core/res/res/values-ga-rIE/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-ga-rIE/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ga-rIE/strings.xml b/core/res/res/values-ga-rIE/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-ga-rIE/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-gd-rGB/cm_strings.xml b/core/res/res/values-gd-rGB/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-gd-rGB/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-gd-rGB/strings.xml b/core/res/res/values-gd-rGB/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-gd-rGB/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-gl-rES-watch/strings.xml b/core/res/res/values-gl-rES-watch/strings.xml index d9ea0fe252a20..5e52823477cac 100644 --- a/core/res/res/values-gl-rES-watch/strings.xml +++ b/core/res/res/values-gl-rES-watch/strings.xml @@ -21,4 +21,5 @@ "Aplicación %1$d de %2$d." + "Sensores" diff --git a/core/res/res/values-gl-rES/cm_strings.xml b/core/res/res/values-gl-rES/cm_strings.xml new file mode 100644 index 0000000000000..1f043207afba3 --- /dev/null +++ b/core/res/res/values-gl-rES/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Captura de pantalla + + recibir SMS protexidas + + Permitir que a aplicación reciba unha SMS protexida. + + modificar a lista de SMS protexidas + + Permitir que a aplicación modifique a lista de enderezos de SMS protexidas. + + Seguridade + + Permisos relacionados coa información de seguridade do dispositivo. + + ler a lista de bloqueo do teléfono + + Permítelle a unha aplicación ler a información sobre os números de teléfono que están bloqueados, dos que non se recibirán nin chamadas nin mensaxes. + + cambiar a lista de bloqueo do teléfono + + Permítelle a unha aplicación cambiar os números de teléfono que están bloqueados, dos que nin se recibirán chamadas nin mensaxes. + + estabelecer fondo de pantalla de bloqueo + + Permitir que unha aplicación cambie o fondo da pantalla de bloqueo. + + Reiniciar + + Actual + + + Reiniciar + + Recuperar + + Xestor de arranque + + Descargar + + Reinicio do sistema + + Reiniciar + + Vaise reiniciar a súa tableta. + Vaise reiniciar o seu teléfono. + + Reiniciando\u2026 + + Aplicación terminada + + Activouse a rede en ADB + + Activada a ADB en USB e rede + + Toque para desactivar a depuración. + + ADB - %1$s + USB e rede + USB + Rede + + Interromper o inicio de aplicacións + + %s non está instalada + + Prioridade + Ningún + + Hotspot Wi-Fi desactivado debido ao cambio da subscrición da SIM + + Apagar o Wi-Fi + + activar ou desactivar a Protección da privacidade + Permítelle á aplicación decidir sobre se outra aplicación debe executarse ou non con Protección da privacidade. De unha aplicación estarse a executar con Protección da privacidade, non poderá acceder a contactos, rexistros de chamadas nin mensaxes. + Protección da privacidade activada + %1$s non poderá acceder aos datos persoais + Protección da privacidade + %1$s quere %2$s. + + Lembrar a miña escolla + + Acceder á cámara + Acceder á súa localización + Ler as súas notificacións + Activar unha VPN + Iniciar ao arrancar + Borrar o seu rexistro de chamadas + Borrar os seus contactos + Borrar as súas mensaxes MMS + Borrar as súas mensaxes SMS + amosar enriba + obter estatísticas sobre o uso da aplicación + manter o seu dispositivo esperto + realizar unha chamada de teléfono + actualizar o seu calendario + actualizar o rexistro de chamadas + modificar o seu portapapeis + actualizar os seus contactos + actualizar a configuración do sistema + activar/desactivar o micrófono + reproducir son + enviar unha notificación + visualizar recursos multimedia + ler o seu calendario + ler o rexistro de chamadas + ler o portapapeis + ler os seus contactos + ler as súas mensaxes MMS + ler as súas mensaxes SMS + recibir unha mensaxe SMS + gravar son + enviar unha mensaxe MMS + enviar unha mensaxe SMS + iniciar ao arrancar + amosar notificacións emerxentes + trocar o Bluetooth + mudar os datos móbeis + trocar o NFC + trocar o Wi-Fi + controlar o volume da alarma + controlar o foco de son + controlar o volume do Bluetooth + controlar o volume global + empregar os botóns de multimedia + controlar o volume de multimedia + controlar o volume das notificacións + controlar o volume do ton de chamada + utilizar a resposta háptica + controlar o volume das chamadas de voz + escribir unha mensaxe MMS + escribir unha mensaxe SMS + empregar pegada dixital + engadir ó correo de voz + acceder ao estado do móbil + buscar redes Wi-Fi + mudar o fondo de pantalla + usar a estrutura de asistencia + realizar captura de pantalla + usar os sensores do corpo + ler as transmisións de celulares + simular a miña localización + ler do almacenamento externo + escribir no almacenamento externo + acender a pantalla + obter as contas do dispositivo + mudar o estado da Wi-Fi + Obter acceso como superusuario + + Para deixar de fixar esta pantalla, mantén tocado o botón Atrás. + + Dispositivo non conectado + Dispositivo %1$s conectado + Dispositivos %1$s conectados + + + + Inicio da actividade bloqueado + %1$s esta protexido de ser lanzado.Toque para auntentificar e iniciar o aplicativo. + + Batería cargada + Desconecta o teu dispositivo do cargador para mellorar a lonxevidade da batería. + + reiniciar estatísticas da bateria + + Permite que un aplicativo poida reiniciar os datos de uso actual de batería a baixo nivel. + + As tarxetas SIM cambiaron + Tocar para definir as preferencias predefinidas da tarxeta SIM + diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml index 48dc96e7e01eb..39108d3b1b462 100644 --- a/core/res/res/values-gl-rES/strings.xml +++ b/core/res/res/values-gl-rES/strings.xml @@ -254,7 +254,7 @@ "Inclúe datos persoais como números e contrasinais de tarxetas de crédito." "desactivar ou modificar a barra de estado" "Permite á aplicación desactivar a barra de estado ou engadir e eliminar as iconas do sistema." - "barra de estado" + "actuar como a barra de estado" "Permite á aplicación ser a barra de estado." "ampliar/contraer a barra de estado" "Permite á aplicación ampliar ou contraer a barra de estado." @@ -282,7 +282,7 @@ "Permite á aplicación recibir e procesar mensaxes WAP. Este permiso inclúe a capacidade de supervisar ou eliminar mensaxes enviadas a ti sen mostrarchas." "recuperar aplicacións en execución" "Permite á aplicación recuperar información acerca de tarefas que se están executando actualmente ou que se executaron recentemente. É posible que esta acción permita á aplicación descubrir información acerca de que aplicacións se utilizan no dispositivo." - "Xestionar os propietarios do perfil e do dispositivo" + "xestionar propietarios do perfil e do dispositivo" "Permite ás aplicacións establecer os propietarios do perfil e o propietario do dispositivo." "reordenar as aplicacións en execución" "Permite á aplicación mover tarefas ao primeiro e segundo plano. É posible que a aplicación leve a cabo esta acción sen a túa intervención." @@ -324,7 +324,7 @@ "Permite á aplicación modificar o rexistro de chamadas do tablet, incluídos os datos acerca de chamadas entrantes e saíntes. É posible que aplicacións maliciosas utilicen esta acción para borrar ou modificar o teu rexistro de chamadas." "Permite que a aplicación modifique o rexistro de chamadas da televisión, incluídos os datos sobre chamadas entrantes e saíntes. As aplicacións maliciosas poden utilizar este permiso para borrar ou modificar o rexistro de chamadas." "Permite á aplicación modificar o rexistro de chamadas do teléfono, incluídos os datos acerca de chamadas entrantes e saíntes. É posible que aplicacións maliciosas utilicen esta acción para borrar ou modificar o teu rexistro de chamadas." - "sensores de corpo (como monitores de ritmo cardíaco)" + "acceder a sensores do corpo (como monitores de ritmo cardíaco)" "Permite que a aplicación acceda aos datos dos sensores que controlan o teu estado físico, como o ritmo cardíaco." "ler os eventos do calendario e a información confidencial" "Permite á aplicación ler todos os eventos do calendario que están almacenados no tablet, incluídos os pertencentes aos teus amigos ou compañeiros de traballo. É posible que esta acción permita á aplicación compartir ou gardar os datos do teu calendario, independentemente da confidencialidade." @@ -336,15 +336,15 @@ "Permite á aplicación engadir, eliminar e cambiar eventos que podes modificar no teu teléfono, incluídos os de amigos ou compañeiros de traballo. É posible que esta acción permita á aplicación enviar mensaxes que parecen proceder de propietarios de calendarios ou modificar eventos sen o coñecemento dos propietarios." "acceder a comandos adicionais do provedor de situación" "Permite á aplicación acceder a comandos adicionais de fornecedor de localizacións. É posible que isto provoque que a aplicación interfira co funcionamento do GPS ou doutras fontes da localización." - "localización precisa (baseada en GPS e na rede)" + "acceder á localización precisa (baseada no GPS e na rede)" "Permite á aplicación obter a túa localización precisa co sistema de posicionamento global (GPS ou Global Positioning System) ou con fontes da localización de rede como as torres de telecomunicacións e a wifi. Estes servizos de localización deben estar activados e dispoñibles para o teu dispositivo para que a aplicación poida utilizalos. As aplicacións poden usar esta opción para determinar aproximadamente o lugar en que te atopas e é posible que consuman batería adicional." - "situación aproximada (baseada na rede)" + "acceder á localización aproximada (baseada na rede)" "Permite á aplicación obter a túa localización aproximada. Esta localización provén dos servizos de localización que utilizan fontes da localización de rede como as torres de telecomunicacións e a wifi. Estes servizos de localización deben estar activados e dispoñibles para o teu dispositivo para que a aplicación poida utilizalos. As aplicacións poden esta opción para determinar aproximadamente o lugar en que te atopas." "cambiar a configuración de son" "Permite á aplicación modificar a configuración de audio global, como o volume e que altofalante se utiliza para a saída." "gravar audio" "Permite á aplicación gravar audio co micrófono. Este permiso permite á aplicación gravar audio en calquera momento sen a túa confirmación." - "comunicación SIM" + "enviar comandos á SIM" "Permite á aplicación enviar comandos á SIM. Isto é moi perigoso." "facer fotos e vídeos" "Permite á aplicación tomar imaxes e vídeos coa cámara. Con este permiso a aplicación pode utilizar a cámara en calquera momento sen a túa confirmación." @@ -382,7 +382,7 @@ "Permite á aplicación obter a lista de contas coñecidas polo teléfono. É posible que aquí se inclúan as contas creadas por aplicacións que tes instaladas." "ver conexións de rede" "Permite á aplicación ver información acerca das conexións da rede, como que redes existen e cales están conectadas." - "acceso total á rede" + "ter acceso completo á rede" "Permite á aplicación crear sockets de rede e utilizar protocolos de rede personalizados. O navegador e outras aplicacións ofrecen medios para enviar datos a Internet, polo que non se require este permiso para enviar datos a Internet." "cambiar a conectividade de rede" "Permite á aplicación cambiar o estado da conectividade de rede." @@ -402,7 +402,7 @@ "Permite á aplicación configurar o teléfono Bluetooth local e descubrir e sincronizar con dispositivos remotos." "conectar e desconectar de WiMAX" "Permite á aplicación determinar se WiMAX está activado e obter información acerca das redes WiMAX que están conectadas." - "Cambiar estado de WiMAX" + "cambiar estado de WiMAX" "Permite á aplicación conectar e desconectar o tablet de redes WiMAX." "Permite que a aplicación conecte ou desconecte a televisión de redes WiMAX." "Permite á aplicación conectar e desconectar o teléfono de redes WiMAX." @@ -485,7 +485,7 @@ "Permite á aplicación modificar os parámetros de calibración da pantalla táctil. As aplicacións normais non deberían necesitar este permiso." "acceso a certificados DRM" "Permite a unha aplicación fornecer e utilizar certificados DRM. Non se deberían precisar nunca para as aplicacións normais." - "Recibir estado das transferencias de Android Beam" + "recibir o estado das transferencias de Android Beam" "Permite a esta aplicación recibir información acerca das transferencias actuais de Android Beam" "eliminar certificados DRM" "Permite a unha aplicación eliminar os certificados DRM. As aplicacións normais non o deberían precisar nunca." @@ -1091,11 +1091,11 @@ "Formatando…" "Non se inseriu" "Non se atoparon actividades que coincidan." - "Dirixir saída multimedia" + "dirixir saída multimedia" "Permite a unha aplicación dirixir a saída multimedia a outros dispositivos externos." - "Consultar sesións de instalación" + "ler sesións de instalación" "Permite que unha aplicación consulte as sesións de instalación. Desta forma, pode ver os detalles acerca das instalacións de paquetes activas." - "Solicitar instalación dos paquetes" + "solicitar instalación de paquetes" "Permite a unha aplicación solicitar a instalación dos paquetes." "Toca dúas veces para controlar o zoom" "Non se puido engadir o widget." diff --git a/core/res/res/values-gu-rIN-watch/strings.xml b/core/res/res/values-gu-rIN-watch/strings.xml index 3e503353e83ac..6320fcc1abca3 100644 --- a/core/res/res/values-gu-rIN-watch/strings.xml +++ b/core/res/res/values-gu-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d માંથી %1$d એપ્લિકેશન." + "સેન્સર્સ" diff --git a/core/res/res/values-gu-rIN/cm_strings.xml b/core/res/res/values-gu-rIN/cm_strings.xml new file mode 100644 index 0000000000000..62072a093ec9a --- /dev/null +++ b/core/res/res/values-gu-rIN/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + સ્ક્રિનશોટ + + સુરક્ષિત SMS મેળવો + + ઍપ ને ઇનકમિંગ સુરક્ષિત SMS મેળવવાની છૂટ આપે છે. + + સુરક્ષિત SMS સૂચીમાં ફેરફાર કરો + + ઍપને સુરક્ષિત SMS સરનામાની સૂચીમાં ફેરફાર કરવાની છૂટ આપે છે. + + સુરક્ષા + + ડિવાઇસ સુરક્ષા માહિતી સાથે સંબંધિત પરવાનગીઓ. + + ફોન બ્લેકલિસ્ટ વાંચો + + ઇનકમિંગ કોલ અથવા સંદેશા માટે જે ફોન નંબરો અવરોધવામાં આવ્યા હોય તે વિશેની માહિતી વાંચવાની ઍપને છૂટ આપે છે. + + ફોન બ્લેકલિસ્ટ પરિવર્તન કરો + + ઇનકમિંગ કોલ અથવા સંદેશા માટે જે ફોન નંબરો અવરોધવામાં આવ્યા હોય તે પરિવર્તન કરવા માટે ઍપને છૂટ આપે છે. + + કિગાર્ડ વોલપેપર સેટ કરો + + લૉક સ્ક્રીન વૉલપેપરમાં પરિવર્તન કરવાની ઍપને છૂટ આપે છે. + + રીબૂટ કરો + + વર્તમાન + + + રીબૂટ કરો + + રિકવરી + + બૂટલોડર + + ડાઉનલોડ કરો + + સોફ્ટ રીબૂટ + + રીબૂટ કરો + + તમારું ટૅબ્લેટ રીબૂટ થશે. + તમારો ફોન રીબૂટ થશે. + + રીબુટ થવું\u2026 + + એપ્લિકેશન સંપૂર્ણ બંધ કરવામાં આવી + + નેટવર્ક પર ADB સક્ષમ કરવામાં આવ્યું + + USB અને નેટવર્ક પર ADB સક્ષમ કરવામાં આવ્યું + + ડીબગિંગ અક્ષમ કરવા ટચ કરો. + + ADB - %1$s + USB અને નેટવર્ક + USB + નેટવર્ક + + એપ્લિકેશન લોન્ચમાં ખલેલ પહોંચાડો + + %s ઇન્સ્ટૉલ થયું નથી + + પ્રાધાન્યતા + કોઈ નહીં + + SIM લવાજમ પરિવર્તનને કારણે Wi-Fi હોટસ્પોટ અક્ષમ કરવામાં આવ્યું + + Wi-Fi બંધ કરો + + ગુપ્તતા ગાર્ડ સક્ષમ અથવા અક્ષમ કરો + અન્ય એપ્લિકેશન ગુપ્તતા ગાર્ડ સાથે ચાલી શકે કે કેમ તેમાં એપ્લિકેશનને પરિવર્તન કરવાની છૂટ આપે છે. ગુપ્તતા ગાર્ડ સાથે જ્યારે એપ્લિકેશન ચાલતી હોય ત્યારે તે સંપર્કો, કોલ લૉગ્સ અથવા સંદેશાઓ જેવી અંગત માહિતીની ઍક્સેસ ધરાવશે નહીં. + ગુપ્તતા ગાર્ડ સક્રિય + %1$s અંગત ડેટા એકસેસ કરી શકશે નહીં + ગુપ્તતા ગાર્ડ + %1$s ને %2$sકરવું ગમશે. + + મારી પસંદગી યાદ રાખો + + કૅમેરા ઍક્સેસ કરો + તમારું સ્થાન ઍક્સેસ કરો + તમારી સૂચનાઓ વાંચો + VPN સક્રિય કરો + પાવર અપ થતા શરૂઆત કરો + તમારો કોલ લોગ રદ કરો + તમારા સંપર્કો રદ કરો + તમારા MMS સંદેશાઓ રદ કરો + તમારા SMS સંદેશાઓ રદ કરો + વિન્ડોઝને ટોચ પર ખેંચો + એપ્લિકેશન વપરાશ અંકો મેળવો + તમારી ડિવાઇસને સજાગ રાખો + ફોન કૉલ કરો + તમારું કૅલેન્ડર અપડેટ કરો + કૉલ લોગ અપડેટ કરો + ક્લિપબૉર્ડમાં ફેરફાર કરો + તમારા સંપર્કો અપડેટ કરો + સિસ્ટમ સેટિંગ્સ અપડેટ કરો + માઇક્રોફોન મ્યુટ/અનમ્યુટ કરો + ઓડિયો પ્લે કરો + સૂચનાઓ પોસ્ટ કરો + પ્રોજેક્ટ મીડિયા + તમારું કૅલેન્ડર વાંચો + કૉલ લોગ વાંચો + ક્લિપબૉર્ડ વાંચો + તમારા સંપર્કો વાંચો + તમારા MMS સંદેશાઓ વાંચો + તમારા SMS સંદેશાઓ વાંચો + SMS સંદેશાઓ મેળવો + ઑડિઓ રેકોર્ડ કરો + MMS સંદેશ મોકલો + SMS સંદેશ મોકલો + પાવર અપ થતા શરૂઆત કરો + ટોસ્ટ સંદેશાઓ દર્શાવો + Bluetooth ટૉગલ કરો + મોબાઇલ ડેટા ટૉગલ કરો + NFC ટૉગલ કરો + Wi-Fi ટૉગલ કરો + અલાર્મ વોલ્યુમ નિયંત્રિત કરો + ઓડિયો ફોકસ નિયંત્રિત કરો + Bluetooth વોલ્યુમ નિયંત્રિત કરો + માસ્ટર વોલ્યુમ નિયંત્રિત કરો + મીડિયા બટનોનો ઉપયોગ કરો + મીડિયા વોલ્યુમ નિયંત્રિત કરો + સૂચના વોલ્યુમ નિયંત્રિત કરો + રિંગટોન વોલ્યુમ નિયંત્રિત કરો + હેપ્ટિક સૂચનોનો ઉપયોગ કરો + વૉઇસ કૉલ વોલ્યુમ નિયંત્રિત કરો + MMS સંદેશ લખો + SMS સંદેશ લખો + ફિંગરપ્રિન્ટ વાપરો + વૉઇસમેઇલ ઍડ કરો + ફોન આંકડા ઍક્સેસ કરો + Wi-Fi નેટવર્ક સ્કૅન કરો + વૉલપેપર પરિવર્તન કરો + અસિસ્ટ માળખું વાપરો + સ્ક્રીનશૉટ લો + બૉડિ સેન્સર્સ વાપરો + સેલ પ્રસારણો વાંચો + તમારું કૃત્રિમ સ્થાન મૂકો + બાહ્ય સંગ્રહ વાંચો + બાહ્ય સંગ્રહ લખો + સ્ક્રીન ચાલુ કરો + ડિવાઇસ ખાતા મેળવો + Wi-Fi સ્થિતિ પરિવર્તન કરો + રૂટ ઍક્સેસ મેળવી + + આ સ્ક્રીન અનપિન કરવા માટે બૅક બટન પર ટચ કરી પકડી રાખો. + + કોઇ ડિવાઇસ કનેક્ટ થયેલ નથી + %1$s ડિવાઇસ કનેક્ટ થયેલ છે + %1$s ડિવાઇસેસ કનેક્ટ થયેલ છે + + + + પ્રવૃત્તિ લોન્ચ બ્લૉક થયું + %1$s લોન્ચ થવા સામે સંરક્ષિત છે. ઍપ્લિકેશન લોન્ચ અને અધિકૃત કરવા ટૅપ કરો. + + બેટરી સંપૂર્ણપણે ચાર્જ થઇ ગઈ + ચાર્જર સાથે તમારા ઉપકરણ જોડે નુ જોડાણ કાઢી નાખો બેટરી નુ આયુષ્ય સુધારવા માટે. + + બેટરી અંકો રિસેટ કરો + + ઍપ્લિકેશનને હાલનો નિમ્ન-સ્તરીય બેટરી વપરાશ ડેટા રિસેટ કરવાની છૂટ આપે છે. + + સિમ કાર્ડ બદલાઈ ગયેલ છે + સિમ કાર્ડ મૂળભૂત પસંદગીઓ સુયોજિત કરવા માટે ટેપ કરો + diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml index 823698aeedd7e..25919ff9a3ada 100644 --- a/core/res/res/values-gu-rIN/strings.xml +++ b/core/res/res/values-gu-rIN/strings.xml @@ -254,7 +254,7 @@ "ક્રેડિટ કાર્ડ નંબર્સ અને પાસવર્ડ્સ જેવો વ્યક્તિગત ડેટા શામેલ છે." "સ્થિતિ બાર અક્ષમ કરો અથવા સંશોધિત કરો" "એપ્લિકેશનને સ્થિતિ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે." - "સ્થિતિ બાર" + "સ્થિતિ બાર થાઓ" "એપ્લિકેશનને સ્થિતિ બાર થવાની મંજૂરી આપે છે." "સ્થિતિ બાર વિસ્તૃત કરો/સંકુકિત કરો" "એપ્લિકેશનને સ્થિતિ બાર વિસ્તૃત કરવાની અને સંકુચિત કરવાની મંજૂરી આપે છે." @@ -282,7 +282,7 @@ "એપ્લિકેશનને WAP સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આ પરવાનગીમાં તમને દર્શાવ્યા વિના તમને મોકલેલ સંદેશાઓનું નિરીક્ષણ કરવાની અને કાઢી નાખવાની ક્ષમતાનો સમાવેશ થાય છે." "ચાલુ એપ્લિકેશનો પુનઃપ્રાપ્ત કરો" "એપ્લિકેશનને વર્તમાનમાં અને તાજેતરમાં ચાલી રહેલ કાર્યો વિશેની વિગતવાર માહિતી પુનઃપ્રાપ્ત કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને ઉપકરણ પર કઈ એપ્લિકેશન્સનો ઉપયોગ થાય છે તેના વિશેની માહિતી શોધવાની મંજૂરી આપી શકે છે." - "પ્રોફાઇલ અને ઉપકરણ માલિકોને સંચાલિત કરો" + "પ્રોફાઇલ અને ઉપકરણ માલિકોને સંચાલિત કરો" "એપ્લિકેશન્સને પ્રોફાઇલ માલિકો અને ઉપકરણ માલિકો સેટ કરવાની મંજૂરી આપે છે." "ચાલુ એપ્લિકેશન્સને ફરી ગોઠવો" "એપ્લિકેશનને અગ્રભૂમિ અને પૃષ્ટભૂમિમાં કાર્યો ખસેડવાની મંજૂરી આપે છે. તમારા ઇનપુટ વિના એપ્લિકેશન આ કરી શકે છે." @@ -324,7 +324,7 @@ "એપ્લિકેશનને ઇનકમિંગ અને આઉટગોઇંગ કૉલ્સ વિશેનાં ડેટા સહિત, તમારા ટેબ્લેટના કૉલ લૉગને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ એપ્લિકેશનો આનો ઉપયોગ તમારા કૉલ લૉગને કાઢી નાખવા અથવા સંશોધિત માટે કરી શકે છે." "એપ્લિકેશનને ઇનકમિંગ અને આઉટગોઇંગ કૉલ્સ વિશેનાં ડેટા સહિત, તમારા TV ના કૉલ લૉગને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ એપ્લિકેશનો આનો ઉપયોગ તમારા કૉલ લૉગને કાઢી નાખવા અથવા સંશોધિત માટે કરી શકે છે." "એપ્લિકેશનને ઇનકમિંગ અને આઉટગોઇંગ કૉલ્સ વિશેનાં ડેટા સહિત, તમારા ફોનના કૉલ લૉગને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ એપ્લિકેશનો આનો ઉપયોગ તમારા કૉલ લૉગને કાઢી નાખવા અથવા સંશોધિત માટે કરી શકે છે." - "બૉડી સેન્સર્સ (જેમ કે હાર્ટ રેટ મૉનિટર્સ)" + "બૉડીસેન્સર્સ ઍક્સેસ(જેમકે હ્રદય ગતી મૉનિટર)" "એપ્લિકેશનને તમારી હૃદય ગતિ જેવી તમારી શારીરિક સ્થિતિને મૉનિટર કરતાં સેન્સર્સથી ડેટા ઍક્સેસ કરવાની મંજૂરી આપે છે." "કેલેન્ડર ઇવેન્ટ્સ વત્તા ગોપનીયતા માહિતી વાંચો" "એપ્લિકેશનને મિત્રોના અથવા સહકાર્યકરો સહિત તમારા ટેબ્લેટ પર સંગ્રહિત તમામ કેલેન્ડર ઇવેન્ટ્સ વાંચવાની મંજૂરી આપે છે. આ એપ્લિકેશનને તમારા કેલેન્ડર ડેટાને શેર કરવા કે સાચવવાની મંજૂરી આપી શકે છે, પછી ભલે ગોપનીયતા અથવા સંવેદિતા કોઈપણ હોય." @@ -336,15 +336,15 @@ "એપ્લિકેશનને મિત્રોના અથવા સહકાર્યકરો સહિત તમારા ફોન પર તમે સંશોધિત કરી શકો તે ઇવેન્ટ્સ ઉમેરવા, દૂર કરવા, બદલવાની મંજૂરી આપે છે. આ એપ્લિકેશનને કેલેન્ડર માલિક તરફથી આવતાં હોય તેવા સંદેશા મોકલવાની અથવા માલિકની જાણ વિના ઇવેન્ટ્સ સંશોધિત કરવાની મંજૂરી આપી શકે છે." "વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરો" "એપ્લિકેશનને વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને GPS અથવા અન્ય સ્થાન સ્રોતોના ઓપરેશનમાં દખલ કરવાની મંજૂરી આપી શકે છે." - "નિશ્ચિત સ્થાન (GPS અને નેટવર્ક-આધારિત)" + "નિશ્ચિત સ્થાન ઍક્સેસ કરો (GPS અને નેટવર્ક-આધારિત)" "એપ્લિકેશનને ગ્લોબલ પોઝિશનિંગ સિસ્ટમ (GPS) અથવા સ્થાન સેલ ટાવર્સ અને Wi-Fi જેવા નેટવર્ક સ્થાન સ્રોતોનો ઉપયોગ કરીને તમારું ચોક્કસ સ્થાન મેળવવાની મંજૂરી આપે છે. એપ્લિકેશન દ્વારા તેમનો ઉપયોગ કરવા માટે તમારા ઉપકરણ પર આ સ્થાન સેવાઓ ચાલુ અને ઉપલબ્ધ હોવી આવશ્યક છે. એપ્લિકેશનો તમે ક્યાં છો તે નિર્ધારિત કરવા માટે આનો ઉપયોગ કરી શકે છે અને અતિરિક્ત બૅટરી પાવરનો ઉપયોગ કરી શકે છે." - "અંદાજિત સ્થાન (નેટવર્ક-આધારિત)" + "અંદાજિત સ્થાન ઍક્સેસ કરો (નેટવર્ક-આધારિત)" "એપ્લિકેશનને તમારું અંદાજિત સ્થાન મેળવવાની મંજૂરી આપે છે. આ સ્થાન સેલ ટાવર્સ અને Wi-Fi જેવા નેટવર્ક સ્થાન સ્રોતોનો ઉપયોગ કરીને સ્થાન સેવાઓ દ્વારા મેળવવામાં આવે છે. એપ્લિકેશન દ્વારા તેમનો ઉપયોગ કરવા માટે તમારા ઉપકરણ પર આ સ્થાન સેવાઓ ચાલુ અને ઉપલબ્ધ હોવી આવશ્યક છે. એપ્લિકેશનો તમે અંદાજે ક્યાં છો તે નિર્ધારિત કરવા માટે આનો ઉપયોગ કરી શકે છે." "તમારી ઑડિઓ સેટિંગ્સ બદલો" "એપ્લિકેશનને વૈશ્વિક ઑડિઓ સેટિંગ્સને સંશોધિત કરવાની મંજૂરી આપે છે, જેમ કે વોલ્યુમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો." "ઑડિઓ રેકોર્ડ કરો" "એપ્લિકેશનને માઇક્રોફોન વડે ઑડિઓ રેકોર્ડ કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને તમારી પુષ્ટિ વિના કોઈપણ સમયે ઑડિઓ રેકોર્ડ કરવાની મંજૂરી આપે છે." - "sim સંચાર" + "SIM ને આદેશો મોકલો" "એપ્લિકેશનને SIM પરા આદેશો મોકલવાની મંજૂરી આપે છે. આ ખૂબ જ ખતરનાક છે." "ચિત્રો અને વિડિઓઝ લો" "એપ્લિકેશનને કૅમેરા વડે ચિત્રો અને વિડિઓઝ લેવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને તમારી પુષ્ટિ વિના કોઈપણ સમયે કૅમેરાના ઉપયોગની મંજૂરી આપે છે." @@ -382,7 +382,7 @@ "એપ્લિકેશનને ફોન દ્વારા પરિચિત એકાઉન્ટ્સની સૂચિ મેળવવાની મંજૂરી આપે છે. આમાં તમે ઇન્સ્ટોલ કરેલ એપ્લિકેશનો દ્વારા બનાવેલ કોઈપણ એકાઉન્ટ્સ શામેલ હોઈ શકે છે." "નેટવર્ક કનેક્શન્સ જુઓ" "એપ્લિકેશનને નેટવર્ક કનેક્શન્સ વિશેની માહિતી જોવાની મંજૂરી આપે છે જેમ કે કયા નેટવર્ક્સ અસ્તિત્વમાં છે અને કનેક્ટ થયેલ છે." - "પૂર્ણ નેટવર્ક ઍક્સેસ" + "પૂર્ણ નેટવર્ક ઍક્સેસ મેળવો" "એપ્લિકેશનને નેટવર્ક સૉકેટ્સ બનાવવાની અને કસ્ટમ નેટવર્ક પ્રોટોકોલ્સના ઉપયોગની મંજૂરી આપે છે. બ્રાઉઝર અને એપ્લિકેશનો ઇન્ટરનેટ પર ડેટા મોકલવાના સાધનો પૂરા પાડે છે, તેથી ઇન્ટરનેટ પર ડેટા મોકલવા માટે આ પરવાનગી જરૂરી નથી." "નેટવર્ક કનેક્ટિવિટી બદલો" "એપ્લિકેશનને નેટવર્ક કનેક્ટિવિટીની સ્થિતિ બદલવાની મંજૂરી આપે છે." @@ -402,7 +402,7 @@ "એપ્લિકેશનને સ્થાનિક Bluetooth ફોન ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે." "WiMAX થી કનેક્ટ અને ડિસ્કનેક્ટ કરો" "એપ્લિકેશનને WiMAX સક્ષમ છે કે કેમ અને કનેક્ટ થયેલ છે તે કોઈપણ WiMAX નેટવર્ક્સ વિશેની માહિતી નિર્ધારિત કરવાની મંજૂરી આપે છે." - "WiMAX સ્થિતિ બદલો" + "WiMAX સ્થિતિ બદલો" "ટેબ્લેટને WiMAX નેટવર્ક્સ પર કનેક્ટ કરવાની અને ટેબ્લેટને તેનાથી ડિસ્કનેક્ટ કરવાની મંજૂરી એપ્લિકેશનને આપે છે." "ટીવીને WiMAX નેટવર્ક્સ પર કનેક્ટ કરવાની અને ટીવીને તેનાથી ડિસ્કનેક્ટ કરવાની મંજૂરી એપ્લિકેશનને આપે છે." "ફોનને WiMAX નેટવર્ક્સ પર કનેક્ટ કરવાની અને ફોનને તેનાથી ડિસ્કનેક્ટ કરવાની મંજૂરી એપ્લિકેશનને આપે છે." @@ -485,7 +485,7 @@ "એપ્લિકેશનને ટચ સ્ક્રીનના કેલિબ્રેશન પેરામીટર્સને સંશોધિત કરવાની મંજૂરી આપે છે. સામાન્ય એપ્લિકેશનો માટે ક્યારેય જરૂરી હોતું નથી." "DRM પ્રમાણપત્રોને ઍક્સેસ કરો" "એપ્લિકેશનને DRM પ્રમાણપત્રોની જોગવાઈ કરવાની અને તેનો ઉપયોગ કરવાની મંજૂરી આપે છે. સામાન્ય એપ્લિકેશનો માટે ક્યારેય જરૂરી હોતું નથી." - "Android બીમ ટ્રાન્સફર સ્થિતિ પ્રાપ્ત કરો" + "Android બીમ ટ્રાન્સફર સ્થિતિ પ્રાપ્ત કરો" "એપ્લિકેશનને Android બીમ ટ્રાંસ્ફર્સ વિશે માહિતી પ્રાપ્ત કરવાની મંજૂરી આપે છે" "DRM પ્રમાણપત્રો દૂર કરો" "એપ્લિકેશનને DRM પ્રમાણપત્રો દૂર કરવાની મંજૂરી આપે છે. સામાન્ય એપ્લિકેશનો માટે ક્યારેય જરૂરી હોતું નથી." @@ -1091,11 +1091,11 @@ "ફોર્મેટ કરી રહ્યાં છે..." "શામેલ નથી" "કોઈ મેળ ખાતી પ્રવૃત્તિઓ મળી નથી." - "મીડિયા આઉટપુટ રૂટ કરો" + "મીડિયા આઉટપુટ રૂટ કરો" "એપ્લિકેશનને અન્ય બાહ્ય ઉપકરણો પર મીડિયા આઉટપુટને રૂટ કરવની મંજૂરી આપે છે." - "ઇન્સ્ટોલ સત્રો વાંચો" + "ઇન્સ્ટૉલ સત્રો વાંચો" "એપ્લિકેશનને ઇન્સ્ટોલ સત્રોને વાંચવાની મંજૂરી આપે છે. આ તેને સક્રિય પૅકેજ ઇન્સ્ટોલેશન્સ વિશે વિગતો જોવાની મંજૂરી આપે છે." - "પૅકેજેસ ઇન્સ્ટોલ કરવાની વિનંતી કરો" + "પૅકેજેસ ઇન્સ્ટૉલ કરવાની વિનંતી કરો" "એપ્લિકેશનને પૅકેજેસના ઇન્સ્ટોલેશનની વિનંતી કરવાની મંજૂરી આપો." "ઝૂમ નિયંત્રણ માટે બેવાર ટચ કરો" "વિજેટ ઉમેરી શકાયું નથી." diff --git a/core/res/res/values-hi-watch/strings.xml b/core/res/res/values-hi-watch/strings.xml index 148dab457980f..5d8fd27ec82e6 100644 --- a/core/res/res/values-hi-watch/strings.xml +++ b/core/res/res/values-hi-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d में से %1$d ऐप." + "संवेदक" diff --git a/core/res/res/values-hi/cm_strings.xml b/core/res/res/values-hi/cm_strings.xml new file mode 100644 index 0000000000000..65e20c40df091 --- /dev/null +++ b/core/res/res/values-hi/cm_strings.xml @@ -0,0 +1,168 @@ + + + + + + स्क्रीनशॉट + + रक्षित एसएमएस प्राप्त करें + + ऐप को आवक रक्षित एसएमएस प्राप्त करने देता है। + + रक्षित एसएमएस सूची को संशोधित करें + + ऐप को रक्षित एसएमएस पता सूची को संशोधित करने देता है। + + सुरक्षा + + उपकरण सुरक्षा जानकारी से संबंधित अनुमतियाँ। + + फ़ोन काली सूची पढ़ें + + ऐप को आवक कॉलों या संदेशों के लिए जिन फ़ोन नंबरों को अवरुद्ध किया गया है, उनसे संबंधित जानकारी पढ़ने देता है। + + फ़ोन काली सूची को परिवर्तित करें + + ऐप को आवक कॉलों या संदेशों के लिए जिन फ़ोन नंबरों को अवरुद्ध किया गया है, उन्हें परिवर्तित करने देता है। + + कुंजीकवच वॉलपेपर सेट करें + + ऐप को स्क्रीन वॉलपेपर लॉक को बदलने देता है। + + रीबूट करें + + वर्तमान + + + रीबूट करें + + रिकवरी + + बूटलोडर + + डाउनलोड करें + + नरम रीबूट + + रीबूट करें + + आपका टैब्लेट रीबूट करेगा। + आपका फ़ोन रीबूट करेगा। + + रीबूट कर रहे हैं\u2026 + + ऐप को मार दिया गया + + नेटवर्क पर एडीबी को सक्षम कर दिया गया + + यूएसबी और नेटवर्क पर एडीबी को सक्षम कर दिया गया + + डीबगिंग को अक्षम करने के लिए छुएँ। + + एडीबी - %1$s + यूएसबी और नेटवर्क + यूएसबी + नेटवर्क + + ऐप लॉन्च का अंतररोधन करें + + %s स्थापित नहीं है + + वरीयता + कुछ नहीं + + + + गोपनीयता रक्षक को सक्षम या अक्षम करें + ऐप को इसे बदलने देता है कि कोई दूसरा ऐप गोपनीयता रक्षक के साथ चलेगा अथवा नहीं। जब ऐप गोपनीयता रक्षक के साथ चलता है, उसे संपर्क, कॉल लॉग, या संदेश जैसे निजी डेटा तक पहुँचने की अनुमति नहीं होगी। + गोपनीयता रक्षक सक्रिय है + %1$s निजी डेटा में पहुँच नहीं सकेगा + गोपनीयता रक्षक + %1$s क्या आप %2$s करना चाहते हैं। + + मेरी पसंद को याद रखें + + कैमरे में पहुँचें + अपने स्थान का उपयोग करें + अपनी अधिसूचनाओं को पढ़ें + वीपीएन को सक्रिय करें + पावर अप के दौरान चालू करें + अपने कॉल लॉग को हटाएँ + अपने संपर्कों को हटाएँ + अपने एमएमएस संदेशों को हटाएँ + अपने एसएमएस संदेशों को हटाएँ + ऊपर विंडो बनाएँ + ऐप उपयोग आँकड़े प्राप्त करें + अपने उपकरण को जागृत रखें + फ़ोन कॉल करें + अपने कैलेंडर को अद्यतन करें + अपने कॉल लॉग को अद्यतन करें + अपने क्लिपबोर्ड को संशोधित करें + अपने संपर्कों को अद्यतन करें + सिस्टम सेटिंग को अद्यतन करें + माइक्रोफ़ोन को मूक/वाचाल करें + ऑडियो चलाएँ + अधिसूचना पोस्ट करें + परियोजना माध्यम + अपने कैलेंडर को पढ़ें + कॉल लॉग को पढ़ें + क्लिपबोर्ड को पढ़ें + अपने संपर्कों को पढ़ें + अपने एमएमएस संदेशों को पढ़ें + अपने एसएमएस संदेशों को पढ़ें + एसएमएस संदेश प्राप्त करें + ऑडियो रिकॉर्ड करें + एमएमएस संदेश भेजें + एसएमएस संदेश भेजें + पावर अप पर चालू करें + टोस्ट संदेश प्रदर्शित करें + ब्लूटूथ को बंद-चालू करें + एनएफसी को बंद-चालू करें + अलार्म वोल्यूम को नियंत्रित करें + ऑडियो फ़ोकस को नियंत्रित करें + ब्लूटूथ वोल्यूम को नियंत्रित करें + मास्टर वोल्यूम को नियंत्रित करें + माध्यम बटनों का उपयोग करें + माध्यम वोल्यूम को नियंत्रित करें + अधिसूचना वोल्यूम को नियंत्रित करें + रिंगटोन वोल्यूम को नियंत्रित करें + हैप्टिक फ़ीडबैक का उपयोग करें + वोइल कॉल वोल्यूम को नियंत्रित करें + एक एमएमएस संदेश लिखें + एक एसएमएस संदेश लिखें + मूल तक पहुँच प्राप्त करें + + इस स्क्रीन को अनपिन करने के लिए पीछे के बटन को कुछ देर के लिए छुएँ। + + कोई जुड़ा हुआ उपकरण नहीं है + %1$s जुड़ा हुआ उपकरण + %1$s जुड़े हुए उपकरण + + + + + + बैटरी के आँकड़ों को रीसेट करें + + अनुप्रयोग को वर्तमान निम्न-स्तर के बैटरी उपयोग डेटा को रीसेट करने देता है। + + diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index e030ac17285ec..ce0543e57233a 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -254,7 +254,7 @@ "क्रेडिट कार्ड नंबर और पासवर्ड जैसा व्यक्तिगत डेटा शामिल होता है." "स्‍थिति बार अक्षम या बदलें" "ऐप्स को स्थिति बार अक्षम करने या सिस्‍टम आइकन को जोड़ने या निकालने देता है." - "स्‍थिति बार" + "स्‍थिति बार होने दें" "ऐप्स को स्‍थिति बार होने देता है." "स्‍थिति बार विस्‍तृत/संक्षिप्त करें" "ऐप्स को स्थिति बार को विस्तृत या संक्षिप्त करने देता है." @@ -282,7 +282,7 @@ "ऐप्स को WAP संदेशों को प्राप्‍त और संसाधित करने देता है. इस अनुमति में आपको भेजे गए संदेशों की निगरानी आपको दिखाए बिना करने और हटाने की क्षमता शामिल है." "चल रहे ऐप्स पुनर्प्राप्त करें" "ऐप्स को वर्तमान में और हाल ही में चल रहे कार्यों के बारे में जानकारी को पुन: प्राप्‍त करने देता है. इससे ऐप्स डिवाइस पर उपयोग किए गए ऐप्स के बारे में जानकारी खोज सकता है." - "प्रोफ़ाइल और डिवाइस स्‍वामियों को प्रबंधित करें" + "प्रोफ़ाइल और डिवाइस स्‍वामियों को प्रबंधित करें" "ऐप्‍स को प्रोफ़ाइल स्‍वामी और डिवाइस स्‍वामी सेट करने दें." "चल रहे ऐप्स पुन: क्रमित करें" "ऐप्स को कार्यों को अग्रभूमि और पृष्‍ठभूमि पर ले जाने देता है. ऐप्स आपके इनपुट के बिना यह कर सकता है." @@ -324,7 +324,7 @@ "ऐप्स को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके टेबलेट का कॉल लॉग संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स आपके कॉल लॉग को मिटाने या संशोधित करने के लिए इसका उपयोग कर सकते हैं." "ऐप को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके टैबलेट के कॉल लॉग में बदलाव करने देती है. दुर्भावनापूर्ण ऐप्‍स आपके कॉल लॉग को मिटाने या संशोधित करने के लिए उसका उपयोग कर सकते हैं." "ऐप्स को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके फ़ोन का कॉल लॉग संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स आपके कॉल लॉग को मिटाने या संशोधित करने के लिए इसका उपयोग कर सकते हैं." - "बॉडी सेंसर (जैसे हृदय गति मॉनीटर)" + "शरीर संवेदक एक्सेस करें (जैसे हृदय गति मॉनीटर)" "ऐप को आपकी शारीरिक स्‍थिति, जैसे आपकी हृदय गति पर नज़र रखने वाले संवेदकों का डेटा एक्‍सेस करने देती है." "केलैंडर ईवेंट के साथ-साथ गोपनीय जानकारी पढ़ें" "ऐप्स को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके टेबलेट पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे गोपनीयता या संवेदनशीलता पर ध्यान दिए बिना, ऐप्स आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है." @@ -336,15 +336,15 @@ "ऐप्स को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने फ़ोन पर संशोधित कर सकते हैं. इससे ऐप्स , अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है." "अतिरिक्त स्‍थान प्रदाता आदेशों में पहुंचे" "ऐप्स को अतिरिक्त स्थान प्रदाता आदेशों पर पहुंचने देती है. इससे ऐप्स GPS या अन्य स्थान स्रोतों के संचालन में अवरोध पहुंचा सकता है." - "सटीक स्थान (GPS और नेटवर्क-आधारित)" + "सटीक स्थान एक्सेस करें (GPS और नेटवर्क-आधारित)" "ऐप्स को ग्लोबल पोज़िशनिंग सिस्टम (GPS) या सेल टॉवर और वाई-फ़ाई जैसे नेटवर्क स्थान स्रोतों का उपयोग करके आपका सटीक स्थान प्राप्त करने देती है. ऐप्स द्वारा इन स्थान सेवाओं का उपयोग किए जाने के लिए इन्हें चालू होना चाहिए और आपके डिवाइस पर उपलब्ध होना चाहिए. ऐप्स इसका उपयोग यह पता करने में कर सकते हैं कि आप कहां पर हैं, और अतिरिक्त बैटरी की खपत कर सकते हैं." - "अनुमानित स्थान (नेटवर्क-आधारित)" + "अनुमानित स्थान एक्सेस करें (नेटवर्क-आधारित)" "ऐप्स को आपका अनुमानित स्थान प्राप्त करने देती है. इस स्थान को सेल टॉवर और वाई-फ़ाई जैसे नेटवर्क स्थान स्रोतों का उपयोग करके स्थान सेवाओं द्वारा प्राप्त किया गया है. ऐप्स द्वारा इन स्थान सेवाओं का उपयोग करने के लिए इन्हें चालू होना चाहिए और आपके डिवाइस में उपलब्ध होना चाहिए. ऐप्स इसका उपयोग यह पता लगाने में कर सकते हैं कि आप लगभग कहां पर हैं." "अपनी ऑडियो सेटिंग बदलें" "ऐप्स को वैश्विक ऑडियो सेटिंग, जैसे वॉल्‍यूम और कौन-सा स्पीकर आउटपुट के लिए उपयोग किया गया, संशोधित करने देता है." "ऑडियो रिकॉर्ड करें" "ऐप्स को माइक्रोफ़ोन द्वारा ऑडियो रिकार्ड करने देता है. यह अनुमति ऐप्स को आपकी पुष्टि के बिना किसी भी समय ऑडियो रिकार्ड करने देती है." - "सिम संचार" + "SIM पर आदेश भेजें" "ऐप्स को सिम में आदेश भेजने देती है. यह बहुत ही खतरनाक है." "चित्र और वीडियो लें" "ऐप्स को कैमरे से चित्र और वीडियो लेने देता है. यह अनुमति ऐप्स को किसी भी समय आपकी पुष्टि के बिना कैमरे का उपयोग करने देती है." @@ -382,7 +382,7 @@ "ऐप्स को फ़ोन द्वारा ज्ञात खातों की सूची प्राप्‍त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्‍हें आपके द्वारा इंस्‍टॉल किए गए ऐप्स ने बनाया है." "नेटवर्क कनेक्‍शन देखें" "ऐप्स को नेटवर्क कनेक्‍शन के बारे में जानकारी देखने देता है जैसे कौन से नेटवर्क मौजूद हैं और कनेक्‍ट हैं." - "पूर्ण नेटवर्क एक्सेस" + "पूर्ण नेटवर्क एक्सेस पाएं" "ऐप्स को नेटवर्क सॉकेट बनाने और कस्‍टम नेटवर्क प्रोटोकॉल का उपयोग करने देता है. ब्राउज़र और अन्‍य ऐप्स इंटरनेट को डेटा भेजने के साधन उपलब्‍ध कराते हैं, ताकि इंटरनेट को डेटा भेजने के लिए इस अनुमति की आवश्‍यकता नहीं हो." "नेटवर्क कनेक्‍टिविटी बदलें" "ऐप्स को नेटवर्क कनेक्टिविटी की स्थिति बदलने देता है." @@ -402,7 +402,7 @@ "ऐप्स को स्‍थानीय ब्लूटूथ फ़ोन कॉन्‍फ़िगर करने देता है, और रिमोट डिवाइस के साथ खोजने और युग्‍मित करने देता है." "WiMAX से कनेक्ट और डिस्कनेक्ट करें" "ऐप्स को WiMAX सक्षम है या नहीं और कनेक्‍ट किए गए किसी WiMAX नेटवर्क के बारे में जानकारी निर्धारित करने देता है." - "WiMAX स्‍थिति बदलें" + "WiMAX स्‍थिति बदलें" "ऐप्स को WiMAX नेटवर्क से टेबलेट को कनेक्‍ट और डिस्‍कनेक्‍ट करने देता है." "ऐप को, टीवी को WiMAX नेटवर्कों से कनेक्‍ट करने और उनसे डिस्‍कनेक्‍ट करने देती है." "ऐप्स को WiMAX नेटवर्क से फ़ोन को कनेक्‍ट और डिस्‍कनेक्‍ट करने देता है." @@ -485,7 +485,7 @@ "ऐप्स को टच स्क्रीन के कैलिब्रेशन पैरामीटर को बदलने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए." "DRM प्रमाणपत्र एक्सेस करें" "ऐप्लिकेशन को DRM प्रमाणपत्रों का प्रावधान और उपयोग करने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होना चाहिए." - "Android Beam स्थानान्तरण स्थिति प्राप्त करें" + "Android Beam ट्रांसफर स्थिति प्राप्त करें" "इस ऐप्लिकेशन को वर्तमान Android Beam स्थानान्तरणों के बारे में जानकारी प्राप्त करने देती है." "DRM प्रमाणपत्रों को निकाल सकता है" "एप्‍लिकेशन को DRM प्रमाणपत्रों को निकालने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होनी चाहिए." @@ -1091,11 +1091,11 @@ "प्रारूपित किया जा रहा है..." "नहीं लगाया गया" "कोई मिलती-जुलती गतिविधि नहीं मिली." - "मीडिया आउटपुट को रूट करें" + "मीडिया आउटपुट को रूट करें" "ऐप्स को मीडिया आउटपुट को अन्य बाहरी डिवाइस पर रूट करने देता है." - "इंस्टॉल सत्रों को पढ़ें" + "इंस्टॉल सत्रों को पढ़ें" "ऐप्लिकेशन को इंस्टॉल सत्रों को पढ़ने देती है. इससे उसे सक्रिय पैकेज इंस्टॉलेशन के बारे में विवरण देखने की अनुमति मिल जाती है." - "पैकेज इंस्टॉल करने का अनुरोध" + "पैकेज इंस्टॉल करने का अनुरोध करें" "किसी ऐप्लिकेशन को पैकेज इंस्टॉल करने के अनुरोध की अनुमति देता है." "ज़ूम नियंत्रण के लिए दो बार स्पर्श करें" "विजेट नहीं जोड़ा जा सका." diff --git a/core/res/res/values-hr-watch/strings.xml b/core/res/res/values-hr-watch/strings.xml index 4b88ac79eb83e..7b372ed6905a5 100644 --- a/core/res/res/values-hr-watch/strings.xml +++ b/core/res/res/values-hr-watch/strings.xml @@ -21,4 +21,5 @@ "Aplikacija %1$d od %2$d." + "Senzori" diff --git a/core/res/res/values-hr/cm_strings.xml b/core/res/res/values-hr/cm_strings.xml new file mode 100644 index 0000000000000..75abf479414b4 --- /dev/null +++ b/core/res/res/values-hr/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Snimak zaslona + + primaj zaštićeni SMS + + Dopušta aplikaciji da prima dolazeći zaštićeni SMS. + + Izmjena popisa zaštićenih SMS poruka + + Dozvoljava aplikaciji izmjenu popisa adresa zaštićenih SMS poruka. + + Sigurnost + + Dopuštenja vezana za sigurnosne informacije uređaja. + + čitati listu blokiranih poziva + + Dopušta aplikaciji čitanje informacija o telefonskim brojevima čije su dolazne poruke ili pozivi blokirani. + + promjeniti popis blokiranih poziva + + Dopušta aplikaciji promjenu telefonskih brojeva čije su dolazne poruke ili pozivi blokirani. + + postaviti pozadinu zaslona zaključavanja + + Dozvoljava aplikaciji promjenu pozadine zaslona zaključavanja. + + Ponovno pokreni + + Trenutna + + + Ponovno pokreni + + Način oporavka + + Bootloader + + Download + + Brzo ponovno pokretanje + + Ponovno pokretanje + + Tablet će ponovno biti pokrenut. + Telefon će ponovno biti pokrenut. + + Ponovno pokretanje\u2026 + + Aplikacija prisilno zaustavljena + + Mrežni ADB omogućen + + ADB preko USB & mreže omogućen + + Dodirnite za onemogućavanje ispravljanja pogrešaka. + + ADB - %1$s + USB i mrežni + USB + Mreža + + Presresti pokretanje aplikacija + + %s nije instalirano + + Prioritet + Ništa + + Wi- Fi Hotspot onemogućen zbog SIM promjene + + Isključite Wi-Fi + + omogućiti ili onemogućiti Zaštitu privatnosti + Dopušta aplikaciji odrediti hoće li druga aplikacija biti pokrenuta pod Nadzorom Privatnosti. Kada ja aplikacija pod Nadzorom Privatnosti, neće imati pristup osobnim podacima kao što su kontakti, zapisi poziva ili poruke. + Nadzor privatnosti aktivan + %1$s neće moći pristupiti osobnim podacima + Nadzor privatnosti + %1$s želi %2$s. + + Zapamti moj odabir + + pristupiti kameri + pristupiti vašoj lokaciji + čitati vaše obavijesti + Aktiviraj VPN + Pokrenuti pri podizanju sustava + Obriši popis poziva + Obriši kontakte + Obriši MMS poruke + Obriši SMS poruke + Iscrtaj prozore na vrhu + Statistika korištenja aplikacija + održavati uređaj budnim + uspostaviti poziv + ažurirati kalendar + ažurirati zapisnik poziva + urediti clipboard + ažurirati kontakte + ažurirati postavke sistema + Isključiti/uključiti mikrofon + producirati zvuk + obavijestiti + Pokrenuti multimediju + čitati vaš kalendar + čitati zapisnik poziva + čitati Clipboard + čitati vaše kontakte + čitati vaše MMS poruke + čitati vaše SMS poruke + primiti SMS poruku + snimiti zvuk + poslati MMS poruku + poslati SMS poruku + se pokrenuti pri pokretanju sistema + Prikazivati toast poruke + upravljati Bluetooth-om + uključi/isključi mobilne podatke + Uključi/isključi NFC + upravljati Wi-Fi-em + kontrolirati glasnoću alarma + kontrolirati fokus zvuka + kontrolirati glasnoću Bluetooth-a + kontrolirati glavnu glasnoću zvuka + koristiti tipke medija + kontrolirati glasnoću medija + kontrolirati glasnoću zvuka obavijesti + kontrolirati glasnoću melodije zvona + koristiti vibraciju + kontrolirati glasnoću glasovnog poziva + napisati MMS poruku + napisati SMS poruku + koristite otisak prsta + dodajte glasovnu poruku + pristup stanju telefona + skeniraj Wi-Fi mreže + promjeni pozadinsku sliku + koristi pomoćne strukture + snimak zaslona + koristi senzore + pročitati signal odašiljača + prikazivanje lažne lokacije + čitaj vanjsku pohranu + piši na vanjsku pohranu + uključite zaslon + dobavi račune uređaja + promjeni Wi-Fi stanje + Zatraži root pristup + + Za otkvačiti ovaj zaslon dodirnite i držite tipku za natrag + + Nema spojenih uređaja + %1$s povezani uređaj + %1$s povezanih uređaja + + + + Blokirana aktivnost pokretanja + %1$s je zaštićena od pokretanja. Dodirnite za potvrdu i pokrenite aplikaciju. + + Baterija puna + Odspojite punjač s uređaja da bi poboljšali trajnost baterije. + + Resetirati statistike baterije + + Dopušta aplikaciji resetiranje trenutnog korištenja podataka uz štednju energije. + + SIM kartice su se promijenile + Dodirnite za postavljanje SIM kartice zadane postavke + diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index dd58d5c342e39..ae1b9094bcdd3 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -255,7 +255,7 @@ "Uključuje osobne podatke kao što su brojevi kreditnih kartica i zaporke." "onemogućavanje ili izmjena trake statusa" "Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona." - "traka statusa" + "biti traka statusa" "Aplikaciji omogućuje da bude traka statusa." "proširivanje/sažimanje trake statusa" "Omogućuje aplikaciji proširivanje ili sažimanje trake statusa." @@ -283,7 +283,7 @@ "Aplikaciji omogućuje primanje i obradu WAP poruka. Ta dozvola uključuje mogućnost nadziranja ili brisanja vama poslanih poruka, a da vam ih ne prikaže." "dohvaćanje pokrenutih aplikacija" "Aplikaciji omogućuje dohvaćanje informacija o trenutačnim i nedavnim tekućim zadacima. To aplikaciji može omogućiti otkrivanje informacija o tome koje se aplikacije upotrebljavaju na uređaju." - "Upravljanje vlasnicima profila i uređaja" + "upravljati vlasnicima profila i uređaja" "Omogućuje aplikaciji postavljanje vlasnika profila i vlasnika uređaja." "promjena redoslijeda pokrenutih aplikacija" "Aplikaciji omogućuje premještanje zadataka u prednji plan ili pozadinu. Aplikacija to može napraviti bez vašeg naloga." @@ -325,7 +325,7 @@ "Aplikaciji omogućuje izmjenu dnevnika poziva vašeg tabletnog računala zajedno s podacima o dolaznim i odlaznim pozivima. Zlonamjerne aplikacije to mogu upotrebljavati za brisanje ili izmjenu vašeg dnevnika poziva." "Aplikaciji omogućuje izmjenu zapisnika poziva vašeg televizora zajedno s podacima o dolaznim i odlaznim pozivima. Zlonamjerne aplikacije to mogu upotrebljavati za brisanje ili izmjenu vašeg zapisnika poziva." "Aplikaciji omogućuje izmjenu dnevnika poziva vašeg telefona zajedno s podacima o dolaznim i odlaznim pozivima. Zlonamjerne aplikacije to mogu upotrebljavati za brisanje ili izmjenu vašeg dnevnika poziva." - "senzori tjelesnih funkcija (npr. monitori otkucaja srca)" + "pristupati biometrijskim senzorima (kao što su monitori otkucaja srca)" "Omogućuje aplikaciji pristup podacima sa senzora koji nadziru vaše fizičko stanje, na primjer, broj otkucaja srca." "čitajte kalendarske događaje i povjerljive informacije" "Aplikaciji omogućuje čitanje svih događaja u kalendaru pohranjenih na vašem tabletnom računalu, uključujući one od vaših prijatelja ili suradnika. To aplikaciji može omogućiti dijeljenje ili spremanje vaših podataka kalendara, neovisno o povjerljivosti ili osjetljivosti." @@ -337,15 +337,15 @@ "Aplikaciji omogućuje dodavanje, uklanjanje i promjenu događaja koje možete izmijeniti na telefonu, uključujući one od vaših prijatelja ili suradnika. To aplikaciji može omogućiti slanje poruka koje izgledaju kao da dolaze od vlasnika kalendara ili izmjenu događaja bez znanja vlasnika." "pristup dodatnim naredbama davatelja lokacije" "Omogućuje aplikaciji pristup dodatnim naredbama davatelja usluga lokacije. To može omogućiti aplikaciji ometanje rada GPS-a ili drugih izvora lokacije." - "precizna lokacija (GPS i mreža)" + "pristupati preciznoj lokaciji (na temelju GPS-a i mreža)" "Aplikacija može dobiti vašu preciznu lokaciju pomoću globalnog pozicijskog sustava (GPS-a) ili mrežnih izvora lokacije kao što su bazne stanice i Wi-Fi. Te lokacijske usluge moraju biti uključene i dostupne vašem uređaju da bi ih aplikacija mogla upotrebljavati. Aplikacije mogu upotrebljavati tu mogućnost kako bi utvrdile vašu lokaciju i mogu dodatno trošiti bateriju." - "približna lokacija (mreža)" + "pristupati približnoj lokaciji (na temelju mreža)" "Aplikacija može dobiti vašu približnu lokaciju. Tu lokaciju izvode lokacijske usluge pomoću mrežnih izvora lokacije kao što su bazne stanice i Wi-Fi. Te lokacijske usluge moraju biti uključene i dostupne vašem uređaju da bi ih aplikacija mogla upotrebljavati. Aplikacije mogu upotrebljavati tu mogućnost kako bi utvrdile vašu približnu lokaciju." "promjena postavki zvuka" "Aplikaciji omogućuje izmjenu globalnih postavki zvuka, primjerice glasnoće i zvučnika koji se upotrebljava za izlaz." "snimanje zvuka" "Aplikaciji omogućuje snimanje zvuka mikrofonom. Ta dozvola aplikaciji omogućuje snimanje zvuka u bilo kojem trenutku bez vašeg odobrenja." - "komunikacija sa SIM-om" + "slati naredbe SIM-u" "Omogućuje aplikaciji slanje naredbi SIM-u. To je vrlo opasno." "snimi fotografije i videozapise" "Aplikaciji omogućuje snimanje slika i videozapisa fotoaparatom. Ta dozvola aplikaciji omogućuje upotrebu fotoaparata u bilo kojem trenutku bez vašeg odobrenja." @@ -383,7 +383,7 @@ "Aplikaciji omogućuje dobivanje popisa računa koje telefon poznaje. Uključeni mogu biti svi računi koje izrade aplikacije koje ste instalirali." "prikaz mrežnih veza" "Aplikaciji omogućuje pregled informacija o mrežnim vezama, primjerice koje mreže postoje i koje su spojene." - "puni mrežni pristup" + "imati puni mrežni pristup" "Aplikaciji omogućuje stvaranje mrežnih utičnica i upotrebu prilagođenih mrežnih protokola. Preglednik i druge aplikacije pružaju sredstva za slanje podataka na internet, tako da ta dozvola nije potrebna za slanje podataka na internet." "promjena mrežne povezivosti" "Aplikaciji omogućuje promjenu stanja mrežnog povezivanja." @@ -403,7 +403,7 @@ "Aplikaciji omogućuje konfiguraciju lokalnog Bluetooth telefona i otkrivanje i uparivanje s udaljenim uređajima." "uspostavljanje i prekidanje veze s WiMAX-om" "Aplikaciji omogućuje utvrđivanje omogućenosti WiMAX mreže te daje informaciju o tome je li spojena neka WiMAX mreža." - "Promjena stanja WiMAX mreže" + "promjena stanja WiMAX mreže" "Aplikaciji omogućuje povezivanje tabletnog računala s WiMAX mrežama i prekidanje veze tabletnog računala s njima." "Aplikaciji omogućuje povezivanje i prekidanje veze televizora s WiMAX mrežama." "Aplikaciji omogućuje povezivanje telefona s WiMAX mrežama i prekidanje veze telefona s njima." @@ -486,7 +486,7 @@ "Omogućuje aplikaciji izmjenu parametara kalibracije dodirnog zaslona. Ne bi trebalo biti potrebno za uobičajene aplikacije." "pristup DRM certifikatima" "Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Ne bi trebalo biti potrebno za uobičajene aplikacije." - "Primanje statusa prijenosa Android Beama" + "primati status prijenosa Android Beama" "Omogućuje aplikaciji primanje podataka o trenutačnim prijenosima Android Beama" "uklanjanje DRM certifikata" "Omogućuje aplikaciji uklanjanje DRM certifikata. Ne bi trebalo biti potrebno za uobičajene aplikacije." @@ -1098,11 +1098,11 @@ "Formatiranje…" "Nije umetnut" "Nisu pronađene podudarne radnje." - "Usmjeravanje medijskog izlaza" + "usmjeravati medijski izlaz" "Aplikaciji omogućuje usmjeravanje medijskog izlaza na druge vanjske uređaje." - "Čitanje sesija instaliranja" + "čitati sesije instaliranja" "Omogućuje aplikaciji čitanje sesija instaliranja. Aplikacija može vidjeti pojedinosti o aktivnim instaliranjima paketa." - "Zahtijevaj instaliranje paketa" + "zahtijevati instaliranje paketa" "Aplikaciji omogućuje zahtijevanje instaliranja paketa." "Dodirnite dvaput za upravljanje zumiranjem" "Widget nije moguće dodati." diff --git a/core/res/res/values-hu-watch/strings.xml b/core/res/res/values-hu-watch/strings.xml index 9f2e97f3c4753..060ab23be2637 100644 --- a/core/res/res/values-hu-watch/strings.xml +++ b/core/res/res/values-hu-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d/%2$d. alkalmazás" + "Érzékelők" diff --git a/core/res/res/values-hu/cm_strings.xml b/core/res/res/values-hu/cm_strings.xml new file mode 100644 index 0000000000000..5deb89c5548a1 --- /dev/null +++ b/core/res/res/values-hu/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Képernyőmentés + + védett SMS fogadása + + Lehetővé teszi az alkalmazás számára, hogy védett SMS-t fogadjon. + + védett SMS lista módosítása + + Lehetővé teszi az alkalmazás számára, hogy módosítsa a védett SMS címlistát. + + Biztonság + + Engedélyek az eszköz biztonsági információira vonatkozóan. + + tiltólista olvasása + + Lehetővé teszi az alkalmazás számára, hogy olvassa azokat a számokat, melyek blokkolva vannak bejövő hívásnál vagy üzenetnél. + + tiltólista módosítása + + Lehetővé teszi az alkalmazás számára, hogy szerkessze azokat a telefonszámokat melyek blokkolva vannak bejövő hívásnál vagy üzenetnél. + + billentyűzár háttérképének beállítása + + Lehetővé teszi az alkalmazás számára, hogy módosítsa a képernyőzár hátterét. + + Újraindítás + + Jelenlegi + + + Újraindítás + + Recovery + + Bootloader + + Download + + Lágy újraindítás + + Újraindítás + + A táblagép újraindul. + A telefon újraindul. + + Újraindítás\u2026 + + Alkalmazás leállítva + + ADB hálózaton keresztül engedélyezve + + ADB USB-n & hálózaton keresztül engedélyezve + + Érintse meg a hibakeresés letiltásához. + + ADB - %1$s + USB és hálózat + USB + Hálózat + + alkalmazás indításának feltartóztatása + + %s nincs telepítve + + Prioritás + Nincs + + Wi\u2011Fi hotspot kikapcsolva a SIM előfizetés módosítása miatt + + Wi\u2011Fi kikapcsolása + + adatvédelem engedélyezése vagy tiltása + Lehetővé teszi, hogy más alkalmazások számára engedélyezze, vagy letiltsa az adatvédelmet. Amikor az alkalmazás adatvédelmi módban fut, nem fog hozzáférni az Ön személyes adataihoz, mint a névjegyzékéhez, üzeneteihez, vagy a hívásnaplójához. + Adatvédelem aktív + %1$s nem fog hozzáférni a személyes adataihoz + Adatvédelmi beállítások + %1$s a következő műveletet szeretné végrehajtani: %2$s. + + Jegyezze meg a választást + + hozzáférés a kamerához + hozzáférés a helyadataihoz + értesítések olvasása + VPN-kapcsolat aktiválása + bekapcsoláskor elindul + hívásnapló törlése + névjegyek törlése + MMS-üzenetek törlése + SMS-üzenetek törlése + átfedő ablakok rajzolása + hozzáférés alkalmazás használati statisztikákhoz + készülék ébrentartása + hívást kezdeményezhet + frissítheti a naptárat + frissítheti a hívásnaplót + módosíthatja a vágólapot + frissítheti a névjegyzéket + frissítheti a rendszerbeállításokat + mikrofon némítása/némítás feloldása + zene lejátszása + értesítés küldése + hozzáférés a médiához + naptár olvasása + hívásnapló olvasása + vágólap olvasása + névjegyek olvasása + MMS üzenetek olvasása + SMS üzenetek olvasása + SMS üzenet fogadása + hangfelvétel készítése + MMS üzenet küldése + SMS üzenet küldése + bekapcsoláskor elindul + buborékszöveg üzenetek megjelenítése + Bluetooth kapcsolása + mobilnet váltása + NFC kapcsolása + Wi-Fi kapcsolása + ébresztőhang vezérlése + hang fókusz vezérlése + Bluetooth hangerő vezérlése + fő hangerő vezérlése + média gombok használata + média hangerő vezérlése + értesítési hangerő vezérlése + csengőhang hangerejének vezérlése + érintési visszajelzés használata + hívás közbeni hang vezérlése + MMS írása + SMS írása + ujjlenyomat használata + hangposta hozzáadása + hozzáférés telefon állapotához + Wi-Fi hálózatok keresése + háttérkép módosítása + támogatási szerkezet használata + képernyőmentés készítése + testszenzorok használata + hálózati üzenetek olvasása + helyutánzatok engedélyezése + külső tároló olvasása + külső tároló írása + képernyő bekapcsolása + eszköz fiókok lekérése + Wi-Fi állapot módosítása + rendszergazdai jogosultság szerzése + + Képernyő rögzítésének feloldásához érintse meg és tartsa nyomva a Vissza gombot. + + Nincs csatlakoztatott készülék + %1$s csatlakoztatott eszköz + %1$s csatlakoztatott eszköz + + + + Tevékenység elindítás blokkolva + %1$s védve van az indításra. Kattintson a hitelesítésére és indítsa el az alkalmazást. + + Akkumulátor teljesen feltöltve + A készüléket vegye le a töltőről, hogy javítsa az akkumulátor élettartamát. + + akkumulátor használati statisztika törlése + + Lehetővé teszi az alkalmazás számára, hogy törölhesse alacsony szintű akkumulátor használatára vonatkozó adatokat. + + Megváltoztak a SIM-kártyák + Koppintson a SIM-kártya alapértelmezett beállításainak megadásához + diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 18a2a7c98a585..d5abc40736c7f 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -53,7 +53,7 @@ "A törlés sikerült." "Helytelen jelszó." "MMI kész." - "A megadott régi PIN kód helytelen." + "A megadott régi PIN-kód helytelen." "A megadott PUK kód helytelen." "A beírt PIN kódok nem egyeznek." "Írjon be egy 4-8 számjegyű PIN kódot." @@ -75,7 +75,7 @@ "Hívásvárakoztatás" "Hívásletiltás" "Jelszómódosítás" - "PIN kód módosítása" + "PIN-kód módosítása" "Szám hívása" "Hívószám korlátozva" "Háromutas hívás" @@ -254,7 +254,7 @@ "Beleértve a személyes adatokat, például a hitelkártyaszámokat és jelszavakat." "állapotsor kikapcsolása vagy módosítása" "Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását." - "állapotsor" + "az állapotsor szerepének átvétele" "Lehetővé teszi az alkalmazás számára, hogy az állapotsoron legyen." "állapotsáv részletes- és listanézete" "Lehetővé teszi az alkalmazás számára, hogy váltson az állapotsor részletes és listanézete között." @@ -282,7 +282,7 @@ "Lehetővé teszi az alkalmazás számára, hogy WAP-üzeneteket fogadjon és dolgozzon fel. Ez azt is jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat." "futó alkalmazások lekérése" "Lehetővé teszi az alkalmazás számára a jelenleg futó és nemrég befejezett feladatokkal kapcsolatos információk lekérését. Ezáltal az alkalmazás engedélyt kap az eszközön használt alkalmazásokkal kapcsolatos információk felderítésére." - "Profil- és eszköztulajdonosok kezelése" + "profil és eszköztulajdonosok kezelése" "Lehetővé teszi, hogy az alkalmazások beállítsák a profil- és az eszköztulajdonosokat." "futó alkalmazások átrendezése" "Lehetővé teszi az alkalmazás számára, hogy feladatokat helyezzen át az előtérből a háttérbe és fordítva. Az alkalmazás ezt az Ön jóváhagyása nélkül is megteheti." @@ -324,7 +324,7 @@ "Lehetővé teszi, hogy az alkalmazás módosítsa a táblagép híváslistáját, beleértve a bejövő és kimenő hívások adatait is. A rosszindulatú alkalmazások ezt arra használhatják, hogy híváslistáját töröljék vagy módosítsák." "Lehetővé teszi, hogy az alkalmazás módosítsa a tévé hívásnaplóját, így például a bejövő és kimenő hívások adatait is. A rosszindulatú alkalmazások ezt hívásnaplója törlésére vagy módosítására használhatják." "Lehetővé teszi, hogy az alkalmazás módosítsa a telefon híváslistáját, beleértve a bejövő és kimenő hívások adatait is. A rosszindulatú alkalmazások ezt arra használhatják, hogy híváslistáját töröljék vagy módosítsák." - "testérzékelők (pl. pulzusmérő)" + "hozzáférés a testérzékelőkhöz (például pulzusmérők)" "Engedélyezi az alkalmazásnak, hogy hozzáférjen az Ön fizikai állapotát – például a pulzusszámát – figyelő érzékelők adataihoz." "naptári események és bizalmas információk beolvasása" "Lehetővé teszi az alkalmazás számára a táblagépén tárolt összes naptári esemény beolvasását, beleértve az ismerősök vagy munkatársak eseményeit is. Az alkalmazás így megoszthatja vagy elmentheti az Ön naptáradatait azok titkos vagy bizalmas jellegétől függetlenül." @@ -336,15 +336,15 @@ "Lehetővé teszi az alkalmazás számára a telefonon módosítható események hozzáadását, törlését vagy módosítását, beleértve az ismerősök vagy munkatársak eseményeit is. Az engedéllyel rendelkező alkalmazás üzeneteket küldhet, amelyek úgy tűnhetnek, hogy a naptár tulajdonosától származnak, illetve módosíthatják az eseményeket a tulajdonosok tudta nélkül." "további helyszolgáltatói parancsok elérése" "Lehetővé teszi az alkalmazás számára további helyszolgáltatói parancsok elérését. Ezáltal az alkalmazás beavatkozhat a GPS vagy más helyforrások működésébe." - "pontos (GPS- és hálózatalapú) tartózkodási hely" + "hozzáférés a pontos (GPS- és hálózatalapú) helyadatokhoz" "Lehetővé teszi az alkalmazás számára a pontos tartózkodási helyének lekérését a GPS és a hálózati helyforrások, így például az adótornyok és a Wi-Fi hálózatok adatainak felhasználásával. A helyszolgáltatásokat be kell kapcsolni, és az adatoknak elérhetőknek kell lenniük az eszközén ahhoz, hogy az alkalmazás használhassa őket. Használatukkal az alkalmazások meghatározhatják az Ön tartózkodási helyét, és az akkumulátort is fokozottan fogyaszthatják." - "hozzávetőleges (hálózatalapú) tartózkodási hely" + "hozzáférés a hozzávetőleges (hálózatalapú) helyadatokhoz" "Lehetővé teszi az alkalmazás számára a körülbelüli tartózkodási helyének lekérését. A helymeghatározás a hálózati helyforrások, így például az adótornyok és a Wi-Fi hálózatok adatainak felhasználásával történik. A helyszolgáltatásokat be kell kapcsolni, és az adatoknak elérhetőknek kell lenniük az eszközén ahhoz, hogy az alkalmazás használhassa őket. Használatukkal az alkalmazások meghatározhatják az Ön hozzávetőleges tartózkodási helyét." "hangbeállítások módosítása" "Lehetővé teszi az alkalmazás számára az általános hangbeállítások, például a hangerő és a használni kívánt kimeneti hangszóró módosítását." "hanganyag rögzítése" "Lehetővé teszi az alkalmazás számára a mikrofonnal való hangfelvételt.Az engedéllyel rendelkező alkalmazás az Ön jóváhagyása nélkül, bármikor rögzíthet hanganyagot." - "SIM-kommunikáció" + "parancsok küldése a SIM-kártyára" "Engedélyezi, hogy az alkalmazás parancsokat küldjön a SIM kártyára. Ez rendkívül veszélyes lehet." "fotók és videók készítése" "Lehetővé teszi az alkalmazás számára, hogy a fényképezőgéppel fotókat és videókat készítsen. Az engedéllyel rendelkező alkalmazás bármikor, az Ön jóváhagyása nélkül használhatja a fényképezőgépet." @@ -382,7 +382,7 @@ "Lehetővé teszi az alkalmazás számára a telefon által ismert hálózatok listájának lekérését; beleértve a telepített alkalmazások által létrehozott bármely fiókot." "hálózati kapcsolatok megtekintése" "Lehetővé teszi az alkalmazás számára, hogy hozzáférjen hálózati kapcsolatokra vonatkozó információkhoz, például melyek létező hálózatok, és melyek vannak csatlakoztatva." - "teljes hálózati hozzáférés" + "teljes hálózati hozzáférés" "Lehetővé teszi az alkalmazás számára hálózati szoftvercsatornák létrehozását, valamint egyéni hálózati protokollok használatát. A böngésző és egyéb alkalmazások lehetővé teszik adatok küldését az internetre, így ez az engedély nem szükséges az internetre való adatküldéshez." "hálózati csatlakoztathatóság módosítása" "Lehetővé teszi az alkalmazás számára a hálózati csatlakoztathatóság állapotának módosítását." @@ -402,7 +402,7 @@ "Lehetővé teszi az alkalmazás számára, hogy konfigurálja a helyi Bluetooth telefont, valamint hogy távoli eszközöket fedezzen fel és párosítson." "WiMAX-kapcsolódás és a kapcsolat bontása" "Lehetővé teszi az alkalmazás számára, hogy ellenőrizze, a WiMax engedélyezve van-e, valamint hogy információt gyűjtsön a csatlakoztatott WiMax-hálózatokról." - "WiMAX-állapot módosítása" + "WiMAX-állapot módosítása" "Lehetővé teszi az alkalmazás számára, hogy a táblagépet csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla." "Lehetővé teszi az alkalmazás számára a tévé WiMAX-hálózatokhoz való csatlakoztatását, illetve az ilyen hálózatokról való leválasztását." "Lehetővé teszi az alkalmazás számára, hogy a telefont csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla." @@ -485,7 +485,7 @@ "Lehetővé teszi, hogy az alkalmazás módosítsa az érintőképernyő kalibrációs paramétereit. A normál alkalmazásoknál erre elvileg soha nincs szükség." "DRM-tanúsítványokhoz való hozzáférés" "Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szükségük." - "Android Beam-átviteli állapot fogadása" + "android Beam-átviteli állapot fogadása" "Lehetővé teszi az alkalmazás számára a folyamatban lévő Android Beam-átvitelekről szóló információk fogadását" "DRM-tanúsítványok eltávolítása" "Lehetővé teszi, hogy az alkalmazás eltávolítsa a DRM-tanúsítványokat. A normál alkalmazásoknak erre soha nincs szükségük." @@ -643,11 +643,11 @@ "Írja be a PIN kódot" "Írja be a PUK kódot, majd az új PIN kódot" "PUK kód" - "Új PIN kód" + "Új PIN-kód" "Érintsen jelszó megadásához" "A feloldáshoz írja be a jelszót" "Feloldáshoz írja be a PIN kódot" - "Helytelen PIN kód." + "Helytelen PIN-kód." "A feloldáshoz nyomja meg a Menü, majd a 0 gombot." "Segélyhívó szám" "Nincs szolgáltatás." @@ -699,7 +699,7 @@ "Fiók feloldása" "Túl sok mintarajzolási próbálkozás" "A feloldáshoz jelentkezzen be Google-fiókjával." - "Felhasználónév (e-mail cím)" + "Felhasználónév (e-mail-cím)" "Jelszó" "Bejelentkezés" "Érvénytelen felhasználónév vagy jelszó." @@ -985,7 +985,7 @@ "Feladó:" "Címzett:" "Adja meg a szükséges PIN kódot:" - "PIN kód:" + "PIN-kód:" "A táblagép ideiglenesen lecsatlakozik a Wi-Fi hálózatról, míg a(z) %1$s eszközhöz csatlakozik" "A tévé ideiglenesen lekapcsolódik a Wi-Fi-hálózatról addig, amíg a(z) %1$s eszközhöz csatlakozik." "A telefon ideiglenesen kilép a Wi-Fi hálózatról, míg a(z) %1$s eszközhöz csatlakozik." @@ -1091,11 +1091,11 @@ "Formázás…" "Nincs behelyezve" "Nincs megfelelő tevékenység." - "Médiafájlok kimenetének irányítása" + "médiafájlok kimenetének irányítása" "Lehetővé teszi az alkalmazás számára, hogy más külső eszközökre irányítsa a médiafájlok lejátszását." - "Telepítési munkamenetek olvasása" + "telepítési munkamenetek olvasása" "Engedélyezi az alkalmazásnak a telepítési munkamenetek olvasását. Ezáltal részleteket kaphat az egyes csomagok éppen folyamatban lévő telepítéséről." - "Telepítőcsomagok kérése" + "telepítőcsomagok kérése" "Lehetővé teszi az alkalmazás számára csomagok telepítésének kérését." "Érintse meg kétszer a nagyítás beállításához" "Nem sikerült hozzáadni a modult." @@ -1280,24 +1280,24 @@ "Elfelejtett minta" "Helytelen minta" "Helytelen jelszó" - "Helytelen PIN kód" + "Helytelen PIN-kód" "Próbálkozzon újra %1$d másodperc múlva." "Rajzolja le a mintát" "Adja meg a SIM kártya PIN kódját" "Adja meg a PIN kódot" "Írja be a jelszót" "A SIM kártya le van tiltva. A folytatáshoz adja meg a PUK kódot. A részletekért vegye fel a kapcsolatot szolgáltatójával." - "Kívánt PIN kód megadása" - "Kívánt PIN kód megerősítése" + "Kívánt PIN-kód megadása" + "Kívánt PIN-kód megerősítése" "SIM kártya feloldása..." - "Helytelen PIN kód." + "Helytelen PIN-kód." "4–8 számjegyű PIN kódot írjon be." "A PUK kód 8 karakter hosszú kell, hogy legyen." "Adja meg újra a helyes PUK kódot. Az ismételt próbálkozással véglegesen letiltja a SIM kártyát." "A PIN kódok nem egyeznek." "Túl sok mintarajzolási próbálkozás" "A feloldáshoz jelentkezzen be Google-fiókjával." - "Felhasználónév (e-mail cím)" + "Felhasználónév (e-mail-cím)" "Jelszó" "Bejelentkezés" "Érvénytelen felhasználónév vagy jelszó." @@ -1417,15 +1417,15 @@ "A nyomtatási szolgáltatás nincs bekapcsolva" "A(z) %s szolgáltatás telepítve" "Koppintson az engedélyezéshez" - "Rendszergazdai PIN kód megadása" - "PIN kód megadása" + "Rendszergazdai PIN-kód megadása" + "PIN-kód megadása" "Helytelen" - "Jelenlegi PIN kód" - "Új PIN kód" - "Új PIN kód megerősítése" - "PIN kód létrehozása a korlátozások módosításához" + "Jelenlegi PIN-kód" + "Új PIN-kód" + "Új PIN-kód megerősítése" + "PIN-kód létrehozása a korlátozások módosításához" "A PIN kódok nem egyeznek. Próbálja újra." - "A PIN kód túl rövid. Legalább 4 számjegyből kell állnia." + "A PIN-kód túl rövid. Legalább 4 számjegyből kell állnia." Próbálja újra %d másodperc múlva Próbálja újra 1 másodperc múlva @@ -1448,7 +1448,7 @@ "Az alkalmazás rögzítve van: a rögzítés feloldása nem engedélyezett ezen az eszközön." "Képernyő rögzítve" "Képernyő rögzítése feloldva" - "PIN kód kérése a rögzítés feloldásához" + "PIN-kód kérése a rögzítés feloldásához" "Feloldási minta kérése a rögzítés feloldásához" "Jelszó kérése a rögzítés feloldásához" "A rendszergazda telepítette" diff --git a/core/res/res/values-hy-rAM-watch/strings.xml b/core/res/res/values-hy-rAM-watch/strings.xml index 265268e894568..5aeab8ceabde5 100644 --- a/core/res/res/values-hy-rAM-watch/strings.xml +++ b/core/res/res/values-hy-rAM-watch/strings.xml @@ -21,4 +21,5 @@ "Հավելված %1$d՝ %2$d-ից:" + "Սենսորներ" diff --git a/core/res/res/values-hy-rAM/cm_strings.xml b/core/res/res/values-hy-rAM/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-hy-rAM/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index 1f85bf37df007..71112fa1ad321 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -254,7 +254,7 @@ "Ներառում է անձնական տվյալներ, ինչպիսիք են վարկային քարտերի համարները և գաղտնաբառերը:" "անջատել կամ փոփոխել կարգավիճակի գոտին" "Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:" - "կարգավիճակի գոտի" + "լինել կարգավիճակի գոտի" "Թույլ է տալիս հավելվածին կարգավիճակի գոտին լինել:" "ընդլայնել կամ ետ ծալել կարգավիճակի գոտին" "Թույլ է տալիս ծրագրին ընդլայնել կամ ետ ծալել կարգավիճակի գոտին:" @@ -282,7 +282,7 @@ "Թույլ է տալիս հավելվածին ստանալ և գործարկել WAP հաղորդագրությունները: Այս թույլտվությունը ներառում է ձեզ ուղարկված հաղորդագրությունները հետևելու կամ ջնջելու կարողությունը` առանց ձեր տեսնելու:" "առբերել աշխատող հավելվածները" "Թույլ է տալիս հավելվածին առբերել մանրամասն տեղեկություններ առկա և վերջերս աշխատող առաջադրանքների մասին: Սա կարող է թույլ տալ հավելվածին հայտնաբերել անձնական տեղեկություններ այլ հավելվածների վերաբերյալ:" - "Պրոֆիլների և սարքի սեփականատերերի կառավարում" + "կառավարել պրոֆիլները և սարքի սեփականատերերին" "Թույլ է տալիս հավելվածներին սահմանել պրոֆիլների սեփականատերերին և սարքի սեփականատիրոջը:" "վերադասավորել աշխատող հավելվածները" "Թույլ է տալիս հավելվածին փոխանցել առաջադրանքները առջևք և հետնաշերտ: Հավելվածը կարող է սա անել առանց ձեր ներածման:" @@ -324,7 +324,7 @@ "Թույլ է տալիս հավելվածին փոփոխել ձեր գրասալիկի զանգերի մատյանը, այդ թվում` մուտքային և ելքային զանգերի մասին տվյալները: Վնասարար հավելվածները կարող են սա օգտագործել` ձեր զանգերի մատյանը ջնջելու կամ փոփոխելու համար:" "Թույլ է տալիս հավելվածին փոփոխել հեռուստացույցի զանգերի մատյանը, այդ թվում` մուտքային և ելքային զանգերի մասին տվյալները: Վնասարար հավելվածները կարող են սա օգտագործել` ձեր զանգերի մատյանը ջնջելու կամ փոփոխելու համար:" "Թույլ է տալիս հավելվածին փոփոխել ձեր հեռախոսի զանգերի մատյանը, այդ թվում` մուտքային և ելքային զանգերի մասին տվյալները: Վնասարար հավելվածները կարող են սա օգտագործել` ձեր զանգերի մատյանը ջնջելու կամ փոփոխելու համար:" - "մարմնի սենսորներ (օր.` սրտի)" + "օգտագործել մարմնի սենսորները (օրինակ` սրտի կծկումների հաճախականության չափիչ)" "Հավելվածին թույլ է տալիս մուտք ունենալ սենսորների տվյալներին, որոնք վերահսկում են ձեր ֆիզիկական վիճակը, օրինակ՝ ձեր սրտի զարկերը:" "կարդալ օրացուցային իրադարձությունները և գաղտնի տեղեկությունները" "Թույլ է տալիս հավելվածին կարդալ ձեր գրասալիկում պահված բոլոր օրացուցային իրադարձությունները, այդ թվում` ընկերների կամ գործընկերների: Սա կարող է թույլ տալ հավելվածին տարածել կամ պահել ձեր օրացուցային տվյալները` անկախ գաղտնիությունից կամ զգայունությունից:" @@ -336,15 +336,15 @@ "Թույլ է տալիս հավելվածին ավելացնել, հեռացնել, փոխել այն իրադարձությունները, որոնք կարող եք փոփոխել ձեր հեռախոսից, այդ թվում` ընկերների կամ գործընկերների: Սա կարող է թույլ տալ հավելվածին ուղարկել հաղորդագրություններ, որոնք իբրև գալիս են օրացույցի սեփականատիրոջից, կամ փոփոխել իրադարձությունները` առանց սեփականատիրոջ իմացության:" "օգտագործել տեղադրություն տրամադրող հավելվյալ հրամաններ" "Ծրագրին թույլ է տալիս օգտագործել տեղադրության մասին տվյալների աղբյուրների կառավարման լրացուցիչ հրահանգներ: Սա կարող է ծրագրին թույլ տալ միջամտել GPS-ի կամ տեղադրության մասին տվյալների այլ աղբյուրների գործառույթներին:" - "ճշգրիտ վայրը (ըստ GPS-ի և ցանցի)" + "օգտագործել ճշգրիտ տեղադրությունը (GPS և ցանցային)" "Թույլ է տալիս հավելվածին ստանալ ձեր ճշգրիտ տեղադրությունը` օգտագործելով Գլոբալ Դիրքավորման Համակարգը (GPS) կամ ցանցային տեղանքի աղբյուրները, ինչպես օրինակ` բջջային աշտարակները և Wi-Fi-ը: Այս տեղադրության ծառայությունները պետք է միացվեն և հասանելի լինեն ձեր սարքի համար, որպեսզի հավելվածն օգտագործի դրանք: Հավելվածները կարող են սա օգտագործել` որոշելու համար ձեր գտնվելու վայրը և կարող են սպառել մարտկոցի լրացուցիչ լիցք:" - "մոտավոր տեղադրությունը (ցանցային)" + "օգտագործել մոտավոր տեղադրությունը (ցանցային)" "Թույլ է տալիս հավելվածին ստանալ ձեր մոտավոր տեղադրությունը: Այս տեղադրությունը ստացվում է տեղանքի ծառայությունների կողմից, ինչպես օրինակ` բջջային աշտարակներից և Wi-Fi-ից: Այս տեղանքի ծառայությունները պետք է միացված և հասանելի լինեն ձեր սարքին, որպեսզի հավելվածն օգտագործի դրանք: Հավելվածները կարող են սա օգտագործել` ձեր մոտավոր գտնվելու վայրը որոշելու համար:" "փոխել ձեր աուդիո կարգավորումները" "Թույլ է տալիս հավելվածին փոփոխել ձայնանյութի գլոբալ կարգավորումները, ինչպես օրինակ` ձայնը և թե որ խոսափողն է օգտագործված արտածման համար:" "ձայնագրել ձայնանյութ" "Թույլ է տալիս հավելվածին բարձրախոսով ձայնագրել ձայնանյութ: Այս թույլտվությունը հնարավորություն է տալիս հավելվածին ձայնանյութ ձայնագրել ցանկացած ժամանակ` առանց ձեր հաստատման:" - "SIM հաղորդակցում" + "ուղարկել հրամաններ SIM քարտին" "Թույլ է տալիս հավելվածին հրամաններ ուղարկել SIM-ին: Սա շատ վտանգավոր է:" "լուսանկարել և տեսանկարել" "Թույլ է տալիս հավելվածին ֆոտոխցիկով լուսանկարել և տեսանկարել: Այս թույլտվությունը հնարավորություն է տալիս հավելվածին օգտագործել ֆոտոխցիկը ցանկացած ժամանակ` առանց ձեր հաստատման:" @@ -382,7 +382,7 @@ "Թույլ է տալիս հավելվածին ստանալ հեռախոսի կողմից ճանաչված հաշիվների ցանկը: Սա կարող է ներառել ցանկացած հաշիվ, որ ստեղծվել է ձեր տեղադրած հավելվածների կողմից:" "դիտել ցանցային միացումները" "Թույլ է տալիս հավելվածին տեսնել ցանցային կապերի մասին տեղեկություններ, ինչպես օրինակ, թե ինչ կապեր կան և որոնք են միացված:" - "լրիվ ցանցային մուտք" + "ունենալ ամբողջական ցանցային մուտք" "Թույլ է տալիս հավելվածին ստեղծել ցանցային բնիկներ և օգտագործել հատուկ ցանցային պրոտոկոլներ: Զննարկիչը և այլ հավելվածները միջոցներ են տրամադրում ինտերնետին տվյալներ ուղարկելու համար, ուստի այս թույլտվությունը չի պահանջվում ինտերնետին տվյալներ ուղարկելու համար:" "փոխել ցանցի կապը" "Թույլ է տալիս հավելվածին փոխել ցանցի միացման կարգավիճակը:" @@ -402,7 +402,7 @@ "Թույլ է տալիս հավելվածին կարգավորել տեղային Bluetooth հեռախոսը և հայտնաբերել ու զուգակցվել հեռակա սարքերի հետ:" "միանալ WiMAX-ին և անջատվել դրանից" "Թույլ է տալիս հավելվածին պարզել, արդյոք WiMAX-ը միացված է և ցանկացած միացված WiMAX ցանցի մասին տեղեկություններ:" - "Փոխել WiMAX-ի կարգավիճակը" + "փոխել WiMAX-ի կարգավիճակը" "Թույլ է տալիս հավելվածին գրասալիկը միացնել WiMAX ցանցին և անջատվել այդ ցանցից:" "Թույլ է տալիս հավելվածին կապակցել հեռուստացույցը և ապակապակցել այն WiMAX ցանցերից:" "Թույլ է տալիս հավելվածին հեռախոսը միացնել WiMAX ցանցին և անջատել այդ ցանցից:" @@ -485,7 +485,7 @@ "Թույլ է տալիս ծրագրին փոփոխել հպէկրանի չափաբերման կարգավորումները: Սովորական ծրագրերի համար երբեք պետք չի գալու:" "DRM հավաստագրերի մատչում" "Ծրագրին թույլ է տալիս տրամադրել և օգտագործել DRM վկայագրեր: Սովորական ծրագրերի համար երբեք պետք չի գալիս:" - "Ստանալ Android Beam-ով փոխանցման կարգավիճակը" + "ստանալ Android Beam-ով փոխանցման կարգավիճակը" "Ծրագրին թույլ է տալիս ստանալ Android Beam-ով ընթացիկ փոխանցումների մասին տեղեկատվություն:" "հեռացնել DRM վկայագրեր" "Ծրագրին թույլ է տալիս հեռացնել DRM վկայագրեր: Սովորական ծրագրերի համար երբեք պետք չի գալիս:" @@ -1091,11 +1091,11 @@ "Ձևաչափում…" "Տեղադրված չէ" "Համընկնող գործունեություններ չգտնվեցին:" - "Երթուղել մեդիա արտածումը" + "երթուղել մեդիա արտածումը" "Թույլ է տալիս հավելվածին մեդիա արտածումը երթուղել այլ արտաքին սարքեր:" - "Կարդալ տեղադրման աշխատաշրջանները" + "կարդալ տեղադրման աշխատաշրջանները" "Ծրագրին թույլ է տալիս կարդալ տեղադրման աշխատաշրջանները: Սա թույլ է տալիս տեղեկանալ փաթեթների ակտիվ տեղադրումների մանրամասներին:" - "Պահանջել փաթեթների տեղադրում" + "պահանջել տեղադրման փաթեթներ" "Թույլ է տալիս հավելվածին պահանջել փաթեթների տեղադրումը:" "Հպեք երկու անգամ` դիտափոխման կարգավորման համար" "Չհաջողվեց վիջեթ ավելացնել:" diff --git a/core/res/res/values-in-watch/strings.xml b/core/res/res/values-in-watch/strings.xml index 947a7f19797cb..762c9e62e2bc3 100644 --- a/core/res/res/values-in-watch/strings.xml +++ b/core/res/res/values-in-watch/strings.xml @@ -21,4 +21,5 @@ "Aplikasi %1$d dari %2$d." + "Sensor" diff --git a/core/res/res/values-in/cm_strings.xml b/core/res/res/values-in/cm_strings.xml new file mode 100644 index 0000000000000..bfe62e4a5745e --- /dev/null +++ b/core/res/res/values-in/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Tangkap layar + + terima SMS yang dilindungi + + Izinkan aplikasi untuk menerima SMS yang dilindungi. + + modifikasi daftar SMS yang dilindungi + + Izinkan aplikasi untuk mengubah daftar alamat SMS yang dilindungi. + + Keamanan + + Izin terkait dengan informasi keamanan perangkat. + + baca daftar hitam telepon + + Izinkan aplikasi untuk membaca informasi tentang nomor telepon yang diblokir untuk panggilan atau pesan. + + ubah daftar hitam telepon + + Izinkan aplikasi untuk mengubah nomor telepon yang diblokir untuk panggilan masuk atau pesan. + + atur gambar latar pengaman tombol + + Izinkan aplikasi untuk mengubah gambar latar layar kunci. + + Mulai ulang + + Saat ini + + + Mulai ulang + + Recovery + + Bootloader + + Download + + Mulai ulang cepat + + Mulai ulang + + Tablet anda akan dimulai ulang. + Ponsel anda akan mulai ulang. + + Memulai ulang\u2026 + + Aplikasi dimatikan + + ADB melalui jaringan diaktifkan + + ADB melalui USB & jaringan diaktifkan + + Sentuh untuk menonaktifkan debugging. + + ADB - %1$s + Jaringan & USB + USB + Jaringan + + Mencegah memulai aplikasi + + %s tidak terinstal + + Prioritas + Tidak ada + + Wi-Fi hotspot dinonatifkan karena perubahan langganan SIM + + Nonaktifkan Wi-Fi + + Aktifkan atau nonaktifkan Penjaga Privasi + Izinkan aplikasi untuk mengubah apakah applikasi lain berjalan dengan Penjaga Privasi. Ketika aplikasi sedang berjalan dengan Penjaga Privasi, aplikasi tidak akan memiliki akses untuk data pribadi seperti kontak, daftar panggilan atau pesan. + Penjaga Privasi aktif + %1$s tidak akan dapat mengakses data pribadi + Penjaga Privasi + %1$s ingin %2$s. + + Ingat pilihan saya + + mengakses kamera + mengakses lokasi Anda + membaca notifikasi Anda + Aktifkan VPN + mulai pada saat dinyalakan + hapus log panggilan Anda + hapus kontak Anda + hapus pesan MMS Anda + hapus pesan SMS Anda + menarik jendela di atas + dapatkan statistik penggunaan aplikasi + jaga perangkat Anda tetap bangun + membuat panggilan telepon + memperbarui kalender Anda + memperbarui daftar panggilan + memodifikasi clipboard + memperbarui kontak Anda + memperbarui pengaturan sistem + diam/mengaktifkan suara mikrofon + mainkan audio + mengirim pemberitahuan + proyek media + membaca kalender Anda + membaca log panggilan + membaca clipboard + membaca kontak Anda + membaca pesan MMS Anda + membaca pesan SMS Anda + menerima pesan SMS + merekam audio + mengirim pesan MMS + mengirim pesan SMS + mulai pada saat dinyalakan + tampilkan pesan toast + hidup/matikan Bluetooth + hidup/matikan data seluler + hidup/matikan NFC + hidup/matikan Wi-Fi + mengatur volume alarm + mengatur fokus audio + mengatur volume Bluetooth + mengatur volume utama + menggunakan tombol media + mengatur volume media + mengatur volume pemberitahuan + mengatur volume nada dering + gunakan tanggapan sentuhan + mengatur volume panggilan suara + tulis pesan MMS + tulis pesan SMS + gunakan sidik jari + menambahkan pesan suara + akses status ponsel + memindai jaringan Wi-Fi + mengubah wallpaper + gunakan struktur bantuan + ambil tangkapan layar + menggunakan sensor badan + baca siaran seluler + memalsukan lokasi Anda + membaca penyimpanan eksternal + menulis penyimpanan eksternal + aktifkan layar + dapatkan akun perangkat + ubah status Wi-Fi + dapatkan akses root + + Untuk melepas sematan layar ini, sentuh dan tahan tombol Kembali. + + Tidak ada perangkat yang terhubung + %1$s perangkat yang terhubung + %1$s perangkat yang terhubung + + + + Aktivitas peluncuran diblokir + %1$s dilindungi dari peluncuran. Ketuk untuk mengautentikasi dan meluncurkan aplikasi. + + Baterai telah terisi penuh + Lepaskan perangkat dari pengisi daya agar meningkatkan umur baterai. + + set ulang statistik baterai + + Mengizinkan aplikasi untuk set ulang data penggunaan baterai rendah yang sekarang. + + Kartu SIM telah diganti + Ketuk untuk mengatur preferensi standar kartu SIM + diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 10214c5b478e7..8f94325ac35ef 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -254,7 +254,7 @@ "Meliputi data pribadi seperti nomor kartu kredit dan sandi." "nonaktifkan atau ubah bilah status" "Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem." - "bilah status" + "jadikan bilah status" "Mengizinkan apl menjadi bilah status." "luaskan/ciutkan bilah status" "Mengizinkan apl memperluas atau menciutkan bilah status." @@ -282,7 +282,7 @@ "Memungkinkan aplikasi menerima dan memproses pesan WAP. Izin ini mencakup kemampuan untuk memantau atau menghapus pesan yang dikirim kepada Anda tanpa menunjukkannya kepada Anda." "mengambil apl yang berjalan" "Memungkinkan aplikasi mengambil informasi tentang tugas yang dijalankan saat ini dan baru-baru ini. Izin ini memungkinkan aplikasi menemukan informasi tentang aplikasi mana yang digunakan pada perangkat." - "Mengelola pemilik profil dan perangkat" + "kelola pemilik profil dan perangkat" "Mengizinkan aplikasi menyetel pemilik profil dan pemilik perangkat" "menyusun ulang apl yang berjalan" "Memungkinkan aplikasi memindah tugas ke latar depan dan latar belakang. Aplikasi dapat melakukannya tanpa masukan dari Anda." @@ -324,7 +324,7 @@ "Memungkinkan apl memodifikasi log panggilan tablet Anda, termasuk data tentang panggilan masuk dan keluar. Apl berbahaya dapat menggunakan ini untuk menghapus atau memodifikasi log panggilan Anda." "Mengizinkan aplikasi untuk memodifikasi log panggilan TV, termasuk data tentang panggilan masuk dan keluar. Aplikasi berbahaya mungkin menggunakan ini untuk menghapus atau memodifikasi log panggilan." "Memungkinkan apl memodifikasi log panggilan ponsel Anda, termasuk data tentang panggilan masuk dan keluar. Apl berbahaya dapat menggunakan ini untuk menghapus atau memodifikasi log panggilan Anda." - "sensor tubuh (misal: monitor detak jantung)" + "akses sensor tubuh (misalnya, monitor detak jantung)" "Mengizinkan aplikasi untuk mengakses data dari sensor yang memantau kondisi fisik Anda, seperti denyut jantung." "baca acara kalender serta informasi rahasia" "Memungkinkan aplikasi membaca semua acara kalender yang tersimpan di tablet Anda, termasuk milik teman atau rekan kerja. Izin ini memungkinkan aplikasi berbagi atau menyimpan data kalender Anda, terlepas dari kerahasiaan atau sensitivitas." @@ -336,15 +336,15 @@ "Memungkinkan aplikasi menambahkan, menghapus, mengubah acara yang dapat Anda ubah pada ponsel, termasuk acara teman atau rekan kerja. Izin ini memungkinkan aplikasi mengirim pesan yang kelihatannya berasal dari pemilik kalender, atau mengubah acara tanpa sepengetahuan pemilik." "akses perintah penyedia lokasi ekstra" "Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Tindakan ini memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain." - "lokasi akurat (berbasis jaringan dan GPS)" + "akses lokasi akurat (berbasis jaringan dan GPS)" "Mengizinkan aplikasi memperoleh lokasi Anda yang akurat menggunakan Sistem Pemosisian Global (GPS) atau sumber lokasi jaringan, misalnya menara seluler dan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia untuk perangkat Anda agar aplikasi dapat menggunakannya. Aplikasi dapat menggunakan ini untuk menentukan perkiraan tempat Anda berada dan dapat menghabiskan daya baterai tambahan." - "perkiraan lokasi (berbasis jaringan)" + "akses perkiraan lokasi (berbasis jaringan)" "Mengizinkan aplikasi untuk mendapatkan perkiraan lokasi Anda. Lokasi ini diperoleh dengan layanan lokasi yang menggunakan sumber lokasi jaringan, misalnya menara seluler dan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia untuk perangkat Anda agar aplikasi dapat menggunakannya. Aplikasi dapat menggunakan ini untuk menentukan perkiraan tempat Anda berada." "ubah setelan audio Anda" "Memungkinkan aplikasi mengubah setelan audio global, misalnya volume dan pengeras suara mana yang digunakan untuk keluaran." "rekam audio" "Memungkinkan aplikasi merekam audio dengan mikrofon. Izin ini memungkinkan aplikasi merekam audio kapan saja tanpa konfirmasi Anda." - "komunikasi sim" + "kirimkan perintah ke SIM" "Mengizinkan aplikasi mengirim perintah ke SIM. Ini sangat berbahaya." "ambil gambar dan video" "Memungkinkan aplikasi mengambil gambar dan video dengan kamera. Izin ini memungkinkan aplikasi menggunakan kamera kapan saja tanpa konfirmasi Anda." @@ -382,7 +382,7 @@ "Memungkinkan aplikasi mendapatkan daftar akun yang dikenal oleh ponsel. Ini mungkin termasuk akun yang dibuat oleh aplikasi yang telah Anda pasang." "lihat sambungan jaringan" "Memungkinkan aplikasi melihat informasi tentang sambungan jaringan, misalnya jaringan yang ada dan tersambung." - "akses jaringan penuh" + "dapatkan akses jaringan penuh" "Memungkinkan aplikasi membuat soket jaringan dan menggunakan protokol jaringan khusus. Browser dan aplikasi lain menyediakan sarana untuk mengirim data ke internet sehingga izin ini tidak diperlukan untuk mengirim data ke internet." "ubah konektivitas jaringan" "Mengizinkan apl mengubah keadaan konektivitas jaringan." @@ -402,7 +402,7 @@ "Mengizinkan apl mengonfigurasi ponsel Bluetooth lokal, dan menemukan serta menyandingkan dengan perangkat jarak jauh." "sambungkan dan putuskan dari WiMAX" "Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang tersambung." - "Ubah status WiMAX" + "Ganti status WiMAX" "Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX." "Mengizinkan aplikasi untuk menghubungkan TV ke dan memutuskan hubungan TV dari jaringan WiMAX." "Memungkinkan aplikasi menyambungkan ponsel ke dan memutus ponsel dari jaringan WiMAX." @@ -485,7 +485,7 @@ "Memungkinkan aplikasi mengubah parameter kalibrasi layar sentuh. Tidak diperlukan oleh aplikasi normal." "mengakses sertifikat DRM" "Memungkinkan aplikasi menyediakan dan menggunakan sertifikat DRM. Tidak pernah dibutuhkan untuk aplikasi normal." - "Menerima status transfer Android Beam" + "terima status transfer Android Beam" "Memungkinkan aplikasi ini menerima informasi tentang transfer Android Beam saat ini" "membuang serifikat DRM" "Memungkinkan aplikasi membuang sertifikat DRM. Tidak pernah dibutuhkan untuk aplikasi normal." @@ -1091,11 +1091,11 @@ "Menformat..." "Tidak dicolokkan" "Tidak ditemukan aktivitas yang sesuai." - "Menentukan rute keluaran media" + "tentukan rute keluaran media" "Memungkinkan aplikasi menentukan rute keluaran media ke perangkat eksternal lainnya." - "Membaca sesi pemasangan" + "baca sesi pemasangan" "Memungkinkan aplikasi membaca sesi pemasangan. Tindakan ini memungkinkannya melihat detail tentang pemasangan paket aktif." - "Minta pasang paket" + "minta pasang paket" "Mengizinkan aplikasi meminta pemasangan paket." "Sentuh dua kali untuk mengontrol perbesar/perkecil" "Tidak dapat menambahkan widget." diff --git a/core/res/res/values-is-rIS-watch/strings.xml b/core/res/res/values-is-rIS-watch/strings.xml index cb6da5c036e60..74acce690a5be 100644 --- a/core/res/res/values-is-rIS-watch/strings.xml +++ b/core/res/res/values-is-rIS-watch/strings.xml @@ -21,4 +21,5 @@ "Forrit %1$d af %2$d." + "Skynjarar" diff --git a/core/res/res/values-is-rIS/cm_strings.xml b/core/res/res/values-is-rIS/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-is-rIS/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml index 76c52ccb3deec..b903f7715f72b 100644 --- a/core/res/res/values-is-rIS/strings.xml +++ b/core/res/res/values-is-rIS/strings.xml @@ -254,7 +254,7 @@ "Felur í sér persónuleg gögn á borð við kreditkortanúmer og aðgangsorð." "slökkva á eða breyta stöðustiku" "Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn." - "stöðustika" + "vera stöðustikan" "Leyfir forriti að vera stöðustikan." "stækka/minnka stöðustiku" "Leyfir forriti að stækka og minnka stöðustikuna." @@ -282,7 +282,7 @@ "Leyfir forriti að taka á móti og vinna úr WAP-skilaboðum. Þessi heimild felur í sér möguleikann á að fylgjast með eða eyða skilaboðum sem þér eru send án þess að birta þér þau." "sækja forrit í gangi" "Leyfir forriti að sækja upplýsingar um opin forrit og forrit sem nýlega hafa verið opin. Þetta getur gert forritinu kleift að nálgast upplýsingar um forritin sem notuð eru í tækinu." - "Stjórna eigendum sniða og tækis" + "stjórna eigendum sniða og tækja" "Leyfir forritum að stilla eigendur sniða og eiganda tækisins." "endurraða forritum í gangi" "Leyfir forriti að færa verk á milli forgrunns og bakgrunns. Forritið getur gert þetta án inngrips frá þér." @@ -324,7 +324,7 @@ "Leyfir forriti að breyta símtalaskrá spjaldtölvunnar, þ. á m. gögnum um hringd og móttekin símtöl. Spilliforrit geta notað þetta til að eyða eða breyta símtalaskránni." "Leyfir forriti að breyta símtalaskrá sjónvarpsins, þ. á m. gögnum um hringd og móttekin símtöl. Spilliforrit geta notað þetta til að eyða eða breyta símtalaskránni." "Leyfir forriti að breyta símtalaskrá símans, þ. á m. gögnum um hringd og móttekin símtöl. Spilliforrit geta notað þetta til að eyða eða breyta símtalaskránni." - "líkamsskynjarar (s.s. hjartsláttarmælar)" + "fá aðgang að líkamsskynjurum (s.s. hjartsláttarmælum)" "Veitir forritinu aðgang að gögnum frá skynjurum sem fylgjast með líkamsstarfsemi þinni, svo sem hjartslætti." "lesa dagatalsviðburði og trúnaðarupplýsingar" "Leyfir forriti að lesa alla dagatalsviðburði sem vistaðir eru í spjaldtölvunni, þ. á m. þá sem vinir eða samstarfsmenn eiga. Þetta getur gert forritinu kleift að deila dagatalsgögnunum þínum burtséð frá því hvort þau innihalda trúnaðargögn eða viðkvæmar upplýsingar." @@ -336,15 +336,15 @@ "Leyfir forriti að bæta við, fjarlægja og breyta viðburðum sem hægt er að breyta í símanum, þ. á m. viðburðum sem vinir eða samstarfsmenn eiga. Þetta getur gert forritinu kleift að senda skilaboð sem virðast koma frá eigendum viðburðarins eða breyta viðburðum án vitundar eigenda þeirra." "aðgangur að viðbótarskipunum staðsetningarveitu" "Leyfir forriti að fá aðgang að fleiri skipunum staðsetningarveitu. Þetta getur gert forritinu kleift að hafa áhrif á virkni GPS og annars staðsetningarbúnaðar." - "nákvæm staðsetning (frá GPS og símakerfi)" + "fá aðgang að nákvæmri staðsetningu (frá GPS og símkerfi)" "Leyfir forriti að sjá nákvæma staðsetningu þína með hjálp GPS-kerfis eða staðsetningarbúnaðar sem byggir á netkerfum á borð við farsímasenda og Wi-Fi. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg tækinu til að forritið geti notað hana. Forrit geta notað þjónustuna til að áætla staðsetningu þína og kunna að ganga hraðar á rafhlöðuna." - "gróflega áætluð staðsetning (frá símakerfi)" + "fá aðgang að áætlaðri staðsetningu (frá símkerfi)" "Leyfir forriti að sjá gróflega áætlaða staðsetningu þína. Sú staðsetning er sótt í staðsetningarbúnað sem byggir á netkerfum á borð við farsímasenda og Wi-Fi. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg tækinu til að forritið geti notað hana. Forrit geta notað þjónustuna til að áætla staðsetningu þína gróflega." "breyta hljóðstillingum" "Leyfir forriti að breyta altækum hljóðstillingum, s.s. hljóðstyrk og hvaða hátalari er notaður sem úttak." "taka upp hljóð" "Leyfir forriti að taka upp hljóð með hljóðnemanum. Þessi heimild leyfir forritinu að taka upp hljóð hvenær sem er án þinnar heimildar." - "sim-samskipti" + "senda skipanir til SIM-kortsins" "Leyfir forriti að senda SIM-kortinu skipanir. Þetta er mjög hættulegt." "taka myndir og myndskeið" "Leyfir forriti að taka myndir og myndskeið með myndavélinni. Þessi heimild leyfir forritinu að nota myndavélina hvenær sem er án þinnar heimildar." @@ -382,7 +382,7 @@ "Leyfir forriti að fá lista yfir reikninga sem síminn þekkir. Þar á meðal kunna að vera reikningar stofnaðir af forritum sem þú hefur sett upp." "skoða nettengingar" "Leyfir forriti að skoða upplýsingar um nettengingar, svo sem hvaða net eru til og eru tengd." - "fullur netaðgangur" + "hafa fullan netaðgang" "Leyfir forriti að búa til nettengla og nota sérstilltar netsamskiptareglur. Vafrinn og önnur forrit geta sjálf sent gögn inn á internetið svo þessi heimild er ekki þörf til að senda gögn á internetið." "breyta nettengingu" "Leyfir forriti að breyta stöðu nettengingar." @@ -402,7 +402,7 @@ "Leyfir forriti að stilla Bluetooth-símann og finna og parast við fjartengd tæki." "tengjast og aftengja frá WiMAX" "Leyfir forriti að greina hvort WiMAX er virkt og upplýsingar um tengd WiMAX-net." - "Breyta stöðu WiMAX" + "breyta stöðu WiMAX" "Leyfir forriti að tengja og aftengja spjaldtölvuna við WiMAX-net." "Leyfir forriti að tengja sjónvarpið við WiMAX-net og aftengja frá þeim." "Leyfir forriti að tengja og aftengja símann við WiMAX-net." @@ -485,7 +485,7 @@ "Leyfir forriti að breyta kvörðunarbreytum snertiskjásins. Ætti aldrei að vera nauðsynlegt fyrir venjuleg forrit." "aðgangur að DRM-vottorðum" "Leyfir forriti að úthluta og nota DRM-vottorð. Ætti aldrei að þurfa fyrir venjuleg forrit." - "Fá flutningsstöðu Android Beam" + "fá flutningsstöðu Android Beam" "Leyfir þessu forriti að fá upplýsingar um flutning sem fram fer með Android Beam" "fjarlægja DRM-vottorð" "Leyfir forriti að fjarlægja DRM-vottorð. Ætti aldrei að vera nauðsynlegt fyrir venjuleg forrit." @@ -1091,11 +1091,11 @@ "Forsníður…" "Ekki sett í" "Engar aðgerðir með samsvörun fundust." - "Beina margmiðlunarúttaki" + "beina margmiðlunarúttaki" "Leyfir forriti að beina margmiðlunarúttaki til annarra ytri tækja." - "Lesa uppsetningarlotur" + "lesa uppsetningarlotur" "Leyfir forriti að lesa uppsetningarlotur. Þetta gerir því kleift að sjá upplýsingar um virkar pakkauppsetningar." - "Fara fram á uppsetningu pakka" + "fara fram á uppsetningu pakka" "Leyfir forriti að fara fram á uppsetningu pakka." "Ýttu tvisvar til að fá upp aðdráttarstýringar" "Ekki tókst að bæta græju við." diff --git a/core/res/res/values-it-watch/strings.xml b/core/res/res/values-it-watch/strings.xml index a042221ec81d1..80865f1c6427e 100644 --- a/core/res/res/values-it-watch/strings.xml +++ b/core/res/res/values-it-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d di %2$d." + "Sensori" diff --git a/core/res/res/values-it/cm_strings.xml b/core/res/res/values-it/cm_strings.xml new file mode 100644 index 0000000000000..6adba65d9e4d0 --- /dev/null +++ b/core/res/res/values-it/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Cattura schermata + + ricevere SMS protetti + + Consenti all\'app di ricevere SMS protetti. + + modifica la lista di SMS protetti + + Consente all\'app di modificare la lista indirizzi SMS protetta. + + Sicurezza + + Autorizzazioni relative alle informazioni sulla sicurezza del dispositivo. + + legge la blacklist del telefono + + Consente all\'app di leggere le informazioni sui numeri di telefono che vengono bloccati per messaggi o chiamate in arrivo. + + modifica la blacklist del telefono + + Consente all\'app di modificare i numeri di telefono che vengono bloccati per messaggi o chiamate in arrivo. + + imposta sfondo sblocco schermo + + Consente all\'app di cambiare lo sfondo del blocco schermo. + + Riavvia + + Corrente + + + Riavvia + + Recovery + + Bootloader + + Download + + Riavvio veloce + + Riavvia + + Il dispositivo verrà riavviato. + Il telefono verrà riavviato. + + Riavvio\u2026 + + App terminata + + ADB attraverso la rete attivato + + ADB attraverso USB & rete attivato + + Tocca per disattivare il debug. + + ADB - %1$s + USB & rete + USB + Rete + + Intercetta lancio app + + %s non è installato + + Priorità + Nessuno + + Hotspot WiFi disattivato in seguito al cambio di SIM + + Spegni Wi-Fi + + attiva o disattiva Privacy Guard + Consente all\'app di decidere se un\'altra app viene eseguita con Privacy Guard. Quando un\'app viene eseguita con Privacy Guard, non ha accesso a dati personali come contatti, lista chiamate o messaggi. + Privacy Guard attiva + %1$s non sarà in grado di accedere ai dati personali + Privacy Guard + %1$s vorrebbe %2$s. + + Ricorda la mia scelta + + accedere alla fotocamera + accedere alla posizione + leggere le tue notifiche + Attiva una VPN + avvia all\'accensione + Elimina la tua lista delle chiamate + Elimina i tuoi contatti + Elimina i tuoi messaggi MMS + Elimina i tuoi messaggi SMS + disegna sopra + Ottieni le statistiche di utilizzo + mantenere il dispositivo sveglio + effettuare una chiamata + aggiornare il tuo calendario + aggiornare il registro chiamate + modificare gli appunti + aggiornare i tuoi contatti + aggiornare le impostazioni di sistema + attiva/disattiva microfono + riprodurre audio + inviare una notifica + proietta media + leggere il tuo calendario + leggere il registro chiamate + leggere gli appunti + leggere i tuoi contatti + leggere i tuoi messaggi MMS + leggere i tuoi messaggi SMS + ricevere un messaggio SMS + registrare audio + inviare un messaggio MMS + inviare un messaggio SMS + avviarsi all\'accensione + mostra messaggi di nofifica + cambiare stato del Bluetooth + modifica dati mobili + cambiare stato dell\'NFC + modifica Wi-Fi + controllare il volume sveglia + controllare il focus audio + controllare il volume Bluetooth + controllare il volume master + usare i pulsanti multimediali + controllare il volume multimediale + controllare il volume notifiche + controllare il volume suoneria + usare il feedback aptico + controllare il volume della chiamata + scrivere un messaggio MMS + scrivere un messaggio SMS + utilizza le impronte digitali + aggiungi un messaggio vocale + accedi allo stato del telefono + scansiona reti Wi-Fi + cambia lo sfondo + utilizza struttura assistenza + cattura una schermata + utilizza sensori per il corpo + leggi trasmissioni cellulari + falsifica la tua posizione + leggi scheda SD + scrivi su scheda SD + accendi lo schermo + ottieni account dispositivo + cambia stato Wi-Fi + Ottieni accesso root + + Per sbloccare questo schermo, tocca e tieni premuto il pulsante indietro. + + Nessun dispositivo connesso + %1$s dispositivo connesso + %1$s dispositivi connessi + + + + Lancio dell\'app bloccato + L\'app %1$s è protetta. Tocca qui per autenticarti e aprire l\'app. + + Batteria completamente carica + Disconnetti il dispositivo dal caricatore per preservare la longevità della batteria. + + reimposta statistiche batteria + + Consente all\'applicazione di reimpostare gli attuali dati di utilizzo della batteria a basso livello. + + Le SIM sono cambiate + Toccare per impostare le preferenze predefinite della SIM + diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index f82ee870af7e9..f486ad0680393 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -254,7 +254,7 @@ "Sono inclusi dati personali come numeri di carte di credito e password." "disattivare o modificare la barra di stato" "Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema." - "barra di stato" + "ruolo di barra di stato" "Consente di visualizzare l\'applicazione nella barra di stato." "espansione/compressione barra di stato" "Consente all\'applicazione di espandere o comprimere la barra di stato." @@ -282,7 +282,7 @@ "Consente all\'applicazione di ricevere ed elaborare messaggi WAP. Questa autorizzazione include la facoltà di monitorare o eliminare i messaggi che ti vengono inviati senza mostrarteli." "recupero applicazioni in esecuzione" "Consente all\'applicazione di recuperare informazioni sulle attività attualmente e recentemente in esecuzione. Ciò potrebbe consentire all\'applicazione di scoprire informazioni sulle applicazioni in uso sul dispositivo." - "Gestione dei proprietari di profili e dispositivi" + "gestione dei proprietari di dispositivi e profili" "Consente alle app di impostare i proprietari dei profili e dei dispositivi." "riordinamento applicazioni in esecuzione" "Consente all\'applicazione di spostare attività in primo piano e in background. L\'applicazione potrebbe farlo senza un tuo comando." @@ -324,7 +324,7 @@ "Consente all\'applicazione di modificare il registro chiamate del tablet, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate." "Consente all\'app di modificare il registro chiamate della TV, inclusi i dati sulle chiamate in arrivo e in uscita. Le app dannose potrebbero farne uso per cancellare o modificare il registro chiamate." "Consente all\'applicazione di modificare il registro chiamate del telefono, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate." - "sensori per il corpo (come il cardiofrequenzimetro)" + "accesso ai sensori (come il cardiofrequenzimetro)" "Consente all\'app di accedere ai dati relativi ai sensori che monitorano le tue condizioni fisiche, ad esempio la frequenza cardiaca." "lettura di eventi di calendario e di informazioni riservate" "Consente all\'applicazione di leggere tutti gli eventi di calendario memorizzati sul tablet, inclusi quelli di amici o colleghi. Ciò potrebbe consentire all\'applicazione di condividere o salvare i dati del tuo calendario, a prescindere dal livello di riservatezza o privacy." @@ -336,15 +336,15 @@ "Consente all\'applicazione di aggiungere, rimuovere, modificare gli eventi che puoi modificare sul telefono, inclusi quelli di amici o colleghi. Ciò potrebbe consentire all\'applicazione di inviare messaggi apparentemente provenienti dai proprietari del calendario o di modificare eventi all\'insaputa dei proprietari." "accesso a comandi aggiuntivi del provider di localizz." "Consente all\'app di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'app di interferire con il funzionamento del GPS o di altre fonti di localizzazione." - "posizione precisa (GPS e basata sulla rete)" + "accesso alla posizione esatta (basata su GPS e rete)" "Consente all\'applicazione di ottenere la tua posizione esatta utilizzando il sistema GPS (Global Positioning System) o fonti di geolocalizzazione delle reti come ripetitori di telefonia mobile e Wi-Fi. Questi servizi di localizzazione devono essere attivi e disponibili sul dispositivo per poter essere utilizzati dall\'applicazione. Le applicazioni potrebbero utilizzare questa autorizzazione per stabilire la tua posizione e potrebbero consumare ulteriore batteria." - "posizione approssimativa (basata sulla rete)" + "accesso alla posizione approssimativa (basata sulla rete)" "Consente all\'applicazione di ottenere la tua posizione approssimativa. Questa posizione viene ottenuta da servizi di localizzazione utilizzando fonti di geolocalizzazione delle reti come ripetitori di telefonia mobile e Wi-Fi. Questi servizi di localizzazione devono essere attivi e disponibili sul dispositivo per poter essere utilizzati dall\'applicazione. Le applicazioni potrebbero utilizzare questa autorizzazione per stabilire la tua posizione approssimativa." "modifica impostazioni audio" "Consente all\'applicazione di modificare le impostazioni audio globali, come il volume e quale altoparlante viene utilizzato per l\'uscita." "registrare audio" "Consente all\'applicazione di registrare audio con il microfono. Questa autorizzazione consente all\'applicazione di registrare audio in qualsiasi momento senza la tua conferma." - "comunicazione SIM" + "invio di comandi alla SIM" "Consente all\'app di inviare comandi alla SIM. Questo è molto pericoloso." "acquisizione di foto e video" "Consente all\'applicazione di scattare foto e riprendere video con la fotocamera. Questa autorizzazione consente all\'applicazione di utilizzare la fotocamera in qualsiasi momento senza la tua conferma." @@ -382,7 +382,7 @@ "Consente all\'applicazione di accedere all\'elenco degli account noti al telefono. Ciò può includere eventuali account creati da applicazioni installate." "visualizzazione connessioni di rete" "Consente all\'applicazione di visualizzare informazioni sulle connessioni di rete, ad esempio le reti esistenti e connesse." - "accesso di rete completo" + "accesso completo alla rete" "Consente all\'app di creare socket di rete e di utilizzare protocolli di rete personalizzati. Il browser e altre applicazioni forniscono mezzi per inviare i dati a Internet, quindi non è richiesta questa autorizzazione per inviare dati a Internet." "modifica connettività di rete" "Consente all\'applicazione di modificare lo stato di connettività della rete." @@ -402,7 +402,7 @@ "Consente all\'applicazione di configurare il telefono Bluetooth locale e di rilevare ed effettuare l\'accoppiamento con dispositivi remoti." "connessione e disconnessione da WiMAX" "Consente all\'applicazione di determinare se WiMAX è abilitato e informazioni su eventuali reti WiMAX che sono connesse." - "Modifica stato WiMAX" + "modifica stato WiMAX" "Consente all\'applicazione di connettere/disconnettere il tablet dalle reti WiMAX." "Consente all\'app di collegare la TV a e scollegarla da reti WiMAX." "Consente all\'applicazione di connettere/disconnettere il telefono dalle reti WiMAX." @@ -485,7 +485,7 @@ "Consente all\'app di modificare i parametri di calibrazione del touch screen. Questa opzione non deve essere utilizzata per le app normali." "accesso a certificati DRM" "Consente a un\'app di fornire e utilizzare ceritificati DRM. Questa opzione non deve essere utilizzata per app normali." - "Ricevi lo stato dei trasferimenti Android Beam" + "ricezione dello stato dei trasferimenti Android Beam" "Consente all\'applicazione di ricevere informazioni sugli attuali trasferimenti Android Beam" "rimozione di certificati DRM" "Consente a un\'applicazione di rimuovere certificati DRM. Non dovrebbe mai essere necessaria per le normali applicazioni." @@ -1091,11 +1091,11 @@ "Formattazione…" "Non inserito" "Nessuna attività corrispondente trovata." - "Indirizzamento uscita media" + "indirizzamento dell\'uscita dei contenuti multimediali" "Consente a un\'applicazione di indirizzare l\'uscita di media verso altri dispositivi esterni." - "Lettura di sessioni di installazione" + "lettura delle sessioni di installazione" "Consente a un\'applicazione di leggere le sessioni di installazione. L\'app può conoscere i dettagli sulle installazioni di pacchetti attive." - "Richiesta di pacchetti di installazione" + "richiesta di pacchetti di installazione" "Consente a un\'applicazione di richiedere l\'installazione di pacchetti." "Tocca due volte per il comando dello zoom" "Aggiunta del widget non riuscita." diff --git a/core/res/res/values-iw-watch/strings.xml b/core/res/res/values-iw-watch/strings.xml index 64b194d4e8b5a..3d0dde297913e 100644 --- a/core/res/res/values-iw-watch/strings.xml +++ b/core/res/res/values-iw-watch/strings.xml @@ -21,4 +21,5 @@ "אפליקציה %1$d מתוך %2$d." + "חיישנים" diff --git a/core/res/res/values-iw/cm_strings.xml b/core/res/res/values-iw/cm_strings.xml new file mode 100644 index 0000000000000..291baccf90eb4 --- /dev/null +++ b/core/res/res/values-iw/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + צילום מסך + + קבלת הודעות SMS מוגנות + + מאפשר ליישום לקבל הודעות SMS מוגנות. + + שינוי רשימת הודעות SMS מוגנות + + מאפשר ליישום לשנות את רשימת הכתובות של הודעות SMS מוגנות. + + אבטחה + + הרשאות הקשורות לאבטחת המידע במכשיר. + + קריאת הרשימה השחורה של הטלפון + + מאפשר ליישום לקרוא מידע אודות מספרי הטלפון שנחסמו עבור קבלת שיחות או הודעות נכנסות. + + שנה רשימה שחורה של הטלפון + + מאפשר ליישום לשנות את המספרים שנחסמו עבור קבלת שיחות או הודעות נכנסות. + + הגדרת טפט למסך הנעילה + + מאפשר ליישום לשנות את הטפט של מסך הנעילה. + + אתחול מחדש + + נוכחי + + + אתחול מחדש + + שחזור + + תוכנת טעינה ראשונית + + הורדה + + אתחול מהיר + + אתחול מחדש + + הטאבלט יופעל מחדש. + הטלפון יאותחל מחדש. + + מאתחל\u2026 + + היישום נסגר + + ADB דרך רשת מופעל + + ADB דרך USB ורשת מופעל + + גע להשבתת איתור באגים. + + ADB - %1$s + USB ורשת + USB + רשת + + יירוט הפעלת יישום + + %s לא מותקן + + עדיפות + ללא + + נקודת רשת ציבורית Wi-Fi הושבתה עקב שינוי מנוי SIM + + כיבוי Wi-Fi + + הפעלה או השבתה של שומר הפרטיות + מאפשר ליישום לשנות הרשאות של יישום אחר כדי שיפעל תחת שומר הפרטיות. כאשר יישום פועל תחת שומר הפרטיות, לא תהיה לו גישה למידע פרטי כמו אנשי קשר, יומן שיחות והודעות. + שומר הפרטיות פעיל + %1$s לא יוכל לגשת למידע אישי + שומר הפרטיות + %1$s מבקש/ת %2$s. + + זכור את הבחירה שלי + + גישה למצלמה + גישה למיקום שלך + קריאת ההתראות שלך + הפעלת VPN + התחל פעילות בהדלקת המכשיר + מחיקת יומן השיחות שלך + מחיקת אנשי הקשר שלך + מחיקת הודעות ה-MMS שלך + מחיקת הודעות ה-SMS שלך + הצגת תוכן מעל יישומים אחרים + קבלת סטטיסטיקות שימוש ביישום + השארת המכשיר ער + ביצוע שיחת טלפון + עדכון לוח השנה שלך + עדכון יומן השיחות + שינוי לוח ההעתקה + עדכון אנשי הקשר שלך + עדכון הגדרות המערכת + השתקת/הפעלת המיקרופון + ניגון שמע + פרסום התראה + הקרנת מדיה + קריאת לוח השנה שלך + קריאת יומן השיחות + קריאת לוח ההעתקה + קריאת אנשי הקשר שלך + קריאת הודעות ה-MMS שלך + קריאת הודעות ה-SMS שלך + קבלת הודעת SMS + הקלטת שמע + שליחת הודעת MMS + שליחת הודעת SMS + התחלת פעילות בהדלקת המכשיר + הצגת הודעות קופצות + שינוי מצב ה-Bluetooth + הפעלת/כיבוי נתונים סלולריים + שינוי מצב ה-NFC + הפעלת/כיבוי Wi-Fi + שליטה בעוצמת השעון המעורר + שליטה במיקוד השמע + שליטה בעוצמת קול ב-Bluetooth + שליטה בעוצמת הקול הראשית + שימוש בלחצני המדיה + שליטה בעוצמת קול למדיה + שליטה בעוצמת קול ההתראות + שליטה בעוצמת קול לרינגטון + שימוש במשוב רטט + שליטה על עוצמת הקול בשיחה + כתיבת הודעת MMS + כתיבת הודעת SMS + שימוש בטביעת אצבע + הוסף תא קולי + גש למצב הטלפון + סרוק רשתות Wi-Fi + החלף טפט + שימוש בתבנית המידע ליישום הסיוע + צלם מסך + השתמש בחיישני גוף + קרא שידורי סלולר + הסווה את מיקומך + קרא אחסון חיצוני + כתוב לאחסון חיצוני + הפעל המסך + קבל חשבונות מכשיר + שנה מצב Wi-Fi + קבלת גישת שורש (Root) + + כדי לבטל נעיצת מסך זה, גע והחזק בלחצן \"הקודם\". + + אין מכשירים מחוברים + מכשיר %1$s מחובר + %1$s מכשירים מחוברים + + + + הפעלת הפעולה נחסמה + %1$s מוגן מפני הפעלה. הקש כדי להזדהות ולהפעיל את היישום. + + סוללה טעונה במלואה + נתק את מכשירך מהמטען כדי לשפר את אורך חיי סוללה. + + איפוס סטטיסטיקות סוללה + + מאפשר ליישום לאפס נתוני רמה-נמוכה נוכחיים של השימוש בסוללה. + + כרטיסי SIM הוחלפו + הקש כדי להגדיר את העדפות ברירת המחדל של כרטיס ה-SIM + diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 2c6b3beee256b..eb27098ecf587 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -256,7 +256,7 @@ "כולל נתונים אישיים כמו מספרי כרטיס אשראי וסיסמאות." "השבת או שנה את שורת המצב" "מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת." - "שורת מצב" + "להיות שורת הסטטוס" "מאפשר לאפליקציה להופיע בשורת המצב." "הרחב/כווץ את שורת המצב" "מאפשר לאפליקציה להרחיב או לכווץ את שורת המצב." @@ -284,7 +284,7 @@ "‏מאפשר לאפליקציה לקבל ולעבד הודעות WAP. אישור זה כולל את היכולת לעקוב אחר הודעות שנשלחו אליך ולמחוק אותן מבלי להציג לך אותן." "אחזור אפליקציות פעילות" "מאפשר לאפליקציה לאחזר מידע לגבי משימות הפועלות כרגע ושפעלו לאחרונה. ייתכן שהדבר יתיר לאפליקציה לגלות מידע לגבי האפליקציות שבהן נעשה שימוש במכשיר." - "ניהול בעלים של פרופיל ומכשיר" + "ניהול בעלים של פרופיל ומכשיר" "מאפשרת לאפליקציות להגדיר את הבעלים של הפרופיל ואת בעל המכשיר." "סידור מחדש של אפליקציות פעילות" "מאפשר לאפליקציה להעביר משימות לחזית ולרקע. האפליקציה עשוי לעשות זאת ללא התערבותך." @@ -326,7 +326,7 @@ "מאפשר לאפליקציה לשנות את יומן השיחות של הטאבלט, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות לעשות בכך שימוש כדי למחוק או לשנות את יומן השיחות שלך." "מאפשרת לאפליקציה לשנות את יומן השיחות של הטלוויזיה, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות להשתמש בהרשאה זו כדי למחוק או לשנות את יומן השיחות שלך." "מאפשר לאפליקציה לשנות את יומן השיחות של הטלפון, כולל נתונים על שיחות נכנסות ויוצאות. אפליקציות זדוניות עלולות לעשות בכך שימוש כדי למחוק או לשנות את יומן השיחות שלך." - "חיישני גוף (כמו מוניטורים עבור קצב לב)" + "גישה אל חיישני גוף (כמו מוניטורים לקצב לב)" "מאפשר לאפליקציה לגשת אל נתוני חיישנים העוקבים אחר מצבך הגופני, כמו קצב הלב." "קריאת אירועי יומן וגם מידע סודי" "מאפשר לאפליקציה לקרוא את כל אירועי היומן המאוחסנים בטאבלט, כולל אלה של חברים ועמיתים לעבודה. הדבר עשוי להתיר לאפליקציה לשתף או לשמור את נתוני היומן שלך, ללא התחשבות בסודיות או ברגישות." @@ -338,15 +338,15 @@ "מאפשר לאפליקציה להוסיף, להסיר ולשנות אירועים שאתה יכול לשנות בטלפון, כולל אלה של חברים או עמיתים לעבודה. הדבר עשוי להתיר לאפליקציה לשלוח הודעות הנראות כאילו שנשלחו מבעלי יומן או לשנות אירועים ללא ידיעת הבעלים." "גישה לפקודות ספק מיקום נוספות" "‏מאפשרת לאפליקציה לגשת לפקודות נוספות של ספק המיקום. הרשאה זו עשויה לאפשר לאפליקציה לשבש את פעולת ה-GPS או מקורות מיקום אחרים." - "‏מיקום מדויק (מבוסס GPS ורשת)" + "‏גישה אל מיקום מדויק (מבוסס GPS ורשת)" "‏מאפשר לאפליקציה לקבל את המיקום המדויק שלך באמצעות מערכת המיקום הגלובלית (GPS) או מקורות מיקום ברשת כגון אנטנות סלולריות ו-Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים ונגישים למכשיר שלך כדי שהאפליקציה תשתמש בהם. ייתכן שאפליקציות יעשו בכך שימוש כדי לקבוע היכן אתה נמצא ולגרום לצריכת סוללה מוגברת." - "מיקום משוער (מבוסס רשת)" + "גישה אל מיקום משוער (מבוסס רשת)" "‏מאפשר לאפליקציה לקבל את מיקומך המשוער. מיקום זה נגזר על-פי שירותי מיקום העושים שימוש במקורות מיקום ברשת, כגון אנטנות סלולריות ו-Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים ונגישים למכשיר שלך כדי שהאפליקציה תשתמש בהם. ייתכן שאפליקציות יעשו בכך שימוש כדי לקבוע את מיקומך המשוער." "שנה את הגדרות האודיו שלך" "מאפשר לאפליקציה לשנות הגדרות אודיו גלובליות כמו עוצמת קול ובחירת הרמקול המשמש לפלט." "הקלט אודיו" "מאפשר לאפליקציה להקליט אודיו באמצעות המיקרופון. אישור זה מתיר לאפליקציה להקליט אודיו בכל עת ללא אישורך." - "‏תקשורת SIM" + "‏שליחת פקודות אל ה-SIM" "‏מאפשרת ליישום לשלוח פקודות ל-SIM. זוהי הרשאה מסוכנת מאוד." "צלם תמונות וסרטונים" "מאפשר לאפליקציה לצלם תמונות וסרטונים באמצעות המצלמה. אישור זה מאפשר לאפליקציה להשתמש במצלמה בכל עת ללא אישורך." @@ -384,7 +384,7 @@ "מאפשר לאפליקציה לקבל רשימה של חשבונות המוכרים לטלפון. הדבר עשוי לכלול חשבונות שנוצרו על ידי אפליקציות שהתקנת." "הצג חיבורי רשת" "מאפשר לאפליקציה להציג מידע לגבי חיבורי רשת, למשל, אילו רשתות קיימות ומחוברות." - "גישת רשת מלאה" + "קבלת גישת רשת מלאה" "‏מאפשר לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן, כמו אפליקציות אחרות, מספק אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט." "שנה את קישוריות הרשת" "מאפשר לאפליקציה לשנות את מצב הקישוריות של הרשת." @@ -404,7 +404,7 @@ "‏מאפשר לאפליקציה להגדיר את תצורתו של הטלפון המקומי מסוג Bluetooth וכן לגלות מכשירים מרוחקים ולבצע התאמה איתם." "‏התחברות והתנתקות מ-WiMAX" "‏מאפשר לאפליקציה לדעת האם WiNMAX מופעל, כמו גם לקבל מידע האם רשתות WiNMAX כלשהן מחוברות." - "‏שנה את מצב WiMAX" + "‏שנה את מצב WiMAX" "‏מאפשר לאפליקציה לחבר את הטאבלט לרשתות WiMAX ולהתנתק מהן." "‏מאפשרת לאפליקציה לחבר את הטלוויזיה לרשתות WiMAX ולנתק את החיבור שלה מהן." "‏מאפשר לאפליקציה לחבר את הטלפון לרשתות WiMAX ולהתנתק מהן." @@ -487,7 +487,7 @@ "מאפשרת לאפליקציה לשנות את פרמטרי הכיול של מסך המגע. לעולם לא אמורה להיות נחוצה לאפליקציות רגילות." "‏גישה אל אישורי DRM" "‏מאפשרת לאפליקציה לנהל תצורה של אישורי DRM ולהשתמש בהם. לעולם לא אמורה להיות נחוצה עבור אפליקציה רגילה." - "‏קבלת סטטוס העברה של Android Beam" + "‏קבלת סטטוס העברה של Android Beam" "‏מאפשר לאפליקציה הזו לקבל מידע על העברות Android Beam נוכחיות" "‏הסרת אישורי DRM" "‏הרשאה זו מאפשרת לאפליקציה להסיר אישורי DRM. באפליקציות רגילות אף פעם לא אמור להיות בה צורך." @@ -1105,11 +1105,11 @@ "מפרמט…" "לא הוכנס" "לא נמצאו פעילויות תואמות." - "ניתוב פלט מדיה" + "ניתוב פלט מדיה" "מאפשר לאפליקציה לנתב פלט מדיה למכשירים חיצוניים אחרים." - "קריאת פעילות התקנה" + "קריאת פעילות התקנה" "מאפשר לאפליקציה לקרוא הפעלות התקנה. הרשאה זו מאפשרת לה לראות פרטים על התקנות פעילות של חבילות." - "בקשה להתקנת חבילות" + "בקשה להתקנת חבילות" "מתיר לאפליקציה לבקש התקנה של חבילות." "גע פעמיים לבקרת מרחק מתצוגה" "‏לא ניתן להוסיף widget." diff --git a/core/res/res/values-ja-watch/strings.xml b/core/res/res/values-ja-watch/strings.xml index b3c6d97adba65..893063e7d08db 100644 --- a/core/res/res/values-ja-watch/strings.xml +++ b/core/res/res/values-ja-watch/strings.xml @@ -21,4 +21,5 @@ "アプリ%1$d/%2$d" + "センサー" diff --git a/core/res/res/values-ja/cm_strings.xml b/core/res/res/values-ja/cm_strings.xml new file mode 100644 index 0000000000000..7157ab25c9ff4 --- /dev/null +++ b/core/res/res/values-ja/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + スクリーンショット + + 保護されたSMSの受信 + + 保護されたSMSの受信をアプリに許可します。 + + 保護されたSMSリストの変更 + + 保護されたSMSアドレスリストの変更をアプリに許可します。 + + セキュリティ + + 端末のセキュリティ情報に関連する権限です。 + + 携帯電話の着信拒否リストの読み取り + + 着信やメッセージを拒否している電話番号に関する情報の読み取りをアプリに許可します。 + + 携帯電話の着信拒否リストの変更 + + 着信やメッセージを拒否している電話番号の変更をアプリに許可します。 + + キーガードの壁紙の設定 + + ロック画面の壁紙の変更をアプリに許可します。 + + 再起動 + + 現在 + + + 再起動 + + リカバリー + + ブートローダ + + ダウンロード + + ソフトリブート + + 再起動 + + タブレットは再起動します。 + 携帯電話は再起動します。 + + 再起動中\u2026 + + アプリを終了しました。 + + ネットワーク経由のADBが有効です + + USBとネットワーク経由のADBが有効です + + タップしてデバッグを無効にします。 + + ADB - %1$s + USBとネットワーク + USB + ネットワーク + + アプリの起動の監視 + + %sはインストールされていません + + 優先順位 + なし + + SIMサブスクリプションの変更によってWi-Fiアクセスポイントが無効になりました + + Wi-FiをOFFにする + + プライバシーガードを有効/無効にする + 他のアプリでプライバシーガードを有効にするかどうかの変更をアプリに許可します。プライバシーガードを有効にしてアプリを実行すると、そのアプリは連絡先、通話履歴、メッセージなどの個人データにアクセスできなくなります。 + プライバシーガードが有効です + %1$sは個人データにアクセスできません + プライバシーガード + %1$s%2$sをしようとしています。 + + 選択を保存 + + カメラへのアクセス + 位置情報へのアクセス + 通知の読み取り + VPNの有効化 + 電源投入時の実行 + 通話履歴の削除 + 連絡先の削除 + MMSメッセージの削除 + SMSメッセージの削除 + 上部への描画 + アプリの使用統計の取得 + 端末のスリープの無効化 + 通話の発信 + カレンダーの更新 + 通話履歴の更新 + クリップボードの変更 + 連絡先の更新 + システムの設定の更新 + マイクのミュート/ミュート解除 + 音声の再生 + 通知の配信 + メディアの投影 + カレンダーの読み取り + 通話履歴の読み取り + クリップボードの読み取り + 連絡先の読み取り + MMSメッセージの読み取り + SMSメッセージの読み取り + SMSメッセージの受信 + 音声の録音 + MMSメッセージの送信 + SMSメッセージの送信 + 起動時の実行 + トーストメッセージの表示 + Bluetoothの切り替え + モバイルデータの切り替え + NFCの切り替え + Wi-Fiの切り替え + アラームの音量の制御 + 音声フォーカスの制御 + Bluetoothの音量の制御 + 主音量の制御 + メディアボタンの使用 + メディアの音量の制御 + 通知音量の制御 + 着信音の音量の制御 + 触覚フィードバックの使用 + 音声の音量の制御 + MMSメッセージの書き込み + SMSメッセージの書き込み + 指紋の使用 + ボイスメールの追加 + 携帯電話の状態へのアクセス + Wi-Fiネットワークのスキャン + 壁紙の変更 + ストラクチャのアシストの使用 + スクリーンショットの撮影 + ボディセンサーの使用 + セルブロードキャストの読み取り + 位置情報の仮想 + 外部ストレージの読み取り + 外部ストレージの書き込み + 画面の点灯 + 端末のアカウントの取得 + Wi-Fiの状態の変更 + ルートアクセスの取得 + + この画面の固定を解除するには、戻るボタンを長押しします。 + + 接続しているデバイスはありません + %1$s台のデバイスが接続しています + %1$s台のデバイスが接続しています + + + + アクティビティの起動がブロックされました + %1$sは起動できないように保護されています。タップして認証後にアプリケーションを起動してください。 + + 電池の充電が完了しました + 電池寿命を延ばすために端末を充電器から取り外してください。 + + 電池統計情報のリセット + + 現在の電池消費量の低レベルデータをリセットすることをアプリに許可します。 + + SIMカードが変更されました + タップしてSIMカードのデフォルトの設定をする + diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 4062c291402c2..9cd0ae62d706a 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -254,7 +254,7 @@ "クレジットカードの番号やパスワードなどの個人データが含まれます。" "ステータスバーの無効化や変更" "ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。" - "ステータスバーへの表示" + "ステータスバーへの表示" "ステータスバーへの表示をアプリに許可します。" "ステータスバーの拡大/縮小" "ステータスバーの展開/折りたたみをアプリに許可します。" @@ -282,7 +282,7 @@ "WAPメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。" "実行中のアプリの取得" "現在実行中または最近実行したタスクに関する情報の取得をアプリに許可します。これにより、その端末でどのアプリを使用しているかをアプリから識別できるようになる可能性があります。" - "プロファイルの所有者と端末の所有者の管理" + "プロファイルの所有者と端末の所有者の管理" "プロファイルの所有者と端末の所有者の設定をアプリに許可します。" "実行中のアプリの順序変更" "タスクをフォアグラウンドやバックグラウンドに移動することをアプリに許可します。これにより、アプリがユーザーからの入力なしでこの処理を実行する可能性があります。" @@ -324,7 +324,7 @@ "タブレットの通話履歴(着信や発信のデータなど)の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、通話履歴が消去または変更される恐れがあります。" "テレビの通話履歴(着信や発信のデータなど)の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、通話履歴が消去または変更される恐れがあります。" "携帯端末の通話履歴(着信や発信のデータなど)の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、通話履歴が消去または変更される恐れがあります。" - "ボディーセンサー(心拍数モニターなど)" + "ボディーセンサー(心拍数モニターなど)へのアクセス" "心拍数など、身体状態を監視するセンサーからのデータにアクセスすることをアプリに許可します。" "カレンダーの予定と機密情報の読み取り" "タブレットに保存されているカレンダーの予定(友だちや同僚の予定も含めすべて)を読み取ることをアプリに許可します。これにより、アプリがカレンダーのデータを機密性に関係なく共有または保存できるようになる可能性があります。" @@ -336,15 +336,15 @@ "ユーザーが携帯端末から編集できる予定(友だちや同僚の予定も含む)を追加、削除、変更することをアプリに許可します。これによりアプリは、カレンダーの所有者から発信されたかのようなメッセージを送信したり、所有者の知らないうちに予定を変更したりできるようになる可能性があります。" "位置情報提供者の追加コマンドアクセス" "位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。" - "正確な位置情報(GPSとネットワーク基地局)" + "正確な位置情報(GPSとネットワーク基地局)へのアクセス" "グローバルポジショニングシステム(GPS)またはネットワーク位置情報源(携帯基地局やWi-Fiなど)を利用して正確な位置情報を取得することをアプリに許可します。これらの位置情報サービスはONの状態にして、端末でアプリがサービスを利用できるようにする必要があります。アプリはこの位置情報を利用してユーザーの現在地を特定できます。また、これにより電池の消費量が増える可能性があります。" - "おおよその位置情報(ネットワーク基地局)" + "おおよその位置情報(ネットワーク基地局)へのアクセス" "ユーザーのおおよその位置情報を取得することをアプリに許可します。この位置情報はネットワーク位置情報源(携帯基地局やWi-Fiなど)を利用した位置情報サービスから取得されます。これらの位置情報サービスはONの状態にして、端末でアプリがサービスを利用できるようにする必要があります。アプリはこの位置情報を利用してユーザーのおおよその現在地を特定できます。" "音声設定の変更" "音声全般の設定(音量、出力に使用するスピーカーなど)の変更をアプリに許可します。" "録音" "マイクを使った録音をアプリに許可します。これにより、アプリがいつでも確認なしで録音できるようになります。" - "SIM通信" + "SIMへのコマンド送信" "SIMにコマンドを送信することをアプリに許可します。この許可は非常に危険です。" "写真と動画の撮影" "カメラでの写真と動画の撮影をアプリに許可します。これにより、アプリが確認なしでいつでもカメラを使用できるようになります。" @@ -382,7 +382,7 @@ "携帯端末で認識されているアカウントのリストの取得をアプリに許可します。これには、インストールしたアプリによって作成されたアカウントも含まれます。" "ネットワーク接続の表示" "存在するネットワークや接続しているネットワークなど、ネットワーク接続に関する情報を表示することをアプリに許可します。" - "ネットワークへのフルアクセス" + "ネットワークへのフルアクセス" "ネットワークソケットの作成とカスタムネットワークプロトコルの使用をアプリに許可します。インターネットにデータを送信する手段はブラウザや他のアプリが提供するため、インターネットへのデータ送信のためにこれを許可する必要はありません。" "ネットワーク接続の変更" "ネットワーク接続状態の変更をアプリに許可します。" @@ -402,7 +402,7 @@ "ローカルのBluetooth携帯端末を設定することと、リモート端末を検出してペアに設定することをアプリに許可します。" "WiMAXへの接続と切断" "WiMAXがONになっているかどうかを識別し、接続されているWiMAXネットワークの情報を表示することをアプリに許可します。" - "WiMAX状態の変更" + "WiMAX状態の変更" "タブレットのWiMAXネットワークへの接続と切断をアプリに許可します。" "テレビのWiMAXネットワークへの接続と切断をアプリに許可します。" "携帯端末のWiMAXネットワークへの接続と切断をアプリに許可します。" @@ -420,7 +420,7 @@ "指紋ハードウェアを認証に使用することをアプリに許可します" "指紋を一部しか検出できませんでした。もう一度お試しください。" "指紋を処理できませんでした。もう一度お試しください。" - "指紋センサーに汚れがあります。汚れを落としてもう一度お試しください。" + "指紋認証センサーに汚れがあります。汚れを落としてもう一度お試しください。" "指の動きが速すぎました。もう一度お試しください。" "指の動きが遅すぎました。もう一度お試しください。" @@ -485,7 +485,7 @@ "タッチスクリーンの調整パラメータの変更をアプリに許可します。通常のアプリでは必要ありません。" "DRM証明書へのアクセス権" "DRM証明書のプロビジョニングと使用をアプリに許可します。通常のアプリでは不要です。" - "Androidビーム転送のステータスを受信" + "Androidビーム転送のステータスの受信" "現在のAndroidビーム転送に関する情報を受信することをこのアプリに許可します。" "DRM証明書の削除" "DRM証明書の削除をアプリに許可します。通常のアプリでは不要です。" @@ -1091,11 +1091,11 @@ "フォーマットしています…" "挿入されていません" "一致するアクティビティが見つかりません。" - "メディア出力のルーティング" + "メディア出力のルーティング" "メディア出力を他の外部デバイスにルーティングすることをアプリに許可します。" - "インストールセッションの読み取り" + "インストールセッションの読み取り" "インストールセッションの読み取りをアプリに許可します。これにより、アプリはアクティブパッケージのインストールに関する詳細情報を参照できるようになります。" - "パッケージインストールのリクエスト" + "インストールパッケージのリクエスト" "パッケージのインストールをリクエストすることをアプリケーションに許可します。" "ダブルタップでズームコントロール" "ウィジェットを追加できませんでした。" diff --git a/core/res/res/values-ka-rGE-watch/strings.xml b/core/res/res/values-ka-rGE-watch/strings.xml index 4fe6d11a53b3a..0c2f4adc7ba5a 100644 --- a/core/res/res/values-ka-rGE-watch/strings.xml +++ b/core/res/res/values-ka-rGE-watch/strings.xml @@ -21,4 +21,5 @@ "აპი %1$d, სულ %2$d-დან." + "სენსორები" diff --git a/core/res/res/values-ka-rGE/cm_strings.xml b/core/res/res/values-ka-rGE/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-ka-rGE/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index d88adcbc57183..75f07b6ef79f8 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -254,7 +254,7 @@ "შეიცავს ისეთ პირად მონაცემებს, როგორიცაა საკრედიტო ბარათის ნომრები და პაროლები." "სტატუსის ზოლის გათიშვა ან ცვლილება" "აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა." - "სტატუსის ზოლი" + "სტატუსის ზოლის ჩანაცვლება" "აპს შეეძლება სტატუსის ზოლის ჩანაცვლება." "სტატუსების ზოლის გაფართოება/აკეცვა" "აპს შეეძლება სტატუსის ზოლის გახსნა-დახურვა." @@ -282,7 +282,7 @@ "აპს შეეძლება WAP შეტყობინებების მიღება და გენერირება. ამ უფლებით აპი ისე დააკვირდება და წაშლის თქვენთვის გამოგზავნილ შეტყობინებებს, რომ თქვენ ვერც ნახავთ." "მოქმედი აპების მოძიება" "აპს შეეძლება მოიძიოს ინფორმაცია ამჟამად და უახლოეს წარსულში მიმდინარე ამოცანების შესახებ. ამგვარად, აპს აქვს შესაძლებლობა აღმოაჩინოს ინფორმაცია იმის შესახებ, თუ რომელი აპლიკაციებია გამოყენებული მოწყობილობაზე." - "პროფილისა და მოწყობილობის მფლობელების მართვა" + "პროფილისა და მოწყობილობის მფლობელების მართვა" "აპებს უფლებას აძლევს, დააყენოს პროფილის მფლობელები და მოწყობილობის მფლობელი." "მოქმედი აპების წყობის შეცვლა" "აპს შეეძლება ამოცანების გადატანა წინა და უკანა პლანზე. ამას თქვენი ჩარევის გარეშე გააკეთებს." @@ -324,7 +324,7 @@ "აპს შეეძლება, შეცვალოს თქვენი ტაბლეტის ზარების ჟურნალი, მათ შორის შემომავალი და გამავალი ზარების მონაცემები. მავნე აპებმა შეიძლება გამოიყენონ ეს თქვენი ზარების ჟურნალის წასაშლელად ან შესაცვლელად." "ნებას რთვს აპლიკაციას, შეცვალოს თქვენი ტელევიზორის ზარების ჟურნალი, შემომავალი და გამავალი ზარების მონაცემთა ჩათვლით. მავნე აპლიკაციებს შეუძლიათ ამოშალონ ან შეცვალონ თქვენი ზარების ჟურნალი." "აპს შეეძლება, შეცვალოს თქვენი ტელეფონის ზარების ჟურნალი, მათ შორის შემომავალი და გამავალი ზარების მონაცემები. მავნე აპებმა შეიძლება გამოიყენონ ეს თქვენი ზარების ჟურნალის წასაშლელად ან შესაცვლელად." - "სხეულის სენსორები (მაგ. გულისცემის მონიტორები)" + "სხეულის სენსორებზე წვდომა (მაგ., გულისცემის მონიტორები)" "აპისთვის ნების დართვა, რათა მას ჰქონდეს წვდომა თქვენი ფიზიკური მდგომარეობის მონიტორინგის სენსორების მონაცემებზე." "კალენდრის ღონისძიებებისა და კონფიდენციალური ინფორმაციის წაკითხვა" "აპს შეეძლება, წაიკითხოს თქვენ ტაბლეტზე შენახული კალენდრის ყველა მოვლენა, მათ შორის მეგობრებისა და თანამშრომლების მოვლენებიც. ამან შეიძლება უფლება მისცეს აპს, გააზიაროს ან შეინახოს თქვენი კალენდრის მონაცემები, მიუხედავად კონფიდენციალურობისა თუ მგრძობიარობისა." @@ -336,15 +336,15 @@ "აპს შეეძლება იმ ღონისძიებების დამატება, წაშლა და შეცვლა, რომლებსაც თქვენს ტელეფონზე ქმნით, ასევე თქვენი მეგობრების და თანამშრომლების ღონისძიებებიც. ამგვარად, აპს ექნება შესაძლებლობა ისე დააგზავნოს შეტყობინებები კალენდრის მფლობელის სახელით ან შეცვალოს ღონისძიებები, რომ მფლობელმა ამის შესახებ არაფერი იცოდეს." "მდებარეობის პროვაიდერის დამატებით ბრძანებებზე წვდომა" "აპს შეეძლება წვდომა ჰქონდეს მდებარეობის სერვისის დამატებით ბრძანებებზე. შესაძლოა აპმა ეს გამოიყენოს GPS-ისა და მდებარეობის სხვა წყაროების მუშაობის პროცესში ჩარევისთვის." - "ზუსტი მდებარეობა (GPS და ქსელის კოორდინატების მიხედვით)" + "ზუსტ მდებარეობაზე წვდომა (GPS-ისა და ქსელის მეშვეობით)" "აძლევს აპს უფლებას მოიპოვოს ზუსტი მდებარეობა გლობალური პოზიციონირების სისტემის (GPS) გამოყენებით ან ქსელის მდებარეობის წყაროს მიხედვით, როგორიცაა ქსელის ანძები და Wi-Fi. მდებარეობის ეს სერვისები ჩართული უნდა იყოს და თქვენს მოწყობილობაზე აპისთვის მისაწვდომი, რათა შეძლოს მათი გამოყენება. აპებში შესაძლებელია მათი გამოყენება თქვენი მდებარეობის განსასაზღვრად და ამან ელემენტის დამატებითი ხარჯვა შეიძლება გამოიწვიოს." - "სავარაუდო (ქსელის კოორდინატების მიხედვით) მდებარეობა" + "მიახლოებით მდებარეობაზე წვდომა (ქსელის მეშვეობით)" "აპს შეეძლება გაიგოს თქვენი სავარაუდო მდებარეობა. ის გამოითვლება მდებარეობის სერვისის მიერ ქსელის მონაცემების - მობილური კავშირგაბმულობის ანძებისა და Wi-Fi-ის მიხედვით. ეს სერვისები ჩართული უნდა იყოს თქვენს მოწყობილობაზე, ხოლო აპებს უნდა ჰქონდეთ მათი გამოყენების უფლება. აპები მათი მონაცემების მიხედვით სავარაუდო მდებარეობის გამოთვლას შეძლებენ." "თქვენი აუდიო პარამეტრების შეცვლა" "აპს შეეძლება აუდიოს გლობალური პარამეტრების შეცვლა. მაგ.: ხმის სიმაღლე და რომელი დინამიკი გამოიყენება სიგნალის გამოსტანად." "აუდიოს ჩაწერა" "აპს შეეძლება აუდიო ჩაწერა მიკროფონით. ნებართვა აპს აუდიო ჩაწერის უფლებას აძლევს ნებისმიერ დროს, თქვენი თანხმობის გარეშე." - "კომუნიკაცია SIM-თან" + "ბრძანებების SIM-ზე გაგზავნა" "აპისთვის ნების დართვა გაუგზავნოს ბრძანებები SIM-ბარათს. ეს ძალიან საშიშია." "სურათებისა და ვიდეოების გადაღება" "აპს შეეძლება კამერით სურათისა და ვიდეოს გადაღება. ეს ნებართვა აპს უფლებას აძლევს, ნებისმიერ დროს გამოიყენოს კამერა თქვენი დადასტურების გარეშე." @@ -382,7 +382,7 @@ "აპს შეეძლება, მიიღოს ტელეფონისთვის ცნობილი ანგარიშების სია. ეს შეიძლება მოიცავდეს ნებისმიერ ანგარიშს, რომელიც თქვენ მიერ დაყენებული აპლიკაციებით შეიქმნა." "ქსელის კავშირების ნახვა" "აპს შეეძლება ქსელის კავშირის შესახებ ინფორმაციის ნახვა, მაგ. რომელი ქსელები არსებობს და რომელია დაკავშირებული." - "ქსელზე სრული წვდომა" + "ქსელზე სრული წვდომის მიღება" "აპს შეეძლება შექმნას ქსელური ბუდეები და გამოიყენოს მორგებული ქსელის პროტოკოლები. ბრაუზერი და სხვა აპლიკაციები უზრუნველყოფს ინტერნეტში მონაცემების გაგზავნის საშუალებას, ამგვარად ეს უფლება ინფორმაციის გასაგზავნად საჭირო არაა." "კავშირის მდგომარეობის/პარამეტრების შეცვლა" "აპს შეეძლება, შეცვალოს ქსელის კავშირის მდგომარეობა." @@ -402,7 +402,7 @@ "აპს შეეძლება ტელეფონის ადგილობრივი Bluetooth პარამეტრების დაყენება და დისტანციური მოწყობილობების აღმოჩენა და დაწყვილება." "WiMAX-თან დაკავშირება და კავშირის გაწყვეტა" "აპს შეეძლება განსაზღვროს, WiMAX არის თუ არა ჩართული და ასევე ინფორმაცია ნებისმიერი დაკავშირებული WiMAX ქსელის შესახებ." - "WiMAX მდგომარეობის შეცვლა" + "WiMAX-ის მდგომარეობის შეცვლა" "აპს შეეძლება, დაუკავშიროს და გამოაერთოს ტაბლეტი WiMAX ქსელებიდან." "ნებას რთავს აპლიკაციას, ჩართოს ან გამორთოს ტელევიზორი WiMAX-ის ქსელიდან." "აპს შეეძლება, დაუკავშიროს და გამოაერთოს ტელეფონი WiMAX ქსელებიდან." @@ -485,7 +485,7 @@ "საშუალებას აძლევს აპს შეცვალოს სენსორული ეკრანის კალიბრაციის პარამეტრები. ჩვეულებრივ აპებს წესით არ უნდა დაჭირდეს." "DRM სერთიფიკატებზე წვდომა" "საშუალებას აძლევს აპლიკაციას დანერგოს და გამოიყენოს DRM სერთიფიკატები. ეს უფლება ჩვეულებრივ აპებს არ ჭირდება." - "Android Beam ტრანსფერის სტატუსის მიღება" + "Android სხივით გადაცემის სტატუსის მიღება" "ნებას რთავს ამ აპლიკაციას, მიიღოს ინფორმაცია მიმდინარე Android Beam-ის ტრანსფერების შესახებ" "DRM სერტიფიკატების ამოშლა" "საშუალებას აძლევს აპლიკაციას ამოშალოს DRM სერtიფიკატები. ეს წესით ჩვეულებრივ აპებს არ უნდა დაჭირდეს." @@ -1091,11 +1091,11 @@ "დაფორმატება…" "არ არის ჩასმული" "შესატყვისი აქტივობები არ არის." - "მულტიმედია მონაცემების გადამისამართება" + "გამომავალი მედიის მარშრუტიზაცია" "აპლიკაციას შეეძლება გადაამისამართოს მულტიმედია მონაცემები სხვა გარე მოწყობილობებისკენ." - "ინსტალაციის სესიების წაკითხვა" + "ინსტალაციის სესიების წაკითხვა" "საშუალებას აძლევს აპლიკაციას წაიკითხოს ინსტალაციის სესიები. ამით მას საშუალება აქვს იხილოს პაკეტის აქტიური ინსტალაციები." - "პაკეტების ინსტალაციის მოთხოვნა" + "პაკეტების ინსტალაციის მოთხოვნა" "აპლიკაციას შეეძლება მოითხოვოს პაკეტების ინსტალაცია." "მასშტაბის მართვისთვის შეეხეთ ორჯერ." "ვერ დაემატა ვიჯეტი." diff --git a/core/res/res/values-kk-rKZ-watch/strings.xml b/core/res/res/values-kk-rKZ-watch/strings.xml index 583eb1957401d..3ba5686981f92 100644 --- a/core/res/res/values-kk-rKZ-watch/strings.xml +++ b/core/res/res/values-kk-rKZ-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d/%2$d бағдарлама." + "Сенсорлар" diff --git a/core/res/res/values-kk-rKZ/cm_strings.xml b/core/res/res/values-kk-rKZ/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-kk-rKZ/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml index f8426c97893ee..b374f47f94ded 100644 --- a/core/res/res/values-kk-rKZ/strings.xml +++ b/core/res/res/values-kk-rKZ/strings.xml @@ -254,7 +254,7 @@ "Кредит карта нөмірі және кілтсөздер сияқты жеке деректерді қоса." "күйін көрсету тақтасын өшіру немесе өзгерту" "Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді." - "күйін көрсету жолағы" + "күй жолағы болу" "Қолданбаға күй жолағы болуға рұқсат береді." "күйі жолағын кеңейту/жиыру" "Қолданбаға статус жолағын жаюға емесе тасалауға рұқсат береді." @@ -282,7 +282,7 @@ "Қолданбаға WAP хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді." "жұмыс істеп жатқан қолданбаларды шығарып алу" "Қолданбаларға ағымдағы және соңғы тапсырмалар туралы ақпарат алу мүмкіндігін береді. Бұл қолданбаға құрылғы қолданатын басқа қолданбалар туралы деректері анықтау мүмкіндігін беруі ықтимал." - "Профиль және құрылғы иелерін басқару" + "профиль және құрылғы иелерін басқару" "Қолданбаларға профиль иелері мен құрылғы иесін орнатуға мүмкіндік береді." "жұмыс істеп жатқан қолданбалардың ретін өзгерту" "Қолданбаға тапсырмаларды алғы немесе артқы шепке жылжыту мүмкіндігін береді. Қолданба бұны сіздің қатысуыңызсыз жасауы мүмкін." @@ -324,7 +324,7 @@ "Қолданбаға сіздің планшетіңіздегі қоңырау тіркеуін, келетін немесе шығатын қоңыраулар туралы деректерді қоса, өзгерту мүмкіндігін береді. Залалды қолданбалар бұны сіздің қоңырау тіркеуіңізді өшіру үшін қолдануы мүмкін." "Қолданбаға ТД қоңыраулар журналын, соның ішінде, кіріс және шығыс қоңыраулар туралы деректерді өзгертуге рұқсат етеді. Зиянкес қолданбалар мұны қоңыраулар журналын өшіру немесе өзгерту үшін пайдалануы мүмкін." "Қолданбаға сіздің телефоныңыздың қоңырау тіркеуін, келетін немесе шығатын қоңыраулар туралы деректерді қоса, өзгерту мүмкіндігін береді. Залалды қолданбалар бұны сіздің қоңырау тіркеуіңізді өшіру үшін қолдануы мүмкін." - "дене сен-ры (жүрек соғу жиіл. мон-ры сияқты)" + "дене датчиктеріне (мысалы, жүрек соғу жиілігінің мониторларына) қатынасу" "Қолданбаға жүрек соғу жиілігіңіз сияқты дене күйіңізді бақылайтын сенсорлардың деректеріне қатынасуға рұқсат етеді." "күнтізбе шаралары мен құпия ақпаратты оқу" "Қолданбаға планшетте сақталған барлық күнтізбе шараларын, достар немесе әріптестердің шараларын қоса, оқу мүмкіндігін береді. Бұл қолданбаға күнтізбе деректерін, құпиялығы мен сезімталдығына қарамастан, бөлісу немесе сақтау мүмкіндігін беруі ықтимал." @@ -336,15 +336,15 @@ "Қолданбаға телефондағы сізге өзгертуге болатын шараларды, достарыңыз бен әріптестеріңіздің шараларын қоса, қосу, алу және өзгерту мүмкіндігін береді. Бұл қолданбаға күнтізбе иелерінен келген сияқты көрсетілетін хабарлар жіберу немесе иесінің хабарынсыз шараларды өзгерту мүмкіндігін береді." "қосымша аймақ жабдықтаушы пәрмендеріне қол жетімділік" "Қолданбаға орын жеткізушісінің қосымша пәрмендеріне қатынасуға рұқсат береді. Бұл қолданбаға GPS немесе басқа орын көздерінің жұмысына кедергі келтіруге рұқсат беруі мүмкін." - "нақты аймақ (GPS және желі негізделген)" + "дәл орынға қатынасу (GPS және желіге негізделген)" "Қолданбаға Жаһандық Аймақ Анықтау Жүйесін (GPS) немесе ұялы мұнара және Wi-Fi сияқты желі арқылы аймақ анықтау қызметтерін қолданып, тұрған жеріңізді нақты анықтау мүмкіндігін береді. Бұл аймақ қызметтері қолданбаларға қол жетімді болу үшін қосылып тұруы қажет. Қолданбалар оны сіздің тұрған жеріңізді шамалап анықтау үшін қолдануы мүмкін және батарея тұтынуы мүмкін." - "шамаланған аймақ (желі негізінде)" + "шамамен алған орынға қатынасу (желі негізінде)" "Қолданбаға сіздің тұрған жеріңізді шамалап анықтау мүмкіндігін береді. Бұл аймақ ұялы мұнара және Wi-Fi сияқты желі арқылы аймақ анықтау қызметтерін қолданатын аймақ анықтау функциясы арқылы анықталған. Бұл аймақ қызметтері қолданбаларға қол жетімді болу үшін қосылып тұруы қажет. Қолданбалар оны сіздің тұрған жеріңізді шамалап анықтау үшін қолдануы мүмкін." "аудио параметрлерін өзгерту" "Қолданбаға дыбыс қаттылығы және аудио шығыс үндеткішін таңдау сияқты жаһандық аудио параметрлерін өзгерту мүмкіндігін береді." "аудио жазу" "Қолданбаға микрофон арқылы аудио жазу мүмкіндігін береді. Бұл рұқсат қолданбаға кез келген уақытта сіздің құптауыңызсыз аудио жазып алу мүмкіндігін береді." - "sim байланысы" + "SIM картасына пәрмендер жіберу" "Қолданбаға SIM картасына пәрмен жіберу мүмкіндігін береді. Бұл өте қауіпті." "фотосурет жасау және бейне жазу" "Қолданбаға камераны қолданып, фотосурет немесе бейне жазу мүмкіндігін береді. Бұл рұқсат камераны кез келген уақытта сіздің құптауыңызды қажет етпей қолдану мүмкіндігін береді." @@ -382,7 +382,7 @@ "Қолданбаға телефон арқылы белгілі есептік жазбалар тізімін алу мүмкіндігін береді. Сіз орнатқан қолданбалар жасақтаған есептік жазбалар да қамтылуы мүмкін." "желі байланыстарын көру" "Қолданбаға желі байланысы туралы ақпаратты, мысалы, қайсысы бар және қосылған деген сияқты, көру мүмкіндігін береді." - "желіге толық қол жетімділік" + "желіге толық қатынасы бар" "Қолданбаларға желі ұяларын жасақтау және қалыпты желі протоколдарын қолдану мүмкіндігін береді. Деректерді интернетке жіберу үшін бұл рұқсат талап етілмес үшін браузер және басқа қолданбалар деректерді интернетке жіберу жолдарын қамтамасыз етеді." "желі байланысын өзгерту" "Қолданбаға желілік қосылым күйін өзгертуге рұқсат береді." @@ -402,7 +402,7 @@ "Қолданбаға жергілікті Bluetooth телефонын конфигурациялауға, әрі қашықтағы құрылғыларды табуға және олармен жұптауға рұқсат береді." "WiMAX байланысына жалғану және ажырау" "Қолданбаға WiMAX қосылғаны және қосылған қандай да WiMAX желісі жайлы ақпаратты анықтау мүмкіндігін береді." - "WiMAX күйін өзгерту" + "WiMAX күйін өзгерту" "Қолданбаларға планшетті WiMAX желілеріне қосу және ажырату мүмкіндіктерін береді." "Қолданбаға теледидарға қосылуға және теледидарды WiMAX желілерінен ажыратуға рұқсат етеді." "Қолданбаларға телефонды WiMAX желілеріне қосу және ажырату мүмкіндіктерін береді." @@ -485,7 +485,7 @@ "Қолданбаға сенсорлы экранның параметрлерін өзгертуге рұқсат береді. Қалыпты қолданбалар үшін ешқашан қажет болмайды." "DRM сертификаттарына қатынасу" "Қолданбаға DRM сертификаттарын қамтамасыз етуге және пайдалануға рұқсат береді. Қалыпты қолданбалар үшін ешқашан қажет болмайды." - "Android Beam тасымалдау күйін алу" + "Android Beam тасымалдау күйін алу" "Осы қолданбаға ағымдағы Android Beam тасымалдаулары туралы ақпарат алуға рұқсат ету" "DRM сертификаттарын жою" "Қолданбаға DRM сертификаттарын жоюға рұқсат етеді. Қалыпты қолданбалар үшін ешқашан қажет болмайды." @@ -1091,11 +1091,11 @@ "Пішімделуде..." "Салынбады" "Сәйкес әрекеттер табылмады." - "Медиа шығысын бағыттау" + "медиа шығысын бағыттау" "Қолданбаға медиа шығысын басқа сыртқы құрылғыларға бағыттау мүмкіндігін береді." - "Орнату сеанстарын оқу" + "орнату сеанстарын оқу" "Қолданбаға орнату сеанстарын оқуға рұқсат етеді. Бұл оған белсенді бума орнатулары туралы мәліметтерді көруге рұқсат етеді." - "Бумаларды орнатуға рұқсат сұрау" + "орнату бумаларын сұрау" "Қолданбаның бумаларды орнатуға рұқсат сұрауына мүмкіндік береді." "Масштабтауды басқару үшін екі рет түртіңіз" "Виджетті қосу." diff --git a/core/res/res/values-km-rKH-watch/strings.xml b/core/res/res/values-km-rKH-watch/strings.xml index 2b7e12f634d16..624aab7393e8b 100644 --- a/core/res/res/values-km-rKH-watch/strings.xml +++ b/core/res/res/values-km-rKH-watch/strings.xml @@ -21,4 +21,5 @@ "កម្មវិធី %1$d នៃ %2$d។" + "ឧបករណ៍ចាប់សញ្ញា" diff --git a/core/res/res/values-km-rKH/cm_strings.xml b/core/res/res/values-km-rKH/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-km-rKH/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index 97ac9eb8b9376..eb9771130c591 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -254,7 +254,7 @@ "រួម​បញ្ចូល​ទិន្នន័យ​ផ្ទាល់​ខ្លួន​ ដូចជា​លេខ​កាត​ឥណទាន និង​ពាក្យ​សម្ងាត់។" "បិទ ឬ​កែ​របារ​ស្ថានភាព" "ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។" - "របារ​ស្ថានភាព" + "ធ្វើជារបារស្ថានភាព" "ឲ្យ​កម្មវិធី​ក្លាយ​ជា​របារ​ស្ថានភាព។" "ពង្រីក/បង្រួម​របារ​ស្ថាន​ភាព" "ឲ្យ​កម្មវិធី​ពង្រីក ឬ​បង្រួម​របារ​ស្ថានភាព។" @@ -282,7 +282,7 @@ "ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​សារ WAP ។ សិទ្ធិ​នេះ​​មានលទ្ធភាព​តាមដាន ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ឲ្យ​អ្នក​ដោយ​មិន​បង្ហា​ញ។" "ទៅ​យក​កម្មវិធី​កំពុង​ដំណើរការ" "ឲ្យ​កម្មវិធី​ទៅ​យក​ព័ត៌មាន​លម្អិត​អំពី​កិច្ចការ​ដែល​កំពុង​ដំណើរការ​បច្ចុប្បន្ន។ វា​អាច​ឲ្យ​កម្មវិធី​រកមើល​ព័ត៌មាន​ថា​តើ​កម្មវិធី​ណាមួយ​ត្រូវ​បាន​ប្រើ​លើ​ឧបករណ៍។" - "គ្រប់គ្រងម្ចាស់ឧបករណ៍ និងប្រវត្តិរូប" + "គ្រប់គ្រងម្ចាស់ឧបករណ៍ និងប្រវត្តិរូប" "អនុញ្ញាតឲ្យកម្មវិធីកំណត់ម្ចាស់ប្រវត្តិរូប និងម្ចាស់ឧបករណ៍។" "តម្រៀប​កម្មវិធី​កំពុង​ដំណើរការ​ឡើងវិញ" "ឲ្យ​កម្មវិធី​ផ្លាស់ទី​ភារកិច្ច​​ទៅ​ផ្ទៃ​ខាង​មុខ។​ កម្មវិធី​អាច​ធ្វើ​វា​ដោយ​គ្មាន​ការ​បញ្ចូល​របស់​អ្នក។" @@ -324,7 +324,7 @@ "ឲ្យ​កម្មវិធី​កែ​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។​កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប ឬ​កែ​បញ្ជី​ហៅ​របស់​អ្នក។" "អនុញ្ញាតឲ្យកម្មវិធីកែសម្រួលកំណត់ហេតុហៅទូរស័ព្ទទូរទស្សន៍របស់អ្នក ដោយរាប់បញ្ចូលទាំងទិន្នន័យអំពីការហៅចូល និងការហៅចេញ។ កម្មវិធីព្យាបាទអាចប្រើវាដើម្បីលុប ឬកែសម្រួលកំណត់ហេតុការហៅទូរស័ព្ទរបស់អ្នក។" "ឲ្យ​កម្មវិធី​កែ​បញ្ជី​ហៅ​នៃ​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប ឬ​កែ​បញ្ជី​ការ​ហៅ​របស់​អ្នក។" - "ឧបករណ៍ចាប់សញ្ញារាងកាយ(ដូចជាម៉ាស៊ីនវាស់ចង្វាក់បេះដូង)" + "ចូលដំណើរការឧបករណ៍ចាប់សញ្ញារាងកាយ (ដូចជាម៉ាស៊ីនវាស់ចង្វាក់បេះដូង)" "ឲ្យ​កម្មវិធី​ចូល​ដំណើរការ​ទិន្នន័យ​ពី​ឧបករណ៍​ចាប់​សញ្ញា​ដែល​តាមដាន​លក្ខខណ្ឌ​សុខភាព​របស់​អ្នក ដូច​ជា​ចង្វាក់​បេះដូង។" "អាន​ព្រឹត្តិការណ៍​ប្រតិទិន​​និង​ព័ត៌មាន​សម្ងាត់" "ឲ្យ​កម្មវិធី​អាច​​ព្រឹត្តិការណ៍​ប្រតិទិន​ទាំងអស់​ដែល​បាន​រក្សាទុក​ក្នុង​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​មិត្តភ័ក្ដិ និង​មិត្ត​រួម​ការងារ។ វា​អាច​ឲ្យ​កម្មវិធី​ចែករំលែក​ ឬ​រក្សាទុក​ទិន្នន័យ​ប្រតិទិន​របស់​អ្នក​​ដោយ​មិន​គិត​ពី​ការ​សម្ងាត់ ឬ​ការ​យល់​ដឹង។" @@ -336,15 +336,15 @@ "ឲ្យ​កម្មវិធី​បន្ថែម លុប ឬ​ប្ដូរ​ព្រឹត្តិការណ៍​ដែល​អ្នក​អាច​កែប្រែ​លើ​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​មិត្តភ័ក្ដិ ឬ​មិត្ត​រួម​ការងារ។ វា​​អាច​ឲ្យ​កម្មវិធី​ផ្ញើ​សារ​ដែល​បង្ហាញ​ថា​មក​ពី​ម្ចាស់​ប្រតិទិន ឬ​កែ​ព្រឹត្តិការណ៍​ដោយ​មិន​ឲ្យ​​អ្នក​ដឹង។" "ចូល​ដំណើរការ​ពាក្យ​បញ្ជា​ក្រុមហ៊ុន​ផ្ដល់​ទីតាំង" "ឲ្យ​កម្មវិធី​ចូល​ដំណើរការ​ពាក្យ​បញ្ជា​កម្មវិធី​ផ្ដល់​​ទីតាំង​បន្ថែម។ វា​អាច​អនុញ្ញាត​ឲ្យ​កម្មវិធី​ទាក់ទង​ជា​មួយ​ប្រតិបត្តិការ​ជីភីអេស ឬ​ប្រភព​ទីតាំង​ផ្សេង។" - "ទីតាំង​ពិតប្រាកដ (GPS និង​មាន​មូលដ្ឋាន​លើ​បណ្ដាញ)" + "ចូលដំណើរការទីតាំងច្បាស់លាស់ (ផ្អែកលើបណ្តាញ និង GPS)" "ឲ្យ​កម្មវិធី​ទទួល​ទីតាំង​ពិតប្រាកដ​របស់​អ្នក ដោយ​ប្រើ​ប្រព័ន្ធ​កំណត់​ទីតាំង​សកម្ម (GPS) ឬ​ប្រភព​ទីតាំង​បណ្ដាញ​ដូច​ជា អង់តែន​ចល័ត និង​វ៉ាយហ្វាយ។ សេវាកម្ម​ទីតាំង​ទាំង​នេះ​ត្រូវតែ​បើក និង​អាច​ប្រើ​ចំពោះ​ឧបករណ៍​របស់​អ្នក​សម្រាប់​កម្មវិធី​ដែល​ប្រើ​ពួក​វា។ កម្មវិធី​អាច​ប្រើ​វា ដើម្បី​កំណត់​​ទីកន្លែង​របស់​អ្នក និង​អាច​ប្រើ​ថាមពល​ថ្ម​បន្ថែម។" - "ទីតាំង​ប្រហាក់ប្រហែល (​​មាន​មូលដ្ឋាន​លើ​បណ្ដាញ)" + "ចូលដំណើរការទីតាំងប្រហាក់ប្រហែល (ផ្អែកលើបណ្តាញ)" "ឲ្យ​កម្មវិធី​ទទួល​ទីតាំង​ប្រហាក់ប្រហែល។ ទីតាំង​នេះ​ត្រូវ​បាន​ទទួល​តាម​សេវាកម្ម​ទីតាំង​ដោយ​ប្រើ​ប្រភព​ទីតាំង​បណ្ដាញ​ដូច​ជា អង់តែន និង​វ៉ាយហ្វាយ។ សេវាកម្ម​ទីតាំង​ទាំង​នេះ​ត្រូវ​តែ​បើក និង​អាច​ប្រើ​បាន​ចំពោះ​ឧបករណ៍​របស់​អ្នក​សម្រាប់​កម្មវិធី​ដែល​ប្រើ​ពួកវា។ កម្មវិធី​អាច​ប្រើ​វា ដើម្បី​កំណត់កន្លែង​ដែល​អ្នក​នៅ​ប្រហាក់ប្រហែល។" "ប្ដូរ​ការ​កំណត់​អូឌីយូ​របស់​អ្នក" "ឲ្យ​កម្មវិធី​កែ​ការ​កំណត់​សំឡេង​សកល ដូច​ជា​កម្រិត​សំឡេង និង​អូប៉ាល័រ​ដែល​បាន​ប្រើ​សម្រាប់​លទ្ធផល។" "ថត​សំឡេង" "​ឱ្យ​កម្មវិធី​ថត​សំឡេង​​ជាមួយ​មីក្រូហ្វូន​​​។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​ថត​សំឡេង​​នៅ​ពេល​ណា​មួយ​ដោយ​គ្មាន​ការ​បញ្ជាក់​របស់​អ្នក។" - "ការ​ភ្ជាប់​ស៊ីមកាត" + "ផ្ញើពាក្យបញ្ជាទៅស៊ីមកាត" "ឲ្យ​កម្មវិធី​ផ្ញើ​ពាក្យ​បញ្ជា​ទៅ​ស៊ីម​កាត។ វា​គ្រោះ​ថ្នាក់​ណាស់។" "ថត​រូប និងវីដេអូ" "ឲ្យ​កម្មវិធី​ថត​រូប និង​វីដេអូ​ដោយ​ប្រើ​ម៉ាស៊ីន​ថត។ វា​ឲ្យ​កម្មវិធី​​ប្រើ​ម៉ាស៊ីន​ថត​នៅ​ពេល​​ណាមួយ​ដោយ​គ្មាន​ការ​បញ្ជាក់​របស់​អ្នក។" @@ -382,7 +382,7 @@ "ឲ្យ​កម្មវិធី​ទទួល​បញ្ជី​គណនី​ដែល​ទូរស័ព្ទ​​បាន​ស្គាល់​។ វា​អាច​មាន​គណនី​ដែល​បាន​បង្កើត​ដោយ​កម្មវិធី​ដែល​អ្នក​បាន​ដំឡើង។" "មើល​ការ​តភ្ជាប់​បណ្ដាញ" "ឲ្យ​កម្មវិធី​មើល​ព័ត៌មាន​អំពី​ការ​តភ្ជាប់​បណ្ដាញ​ដូចជា​​មាន​បណ្ដាញ​ណាមួយ​ និង​បណ្ដាញ​ត្រូវ​បាន​ភ្ជាប់។" - "ចូល​ដំណើរការ​បណ្ដាញ​ពេញ​លេញ" + "មានការចូលដំណើរការបណ្ដាញពេញលេញ" "ឲ្យ​កម្មវិធី​បង្កើត​រន្ធ​បណ្ដាញ​ និង​ប្រើ​ពិធីការ​បណ្ដាញ​តាម​បំណង។ កម្មវិធី​អ៊ីនធឺណិត​ និង​កម្មវិធី​ផ្សេង​ៗ​ផ្ដល់​វិធី​ផ្ញើ​ទិន្នន័យ​ទៅ​អ៊ីនធឺណិត ដូច្នេះ​សិទ្ធិ​នេះ​មិន​ទាមទារ​ឲ្យ​ផ្ញើ​ទិន្នន័យ​ទៅ​អ៊ីនធឺណិត។" "ប្ដូរ​ការ​តភ្ជាប់​បណ្ដាញ" "ឲ្យ​កម្មវិធី​ប្ដូរ​ស្ថានភាព​តភ្ជាប់​បណ្ដាញ។" @@ -402,7 +402,7 @@ "ឲ្យ​កម្មវិធី​មើល​​ការ​កំណត់​រចនាសម្ព័ន្ធ​ប៊្លូធូស​ក្នុង​ទូរស័ព្ទ ដើម្បី​រកមើល និង​ផ្គូផ្គង​ជា​មួយ​ឧបករណ៍​ពី​ចម្ងាយ។" "ភ្ជាប់ និង​ផ្ដាច់​ពី WiMAX" "ឲ្យ​កម្មវិធី​កំណត់​ថា​តើ WiMAX ត្រូវ​បាន​បើក និង​ព័ត៌មាន​អំពី​បណ្ដាញ WiMAX ដែល​ត្រូវ​បាន​តភ្ជាប់។" - "ប្ដូរ​ស្ថានភាព WiMAX" + "ប្ដូរ​ស្ថានភាព WiMAX" "ឲ្យ​កម្មវិធី​តភ្ជាប់​ និង​ផ្ដាច់​កុំព្យូទ័រ​បន្ទះ​ពី​បណ្ដាញ WiMAX ។" "អនុញ្ញាតឲ្យកម្មវិធីភ្ជាប់ទៅទូរទស្សន៍ ហើយផ្តាច់ទូរទស្សន៍ពីបណ្តាញ WiMAX។" "ឲ្យ​កម្មវិធី​ភ្ជាប់​ទូរស័ព្ទ​ និង​ផ្ដាច់​ពី​បណ្ដាញ WiMAX ។" @@ -485,7 +485,7 @@ "ឲ្យ​​កម្មវិធី​កែ​ប៉ារ៉ាម៉ែត្រ​កែ​ចំណុច​​នៃ​ការ​ប៉ះ​អេក្រង់។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។" "ចូល​មើល​វិញ្ញាបនបត្រ DRM" "ឲ្យ​កម្មវិធី​ផ្ដល់ និង​ប្រើ​វិញ្ញាបនបត្រ DRM ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។" - "ទទួល​ស្ថានភាព​ផ្ទេរ Android Beam" + "ទទួលបានស្ថានភាពផ្ទេរ Android Beam" "ឲ្យ​កម្មវិធី​ទទួល​ព័ត៌មាន​អំពី​ការ​ផ្ទេរ​​ Android Beam បច្ចុប្បន្ន" "លុប​​វិញ្ញាបនបត្រ DRM ចេញ" "អនុញ្ញាត​ឲ្យ​​កម្មវិធី​លុប​ចេញ​វិញ្ញាបនបត្រ DRM ​។ គួរ​តែ​មិន​ត្រូវការ​សម្រាប់​កម្មវិធី​ធម្មតា​។" @@ -1093,11 +1093,11 @@ "កំពុងសម្អាត…" "មិនបានដាក់ចូលទេ" "រក​មិន​ឃើញ​សកម្មភាព​ផ្គូផ្គង។" - "នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ" + "នាំផ្លូវលទ្ធផលមេឌៀ" "ឲ្យ​កម្មវិធី​នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ​ទៅ​ឧបករណ៍​​ខាង​ក្រៅ​ផ្សេង។" - "អាន​សម័យ​ដំឡើង" + "អានវេនដំឡើង" "ឲ្យ​កម្មវិធី​អាន​សម័យ​ដំឡើង។ វា​អនុញ្ញាត​ឲ្យ​ឃើញ​ព័ត៌មាន​លម្អិត​អំពី​​ការដំឡើង​កញ្ចប់​សកម្ម។" - "ស្នើសុំដំឡើងកញ្ចប់" + "ស្នើសុំកញ្ចប់ដំឡើង" "អនុញ្ញាតឲ្យកម្មវិធីស្នើសុំដំឡើងកញ្ចប់ (ឯកសារ/មាតិកា)។" "ប៉ះ​ពីរ​ដង ​​ដើម្បី​គ្រប់គ្រង​ការ​ពង្រីក" "មិន​អាច​បន្ថែម​ធាតុ​ក្រាហ្វិក។" diff --git a/core/res/res/values-kn-rIN-watch/strings.xml b/core/res/res/values-kn-rIN-watch/strings.xml index e01cee174f713..4738ad569e03b 100644 --- a/core/res/res/values-kn-rIN-watch/strings.xml +++ b/core/res/res/values-kn-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d ರಲ್ಲಿ %1$d ಅಪ್ಲಿಕೇಶನ್." + "ಸೆನ್ಸರ್‌ಗಳು" diff --git a/core/res/res/values-kn-rIN/cm_strings.xml b/core/res/res/values-kn-rIN/cm_strings.xml new file mode 100644 index 0000000000000..8497c9890c0d9 --- /dev/null +++ b/core/res/res/values-kn-rIN/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + ಸ್ಕ್ರೀನ್‍ಶಾಟ್ + + ಸಂರಕ್ಷಿತ ಎಸ್ಎಂಎಸ್ ಸ್ವೀಕರಿಸಿ + + ಆಪ್‍ಗೆ ಒಳಬರುವ ಸಂರಕ್ಷಿತ ಎಸ್ಎಂಎಸ್ ಸ್ವೀಕರಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. + + ಸಂರಕ್ಷಿತ ಎಸ್ಎಂಎಸ್ ಪಟ್ಟಿ ಮಾರ್ಪಡನೆ + + ಆಪ್‍ಗೆ ಸಂರಕ್ಷಿತ ಎಸ್‍ಎಂಎಸ್ ವಿಳಾಸ ಪಟ್ಟಿಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. + + ಭದ್ರತೆ + + ಸಾಧನ ಭದ್ರತೆ ಮಾಹಿತಿಗೆ ಸಂಬಂಧಿಸಿದ ಅನುಮತಿಗಳು. + + ಫೋನ್ ಬ್ಲಾಕ್‍ಪಟ್ಟಿಯನ್ನು ಓದು + + ಆಪ್‍ಗೆ ಒಳಬರುವ ಕರೆಗಳನ್ನು ಅಥವಾ ಸಂದೇಶಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾದ ದೂರವಾಣಿ ಸಂಖ್ಯೆಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಓದಲು ಅನುಮತಿಸುತ್ತದೆ. + + ಫೋನ್ ಬ್ಲಾಕ್‍ಪಟ್ಟಿ ಬದಲಾವಣೆ + + ಆಪ್‍ಗೆ ಒಳಬರುವ ಕರೆ ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾದ ಸಂಖ್ಯೆಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. + + ಕೀಗಾರ್ಡ್ ವಾಲ್‍ಪೇಪರ್ ಹೊಂದಿಕೆ + + ಒಂದು ಆಪ್‍ಗೆ ಲಾಕ್ ಪರದೆಯ ವಾಲ್‍ಪೇಪರ್ ಬದಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. + + ರಿಬೂಟ್ + + ಪ್ರಸ್ತುತ + + + ರಿಬೂಟ್ + + ರಿಕವರಿ + + ಬೂಟ್‍ಲೋಡರ್ + + ಡೌನ್‍ಲೋಡ್ + + ಸಾಫ್ಟ್ ರಿಬೂಟ್ + + ರಿಬೂಟ್ + + ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ರಿಬೂಟ್ ಆಗುವುದು. + ನಿಮ್ಮ ಫೋನ್ ರಿಬೂಟ್ ಆಗುವುದು. + + ರಿಬೂಟ್ ಆಗುತ್ತಿದೆ\u2026 + + ಆಪ್ ಕೊಲ್ಲಲಾಗಿದೆ + + ನೆಟ್‍ವರ್ಕ್‍ನಿಂದ ಎಡಿಬಿ ಸಕ್ರಿಯಗೊಂಡಿದೆ + + ಯುಎಸ್‍ಬಿಯಿಂದ ಎಡಿಬಿ & ನೆಟ್‍ವರ್ಕ್ ಸಕ್ರಿಯಗೊಂಡಿದೆ + + ಡೀಬಗ್ಗಿಂಗ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ. + + ಎಡಿಬಿ - %1$s + ಯುಎಸ್‍ಬಿ & ನೆಟ್‍ವರ್ಕ್ + ಯುಎಸ್‍ಬಿ + ನೆಟ್‍ವರ್ಕ್ + + ಆಪ್ ಆರಂಭ ಪ್ರತಿಬಂಧ + + %s ಸ್ಥಾಪಿತವಾಗಿಲ್ಲ + + ಆದ್ಯತೆ + ಶೂನ್ಯ + + ಸಿಮ್ ಚಂದಾದಾರಿಕೆ ಬದಲಾದ ಕಾರಣ ವೈ-ಫೈ ಹಾಟ್‍ಸ್ಪಾಟನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ + + ವೈ-ಫೈ ಆಫ್ ಮಾಡಿ + + ಗೌಪ್ಯತಾ ರಕ್ಷಕವನ್ನು ಸಕ್ರಿಯ ಅಥವ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುವಿಕೆ + ಆಪ್‍ಗೆ ಇತರೆ ಆಪ್ ಗೌಪ್ಯತಾ ರಕ್ಷಕದ ಜೊತೆ ಚಲಿಸಲು ಅಗುತ್ತದೆಯೆ ಅಥವ ಇಲ್ಲವೇ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. ಒಂದು ಆಪ್ Privacy Guard ಜೊತೆ ಚಲಿಸುತ್ತಿದ್ದಲ್ಲಿ, ಅದಕ್ಕೆ ವಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವಿದಿಲ್ಲ, ಉದಾಹರಣೆಗೆ ಸಂಪರ್ಕಗಳು, ಕರೆ ಲಾಗ್ಸ್, ಅಥವ ಸಂದೇಶಗಳು. + ಗೌಪ್ಯತಾ ರಕ್ಷಕ ಸಕ್ರಿಯ + %1$sಗೆ ಖಾಸಗಿ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ + ಗೌಪ್ಯತಾ ರಕ್ಷಕ + %1$s ನೀವು ಹೀಗೆ %2$s ಬಯಸುವಿರಾ. + + ನನ್ನ ಆಯ್ಕೆಯನ್ನು ನೆನಪಿಡು + + ಕ್ಯಾಮೆರಾ ಪ್ರವೇಶ + ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸುವಿಕೆ + ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದು + ವಿಪಿಎನ್ ಸಶಕ್ತಗೊಳಿಸು + ಪವರ್ ಅಪ್ ವೇಳೆ ಆರಂಭವಾಗು + ನಿಮ್ಮ ಕರೆ ಲಾಗ್‍ನ್ನು ಅಳಿಸು + ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಅಳಿಸು + ಎಂಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸು + ನಿಮ್ಮ ಎಸ್ಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಅಳಿಸು + ಟಾಪ್‍ನಲ್ಲಿ ಕಿಟಕಿಗಳನ್ನು ಬಿಡಿಸು + ಆಪ್ ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳನ್ನು ಪಡೆ + ನಿಮ್ಮ ಸಾಧನವನ್ನು ಎಚ್ಚರವಾಗಿಡುವಿಕೆ + ದೂರವಾಣಿ ಕರೆಯನ್ನು ಮಾಡು + ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್‍ನ್ನು ನವೀಕರಿಸು + ಕರೆ ಲಾಗ್ ನವೀಕರಿಸು + ನಕಲುಫಲಕವನ್ನು ಮಾರ್ಪಡಿಸು + ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ನವೀಕರಿಸು + ಸಿಸ್ಟಂ ಸೆಟ್ಟಿಂಗ್ಸ್ ನವೀಕರಿಸು + ಧ್ವನಿಗ್ರಾಹಕವನ್ನು ಮೌನ/ಅಮೌನಿಸು + ಆಡಿಯೋ ಪ್ಲೇಮಾಡು + ಅಧಿಸೂಚನೆಯನ್ನು ಪೋಸ್ಟ್ ಮಾಡು + ಮಾಧ್ಯಮ ಪ್ರೊಜೆಕ್ಟ್ ಮಾಡು + ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರನ್ನು ಓದು + ಕರೆ ಲಾಗನ್ನು ಓದು + ನಕಲುಫಲಕವನ್ನು ಓದು + ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಓದು + ನಿಮ್ಮ ಎಂಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಓದು + ನಿಮ್ಮ ಎಸ್ಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಓದು + ಎಸ್ಎಂಎಸ್ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸು + ಆಡಿಯೋ ರಿಕಾರ್ಡ್ ಮಾಡು + ಎಂಎಂಎಸ್ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸು + ಎಸ್ಎಂಎಸ್ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸು + ಪವರ್ ಅಪ್ ವೇಳೆ ಆರಂಭವಾಗು + ಟೋಸ್ಟ್ ಸಂದೇಶಗಳನ್ನು ಪ್ರದರ್ಶಿಸು + ಟಾಗಲ್ ಬ್ಲೂಟೂತ್ + ಮೊಬೈಲ್ ಡಾಟಾ ಟಾಗಲ್ ಮಾಡು + ಟಾಗಲ್ NFC + Wi-Fi ಟಾಗಲ್ ಮಾಡು + ಅಲಾರಂ ವಾಲ್ಯೂಂ ನಿಯಂತ್ರಿಸು + ಆಡಿಯೋ ಫೋಕಸ್ ನಿಯಂತ್ರಿಸು + ಬ್ಲೂಟೂತ್ ವಾಲ್ಯೂಂ ನಿಯಂತ್ರಿಸು + ಮಾಸ್ಟರ್ ವಾಲ್ಯೂಂ ನಿಯಂತ್ರಿಸು + ಮಾಧ್ಯಮ ಬಟನ್‍ಗಳನ್ನು ಉಪಯೋಗಿಸು + ಮಾಧ್ಯಮ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು + ಅಧಿಸೂಚನೆ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು + ರಿಂಗ್‍ಟೋನ್ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು + ಸ್ಪಾರ್ಶ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಉಪಯೋಗಿಸು + ಧ್ವನಿ ಕರೆ ವಾಲ್ಯೂಂನ್ನು ನಿಯಂತ್ರಿಸು + ಎಂಎಂಎಸ್ ಸಂದೇಶ ಬರೆ + ಎಸ್ಎಂಎಸ್ ಸಂದೇಶ ಬರೆ + ಬೆರಳಚ್ಚು ಉಪಯೋಗಿಸು + ಒಂದು ವಾಯ್ಸ್‌ಮೇಲ್‌ ಸೇರಿಸಿ + ಫೋನ್‌ ಸ್ಥಿತಿ ಅಕ್ಸೆಸ್‌ ಮಾಡಿ + Wi-Fi ನೆಟ್‌ವರ್ಕ್‌ಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ + ವಾಲ್‌ಪೇಪರ್‌ ಬದಲಿಸಿ + ಅಸಿಸ್ಟ್‌ ರಚನೆ ಬಳಸಿ + ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ತೆಗೆದುಕೊಳ್ಳಿ + ಬಾಡಿ ಸೆನ್ಸರ್ ಗಳನ್ನು ಉಪಯೋಗಿಸು + ಸೆಲ್ ಬ್ರಾಡ್ ಕ್ಯಾಸ್ಟ್ ಗಳನ್ನು ಓದು + ನಿಮ್ಮ ಸ್ಥಳ ಅಣಕು ಮಾಡಿ + ಬಾಹ್ಯ ಸಂಗ್ರಹ ಓದು + ಬಾಹ್ಯ ಸಂಗ್ರಹವನ್ನು ಬರೆಯಿರಿ + ಸ್ಕ್ರೀನ್ ಆನ್ ಮಾಡಿ + ಸಾಧನ ಖಾತೆಗಳನ್ನು ಪಡೆಯಿರಿ + ವೈಫೈ ಸ್ಥಿತಿ ಬದಲಿಸಿ + ರೂಟ್ ಪ್ರವೇಶ ಪಡೆ + + ಪರದೆಯನ್ನು ಅನ್‍ಪಿನ್‍ಮಾಡಲು, ಹಿಂದೆ ಬಟನ್‍ ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿಯಿರಿ. + + ಯಾವುದೇ ಸಂಪರ್ಕಗೊಂಡ ಸಾಧನವಿಲ್ಲ + %1$s ಸಂಪರ್ಕಗೊಳಿಸಿದ ಸಾಧನ + %1$s ಸಂಪರ್ಕಗೊಳಿಸಿದ ಸಾಧನಗಳು + + + + ಆಕ್ಟಿವಿಟಿ ಲಾಂಚ್‌ ಬ್ಲಾಕ್‌ ಆಗಿದೆ + ಲಾಂಚ್‌ ಆಗುವುದರಿಂದ %1$s ಸಂರಕ್ಷಿಸಲ್ಪಟ್ಟಿದೆ ದೃಢೀಕರಿಸಲು ತಟ್ಟಿ ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್‌ ಲಾಂಚ್‌ ಮಾಡಿ. + + ಬ್ಯಾಟರಿ ಸಂಪೂರ್ಣವಾಗಿ ಚಾರ್ಜಾಗಿದೆ + ಬ್ಯಾಟರಿ ದೀರ್ಘಾಯುಷ್ಯ ಸುಧಾರಿಸಲು ಚಾರ್ಜರ್ ನಿಂದ ನಿಮ್ಮ ಸಾಧನವನ್ನು ಕಡಿತಗೊಳಿಸಿ. + + ಬ್ಯಾಟರಿ ಅಂಕಿಅಂಶಗಳನ್ನು ಮರುಹೊಂದಿಸು + + ಒಂದು ಅಪ್ಲಿಕೇಶನ್‍ಗೆ ಪ್ರಸ್ತುತ ಕಡಿಮೆ-ಮಟ್ಟದ ಬ್ಯಾಟರಿ ಬಳಕೆ ಡೇಟಾವನ್ನು ಮರುಹೊಂದಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. + + diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml index 41762b112d90a..040e15a28618c 100644 --- a/core/res/res/values-kn-rIN/strings.xml +++ b/core/res/res/values-kn-rIN/strings.xml @@ -254,7 +254,7 @@ "ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳು ಮತ್ತು ಪಾಸ್‌ವರ್ಡ್‌ಗಳಂತಹ ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ." "ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ" "ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ." - "ಸ್ಥಿತಿ ಪಟ್ಟಿ" + "ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು" "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿ ಅನುಮತಿಸುತ್ತದೆ." "ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ವಿಸ್ತರಿಸಿ/ಸಂಕುಚಿಸಿ" "ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ವಿಸ್ತರಿಸಲು ಅಥವಾ ಸಂಕುಚಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ." @@ -282,7 +282,7 @@ "WAP ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು, ನಿಮಗೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡುವ ಅಥವಾ ಅಳಿಸುವ ಸಾಮರ್ಥ್ಯವನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ." "ರನ್‌ ಆಗುತ್ತಿರುವ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹಿಂಪಡೆಯಿರಿ" "ಪ್ರಸ್ತುತವಿರುವ ಮತ್ತು ಇತ್ತೀಚಿಗೆ ಚಾಲ್ತಿಯಾಗಿರುವ ಕಾರ್ಯಗಳ ಕುರಿತ ಮಾಹಿತಿಯನ್ನು ಮರುಪಡೆದುಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ಸಾಧನದಲ್ಲಿ ಯಾವ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬಳಸಲಾಗಿದೆ ಎಂಬುದರ ಕುರಿತ ಮಾಹಿತಿಯನ್ನು ಅನ್ವೇಷಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸಬಹುದು." - "ಪ್ರೊಫೈಲ್ ಮತ್ತು ಸಾಧನ ಮಾಲೀಕರನ್ನು ನಿರ್ವಹಿಸಿ" + "ಪ್ರೊಫೈಲ್ ಮತ್ತು ಸಾಧನ ಮಾಲೀಕರನ್ನು ನಿರ್ವಹಿಸಿ" "ಪ್ರೊಫೈಲ್ ಮಾಲೀಕರು ಮತ್ತು ಸಾಧನ ಮಾಲೀಕರನ್ನು ಹೊಂದಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅನುಮತಿಸುತ್ತದೆ." "ರನ್‌ ಆಗುತ್ತಿರುವ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಮರುಕ್ರಮಗೊಳಿಸಿ" "ಮುನ್ನೆಲೆ ಮತ್ತು ಹಿನ್ನಲೆಗೆ ಕಾರ್ಯಗಳನ್ನು ಸರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ನಿಮ್ಮ ಇನ್‍‍ಪುಟ್ ಇಲ್ಲದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಈ ಕಾರ್ಯವನ್ನು ಮಾಡಬಹುದು." @@ -324,7 +324,7 @@ "ಒಳಬರುವ ಮತ್ತು ಹೊರಹೋಗುವ ಕರೆಗಳ ಕುರಿತ ಡೇಟಾ ಸೇರಿದಂತೆ, ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನ ಕರೆಯ ಲಾಗ್ ಅನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳು ನಿಮ್ಮ ಕರೆಯ ಲಾಗ್‍ ಅನ್ನು ಅಳಿಸಲು ಅಥವಾ ಮಾರ್ಪಡಿಸಲು ಇದನ್ನು ಬಳಸಿಕೊಳ್ಳಬಹುದು." "ಒಳಬರುವ ಮತ್ತು ಹೊರಹೋಗುವ ಕರೆಗಳ ಕುರಿತು ಡೇಟಾ ಸೇರಿದಂತೆ ನಿಮ್ಮ ಟಿವಿಯ ಕರೆಯ ಲಾಗ್ ಅನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳು ನಿಮ್ಮ ಕರೆಯ ಲಾಗ್‍ ಅನ್ನು ಅಳಿಸಲು ಅಥವಾ ಮಾರ್ಪಡಿಸಲು ಇದನ್ನು ಬಳಸಿಕೊಳ್ಳಬಹುದು." "ಒಳಬರುವ ಮತ್ತು ಹೊರಹೋಗುವ ಕರೆಗಳ ಕುರಿತ ಡೇಟಾ ಸೇರಿದಂತೆ, ನಿಮ್ಮ ಫೋನ್‍‍ನ ಕರೆಯ ಲಾಗ್ ಅನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳು ನಿಮ್ಮ ಕರೆಯ ಲಾಗ್‍ ಅನ್ನು ಅಳಿಸಲು ಅಥವಾ ಮಾರ್ಪಡಿಸಲು ಇದನ್ನು ಬಳಸಿಕೊಳ್ಳಬಹುದು." - "ದೇಹದ ಸಂವೇದಗಳು (ಹೃದಯದ ರೇಟ್‌ ಮಾನಿಟರ್‌ಗಳಂತಹ)" + "ದೇಹ ಸೆನ್ಸರ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಿ (ಹೃದಯದ ಬಡಿತ ಮಾನಿಟರ್‌ಗಳಂತಹ)" "ನಿಮ್ಮ ಹೃದಯ ಬಡಿತದಂತಹ ನಿಮ್ಮ ದೈಹಿಕ ಸ್ಥಿತಿಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ಸೆನ್ಸರ್‌‌ಗಳಿಂದ ಡೇಟಾ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ." "ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳು ಅಲ್ಲದೇ ಗೌಪ್ಯತೆ ಮಾಹಿತಿಯನ್ನು ಓದಿರಿ" "ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ಸ್ನೇಹಿತರ ಅಥವಾ ಸಹೋದ್ಯೋಗಿಗಳ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳೂ ಸೇರಿದಂತೆ, ಎಲ್ಲಾ ಕ್ಯಾಲೆಂಡರ್ ಈವೆಂಟ್‌ಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸಿಕೊಡುತ್ತದೆ. ಇದು ಗೌಪ್ಯತೆ ಮತ್ತು ಸೂಕ್ಷ್ಮತೆಯನ್ನು ಲೆಕ್ಕಿಸದೆಯೇ, ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಮತ್ತು ಉಳಿಸಿಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸಬಹುದು." @@ -336,15 +336,15 @@ "ನಿಮ್ಮ ಫೋನ್‍‍ನಲ್ಲಿ ನಿಮ್ಮ ಸ್ನೇಹಿತರು ಅಥವಾ ಸಹೋದ್ಯೋಗಿಗಳ ಈವೆಂಟ್‌ಗಳೂ ಸೇರಿದಂತೆ, ನೀವು ಮಾರ್ಪಡಿಸಬಹುದಾದ ಈವೆಂಟ್‍‍ಗಳನ್ನು ಸೇರಿಸಲು, ತೆಗೆದುಹಾಕಲು, ಬದಲಾಯಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ಕ್ಯಾಲೆಂಡರ್‍ ಮಾಲೀಕರಿಂದ ಬಂದಿರುವಂತೆ ಗೋಚರಿಸುವ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಇಲ್ಲವೇ ಮಾಲೀಕರ ಗಮನಕ್ಕೆ ತರದೆಯೇ, ಈವೆಂಟ್‌ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸಬಹುದು." "ಹೆಚ್ಚುವರಿ ಸ್ಥಾನ ಪೂರೈಕೆದಾರರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಿ" "ಹೆಚ್ಚಿನ ಸ್ಥಾನ ಪೂರೈಕೆದಾರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಇದು GPS ಅಥವಾ ಇತರ ಸ್ಥಾನ ಮೂಲಗಳ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಮಧ್ಯ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸಬಹುದು." - "ನಿಖರ ಸ್ಥಳ (GPS ಮತ್ತು ನೆಟ್‍ವರ್ಕ್-ಆಧಾರಿತ)" + "ನಿಖರ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ (GPS ಮತ್ತು ನೆಟ್‍ವರ್ಕ್-ಆಧಾರಿತ)" "ಗ್ಲೊಬಲ್ ಪೊಸಿಷನಿಂಗ್ ಸಿಸ್ಟಮ್ (GPS) ಅಥವಾ ಸೆಲ್ ಟವರ್‍‍ಗಳು ಮತ್ತು Wi-Fi ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಸ್ಥಾನ ಮೂಲಗಳನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ನಿಖರವಾದ ಸ್ಥಾನವನ್ನು ಪಡೆಯಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಅಪ್ಲಿಕೇಶನ್‍‍ಗಾಗಿ ಅವುಗಳನ್ನು ಬಳಸಲು ಈ ಸ್ಥಾನ ಸೇವೆಗಳು ಆನ್ ಆಗಿರಬೇಕು ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಲಭ್ಯವಿರಬೇಕು. ನೀವೆಲ್ಲಿರುವಿರಿ ಎಂಬುದನ್ನು ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ ಇದನ್ನು ಬಳಸಬಹುದು ಮತ್ತು ಹೆಚ್ಚುವರಿ ಬ್ಯಾಟರಿ ಶಕ್ತಿಯನ್ನು ಬಳಸಬಹುದು." - "ಅಂದಾಜು ಸ್ಥಳ (ನೆಟ್‍ವರ್ಕ್-ಆಧಾರಿತ)" + "ಅಂದಾಜು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ (ನೆಟ್‌ವರ್ಕ್-ಆಧಾರಿತ)" "ನಿಮ್ಮ ಅಂದಾಜು ಸ್ಥಳವನ್ನು ಪಡೆದುಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಈ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‍‍ಗಳು ಮತ್ತು Wi-Fi ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಸ್ಥಾನದ ಮೂಲಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಸ್ಥಳದ ಸೇವೆಗಳ ಮೂಲಕ ಪಡೆಯಲಾಗಿದೆ. ಅಪ್ಲಿಕೇಶನ್‍‍ಗಾಗಿ ಅವುಗಳನ್ನು ಬಳಸಲು ಈ ಸ್ಥಾನ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಲಭ್ಯವಿರಬೇಕು. ನೀವು ನಿಖರವಾಗಿ ಎಲ್ಲಿರುವಿರಿ ಎಂಬುದನ್ನು ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಇದನ್ನು ಬಳಸಬಹುದು." "ನಿಮ್ಮ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ" "ವಾಲ್ಯೂಮ್ ರೀತಿಯ ಮತ್ತು ಔಟ್‍‍ಪುಟ್‍‍ಗಾಗಿ ಯಾವ ಸ್ಪೀಕರ್ ಬಳಸಬೇಕು ಎಂಬ ರೀತಿಯ ಜಾಗತಿಕ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ." "ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ" "ಮೈಕ್ರೋಫೋನ್ ಮೂಲಕ ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಖಾತರಿ ಇಲ್ಲದೆಯೇ, ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ." - "ಸಿಮ್ ಸಂವಹನ" + "ಸಿಮ್‌ಗೆ ಆಜ್ಞೆಗಳನ್ನು ಕಳುಹಿಸಿ" "ಸಿಮ್‌ ಗೆ ಆದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಇದು ತುಂಬಾ ಅಪಾಯಕಾರಿ." "ಚಿತ್ರಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಸೆರೆಹಿಡಿಯಿರಿ" "ಕ್ಯಾಮರಾ ಮೂಲಕ ಚಿತ್ರಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಸೆರೆಹಿಡಿಯಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಖಾತರಿ ಇಲ್ಲದೆಯೇ ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ." @@ -382,7 +382,7 @@ "ಫೋನ್‌ನ ಮೂಲಕ ತಿಳಿದಿರುವ ಖಾತೆಗಳ ಪಟ್ಟಿಯನ್ನು ಪಡೆದುಕೊಳ್ಳಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ನೀವು ಸ್ಥಾಪಿಸಿರುವ ಅಪ್ಲಿಕೇಶನ್ ಮೂಲಕ ರಚಿಸಲಾದ ಯಾವುದೇ ಖಾತೆಯನ್ನು ಒಳಗೊಂಡಿರಬಹುದು." "ನೆಟ್‍ವರ್ಕ್ ಸಂಪರ್ಕಗಳನ್ನು ವೀಕ್ಷಿಸಿ" "ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಮತ್ತು ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಂಪರ್ಕಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಸಂಪರ್ಕಗಳ ಕುರಿತ ಮಾಹಿತಿಯನ್ನು ವೀಕ್ಷಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ." - "ಪೂರ್ಣ ನೆಟ್‍ವರ್ಕ್ ಪ್ರವೇಶ" + "ಪೂರ್ಣ ನೆಟ್‌ವರ್ಕ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರಿ" "ನೆಟ್‍‍ವರ್ಕ್ ಸಾಕೆಟ್‍‍ಗಳನ್ನು ರಚಿಸಲು ಮತ್ತು ಕಸ್ಟಮ್ ನೆಟ್‍‍ವರ್ಕ್ ಪ್ರೊಟೋಕಾಲ್‍‍ಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಬ್ರೌಸರ್ ಮತ್ತು ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಇಂಟರ್ನೆಟ್‌ಗೆ ಡೇಟಾ ಕಳುಹಿಸಲು ಮಾರ್ಗವನ್ನುಂಟು ಮಾಡುತ್ತದೆ ಹಾಗಾಗಿ ಇಂಟರ್ನೆಟ್‌ಗೆ ಡೇಟಾ ಕಳುಹಿಸಲು ಈ ಅನುಮತಿ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ." "ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕತೆಯನ್ನು ಬದಲಾಯಿಸಿ" "ನೆಟ್‌ವರ್ಕ್‌ ಸಂಪರ್ಕದ ಸ್ಥಿತಿಯನ್ನು ಬದಲಾಯಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ ಅನುಮತಿಸುತ್ತದೆ." @@ -402,7 +402,7 @@ "ಸ್ಥಳೀಯ ಬ್ಲೂಟೂತ್‌‌ ಫೋನ್‌ ಕಾನ್ಫಿಗರ್‌ ಮಾಡಲು ಮತ್ತು ಅನ್ವೇಷಿಸಲು ಹಾಗೂ ರಿಮೊಟ್‌ ಸಾಧನಗಳ ಜೊತೆಗೆ ಜೋಡಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ." "WiMAX ನಿಂದ ಸಂಪರ್ಕಗೊಳಿಸಿ ಮತ್ತು ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಿ" "WiMAX ಸಕ್ರಿಯಗೊಂಡಿದೆಯೇ ಮತ್ತು ಸಂಪರ್ಕಗೊಂಡಿರುವಂತಹ WiMAX ನೆಟ್‍‍ವರ್ಕ್‌ಗಳ ಕುರಿತು ಮಾಹಿತಿಯನ್ನು ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ." - "WiMAX ಸ್ಥಿತಿಯನ್ನು ಬದಲಿಸಿ" + "WiMAX ಸ್ಥಿತಿಯನ್ನು ಬದಲಿಸಿ" "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲು ಮತ್ತು WiMAX ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಿಂದ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲು ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ." "WiMAX ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಂದ ಟಿವಿಯನ್ನು ಸಂಪರ್ಕಪಡಿಸಲು ಮತ್ತು ಕಡಿತಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ." "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಫೋನ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲು ಮತ್ತು WiMAX ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಿಂದ ಫೋನ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲು ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ." @@ -485,7 +485,7 @@ "ಸ್ಪರ್ಶದ ಪರದೆಯ ಮಾಪನಾಂಕ ನಿರ್ಣಯ ಪ್ಯಾರಾಮೀಟರ್‌ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ." "DRM ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಪ್ರವೇಶಿಸಿ" "DRM ಪ್ರಮಾಣಪತ್ರಗಳಿಗೆ ಅನುಮತಿ ಕಲ್ಪಿಸಲು ಮತ್ತು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ." - "Android Beam ವರ್ಗಾವಣೆ ಸ್ಥಿತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ" + "Android ಬೀಮ್ ವರ್ಗಾವಣೆ ಸ್ಥಿತಿ ಸ್ವೀಕರಿಸಿ" "ಪ್ರಸ್ತುತ Android Beam ವರ್ಗಾವಣೆಗಳ ಕುರಿತ ಮಾಹಿತಿಯನ್ನು ಸ್ವೀಕರಿಸಲು ಈ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸಿ" "DRM ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ತೆಗೆದುಹಾಕಿ" "DRM ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ." @@ -1091,11 +1091,11 @@ "ಸ್ವರೂಪಗೊಳಿಸುವಿಕೆ..." "ಸೇರಿಸಲಾಗಿಲ್ಲ" "ಯಾವುದೇ ಹೊಂದಾಣಿಕೆಯ ಚಟುವಟಿಕೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ." - "ಮೀಡಿಯಾ ಔಟ್‍ಪುಟ್ ಅನ್ನು ರೂಟ್ ಮಾಡಿ" + "ಮಾಧ್ಯಮ ಔಟ್‍ಪುಟ್ ಅನ್ನು ರೂಟ್ ಮಾಡಿ" "ಇತರ ಬಾಹ್ಯ ಸಾಧನಗಳಿಗೆ ಮೀಡಿಯಾ ಔಟ್‍‍ಪುಟ್ ಅನ್ನು ರೂಟ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ." - "ಸ್ಥಾಪನೆ ಸೆಷನ್‌ಗಳನ್ನು ಓದಿ" + "ಸ್ಥಾಪನೆ ಸೆಶನ್‌ಗಳನ್ನು ಓದಿ" "ಸ್ಥಾಪಿತ ಸೆಷನ್‌ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ಸಕ್ರಿಯ ಪ್ಯಾಕೇಜ್‌ ಸ್ಥಾಪನೆಗಳ ಕುರಿತು ವಿವರಣೆಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಇದು ಅನುಮತಿಸುತ್ತದೆ." - "ಪ್ಯಾಕೇಜ್‌ಗಳ ಸ್ಥಾಪನೆ ವಿನಂತಿಸಿ" + "ಸ್ಥಾಪನೆ ಪ್ಯಾಕೇಜ್‌ಗಳನ್ನು ವಿನಂತಿಸಿ" "ಪ್ಯಾಕೇಜ್‌ಗಳ ಸ್ಥಾಪನೆಯನ್ನು ವಿನಂತಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ." "ಜೂಮ್‌ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಸ್ಪರ್ಶಿಸಿ" "ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ." diff --git a/core/res/res/values-ko-watch/strings.xml b/core/res/res/values-ko-watch/strings.xml index df3288b3540d1..1572357d25341 100644 --- a/core/res/res/values-ko-watch/strings.xml +++ b/core/res/res/values-ko-watch/strings.xml @@ -21,4 +21,5 @@ "앱 %2$d개 중 %1$d개" + "센서" diff --git a/core/res/res/values-ko/cm_strings.xml b/core/res/res/values-ko/cm_strings.xml new file mode 100644 index 0000000000000..5554d77840ec9 --- /dev/null +++ b/core/res/res/values-ko/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + 스크린샷 + + 보안 SMS 수신 + + 앱이 들어오는 보안 SMS를 수신할 수 있도록 허용합니다. + + 보안 SMS 목록 수정 + + 앱이 보안 SMS 주소 목록을 수정할 수 있도록 허용합니다. + + 보안 + + 장치의 보안 정보에 관련된 권한입니다. + + 전화 블랙리스트 읽기 + + 앱이 전화 또는 메시지 수신이 차단된 전화번호들의 정보를 읽을 수 있도록 허용합니다. + + 전화 블랙리스트 수정 + + 앱이 어떤 전화번호들의 전화 또는 메시지를 차단할 것인지를 변경할 수 있도록 허용합니다. + + 잠금화면 배경 설정 + + 앱이 잠금화면 배경을 바꿀 수 있도록 허용합니다. + + 다시 시작 + + 현재 + + + 다시 시작 + + 복구 모드 + + 부트로더 + + 다운로드 + + 빠른 다시 시작 + + 다시 시작 + + 태블릿이 다시 시작됩니다. + 휴대전화가 다시 시작됩니다. + + 다시 시작하는 중\u2026 + + 앱이 종료되었습니다 + + 네트워크 ADB 활성화됨 + + USB 및 네트워크 ADB 활성화됨 + + 디버깅을 사용하지 않으려면 터치하세요. + + ADB - %1$s + USB 및 네트워크 + USB + 네트워크 + + 앱 실행 차단 + + %s이(가) 설치되지 않음 + + 우선순위 + 없음 + + SIM 구독 변경으로 인해 Wi-Fi 핫스팟 비활성화함 + + Wi-Fi 끄기 + + 프라이버시 가드 활성화 또는 비활성화 + 다른 앱이 프라이버시 가드와 함께 실행될 것인지 변경할 수 있도록 앱을 허용합니다. 앱이 프라이버시 가드와 함께 실행중일 땐 연락처, 통화 기록, 메시지 등의 개인 정보에 접근할 수 없게 됩니다. + 프라이버시 가드 활성화 + %1$s은(는) 개인 데이터에 접근할 수 없습니다. + 프라이버시 가드 + %1$s이(가) %2$s을(를) 원합니다. + + 선택 사항 기억하기 + + 카메라에 액세스 + 위치 정보에 액세스 + 알림 읽기 + VPN 활성화 + 전원을 켤 때 실행 + 통화 기록 삭제 + 연락처 삭제 + MMS 메시지 삭제 + SMS 메시지 삭제 + 창을 맨 위에 그리기 + 앱 사용 통계 확인 + 기기 켜짐 상태 유지 + 전화 걸기 + 캘린더 수정 + 통화 기록 수정 + 클립보드 수정 + 주소록 업데이트 + 시스템 설정 업데이트 + 마이크 켜기/끄기 + 오디오 재생 + 알림 게시 + 미디어 프로젝션 + 일정 읽기 + 전화 기록 읽기 + 클립보드 읽기 + 주소록 읽기 + MMS 메시지 읽기 + SMS 메시지 읽기 + SMS 메시지 받기 + 오디오 녹음 + MMS 메시지 보내기 + SMS 메시지 보내기 + 전원을 켤 때 실행 + 팝업 메시지 표시 + 블루투스 켜기/끄기 + 셀룰러 데이터 켜기/끄기 + NFC 켜기/끄기 + Wi-Fi 켜기/끄기 + 알람 볼륨 제어 + 오디오 포커스 제어 + 블루투스 볼륨 제어 + 마스터 볼륨 제어 + 미디어 버튼 사용 + 미디어 볼륨 제어 + 알림 볼륨 제어 + 벨소리 볼륨 제어 + 터치 진동 사용 + 음성 통화 볼륨 제어 + MMS 메시지 작성 + SMS 메시지 작성 + 지문인식 사용 + 음성 메일 추가 + 전화 상태에 접근 + Wi-Fi 네트워크 스캔 + 배경 화면을 변경 + 어시스트 구조 사용 + 현재 화면을 캡쳐 + 신체 센서를 사용함 + 셀 브로드캐스트 읽기 + 내 위치를 조작 + 외부 저장소 읽기 + 외부 저장소에 쓰기 + 화면을 켬 + 기기 계정 읽기 + Wi-Fi 상태 변경 + 루트 권한 얻기 + + 화면 고정을 해제하려면 뒤로 버튼을 계속 누르세요 + + 연결된 기기 없음 + %1$s대의 기기가 연결되어 있습니다 + %1$s대의 기기가 연결되어 있습니다 + + + + 액티비티 실행 제한됨 + %1$s은(는) 실행이 제한되어 있습니다. 탭하여 제한을 해제하고 애플리케이션을 실행하세요. + + 배터리가 완전히 충전됨 + 배터리 수명을 향상시키기 위해 기기를 충전기에서 분리하세요. + + 배터리 통계 재설정 + + 앱이 현재의 배터리 사용 데이터를 초기화할 수 있도록 허용합니다. + + SIM 카드가 변경되었습니다 + 탭하여 SIM 카드를 재설정 + diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 14f182d4bba5b..05fe58a7e5df2 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -254,7 +254,7 @@ "신용카드 번호와 비밀번호 등의 개인 데이터를 포함합니다." "상태 표시줄 사용 중지 또는 수정" "앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다." - "상태 표시줄" + "상태 표시줄에 위치" "앱이 상태 표시줄이 되도록 허용합니다." "상태 표시줄 확장/축소" "앱이 상태 표시줄을 확장하거나 축소할 수 있도록 허용합니다." @@ -282,7 +282,7 @@ "앱이 WAP 메시지를 수신하고 처리할 수 있도록 허용합니다. 이는 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 모니터링 또는 삭제할 수도 있다는 것을 의미합니다." "실행 중인 앱 검색" "앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있도록 허용합니다. 이 경우 앱이 기기에서 사용되는 다른 앱에 대한 정보를 검색할 수 있습니다." - "프로필 및 기기 소유자 관리" + "프로필 및 기기 소유자 관리" "앱이 프로필 소유자와 기기 소유자를 설정하도록 허용합니다." "실행 중인 앱 순서 재지정" "앱이 사용자의 입력 없이 작업을 포그라운드나 백그라운드로 이동할 수 있도록 허용합니다." @@ -324,7 +324,7 @@ "앱에서 수신 및 발신 통화 데이터를 포함하여 태블릿의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 지우거나 수정할 수 있습니다." "앱에서 수신 및 발신 통화 데이터를 포함하여 TV의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 삭제하거나 수정할 수도 있습니다." "앱에서 수신 및 발신 통화 데이터를 포함하여 휴대전화의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 지우거나 수정할 수 있습니다." - "신체 센서(예: 심박수 모니터)" + "신체 센서(예: 심박수 모니터)에 액세스" "앱이 심박수와 같은 신체 상태를 모니터링하는 센서의 데이터에 액세스하도록 허용합니다." "캘린더 일정 및 기밀정보 읽기" "앱이 친구나 동료의 일정을 포함하여 태블릿에 저장된 모든 캘린더 일정을 읽을 수 있도록 허용합니다. 이 경우 앱이 비밀유지 또는 기밀성을 무시하고 캘린더 데이터를 공유 또는 저장할 수도 있습니다." @@ -336,15 +336,15 @@ "앱이 친구나 동료의 일정을 포함하여 휴대전화에서 수정할 수 있는 일정을 추가, 삭제, 변경할 수 있도록 허용합니다. 이 경우 앱이 캘린더 소유자가 보내는 것처럼 메시지를 전송하거나 소유자 모르게 일정을 수정할 수도 있습니다." "추가 위치 제공업체 명령에 액세스" "앱이 추가 위치 정보 제공 기능의 명령에 액세스하도록 허용합니다. 이 경우 앱이 GPS 또는 기타 위치 소스의 작동을 방해할 수 있습니다." - "정확한 위치(GPS 및 네트워크 기반)" + "정확한 위치(GPS 및 네트워크 기반)에 액세스" "앱에서 GPS 또는 기지국 및 Wi-Fi와 같은 네트워크 위치 제공자를 사용하는 위치 서비스를 통해 내 정확한 위치를 알 수 있도록 합니다. 앱에서 이를 사용하도록 하려면 기기에서 이러한 위치 서비스는 사용하도록 설정해야 합니다. 앱에서 위치 서비스를 사용하여 내 위치를 파악할 수 있으며 배터리 소모량이 증가할 수 있습니다." - "대략적인 위치(네트워크 기반)" + "대략적인 위치(네트워크 기반)에 액세스" "앱에서 나의 대략적인 위치를 알 수 있게 합니다. 이 위치는 기지국 및 Wi-Fi와 같은 네트워크 위치 제공자를 사용하는 위치 서비스를 통해 알 수 있습니다. 앱에서 이를 사용하도록 하려면 기기에서 이러한 위치 서비스를 사용하도록 설정해야 합니다. 앱에서 이를 사용하여 나의 대략적인 위치를 파악할 수 있습니다." "오디오 설정 변경" "앱이 음량이나 출력을 위해 사용하는 스피커 등 전체 오디오 설정을 변경할 수 있도록 허용합니다." "오디오 녹음" "앱이 마이크로 오디오를 녹음할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 사용자의 확인 없이 언제든지 오디오를 녹음할 수 있습니다." - "SIM 통신" + "SIM에 명령어 보내기" "앱이 SIM에 명령어를 전송할 수 있도록 허용합니다. 이 기능은 매우 위험합니다." "사진과 동영상 찍기" "앱이 카메라로 사진과 동영상을 찍을 수 있도록 허용합니다. 이 권한을 사용하면 앱이 언제든지 사용자의 확인 없이 카메라를 사용할 수 있습니다." @@ -382,7 +382,7 @@ "앱이 휴대전화가 알고 있는 계정 목록을 가져올 수 있도록 허용합니다. 이 경우 설치한 애플리케이션에 의해 만들어진 모든 계정을 포함할 수 있습니다." "네트워크 연결 보기" "앱이 어떤 네트워크가 존재하며 연결되었는지 등의 네트워크 연결에 대한 정보를 볼 수 있도록 허용합니다." - "완전한 네트워크 액세스" + "전체 네트워크 액세스 권한 보유" "앱이 네트워크 소켓을 만들고 맞춤 네트워크 프로토콜을 사용할 수 있도록 허용합니다. 브라우저 및 기타 앱이 데이터를 인터넷에 전송하는 수단을 제공하므로, 이 권한이 데이터를 인터넷에 전송하는 데 필요하지 않습니다." "네트워크 연결 변경" "앱이 네트워크 연결 상태를 변경할 수 있도록 허용합니다." @@ -402,7 +402,7 @@ "앱이 로컬 블루투스 휴대전화를 설정한 다음 원격 기기를 검색하여 페어링할 수 있도록 허용합니다." "WiMAX 연결 및 연결 해제" "앱이 WiMAX를 사용하도록 설정했는지 여부와 연결된 WiMAX 네트워크에 대한 정보를 결정할 수 있도록 허용합니다." - "WiMAX 상태 변경" + "WiMAX 상태 변경" "앱이 태블릿을 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다." "앱이 WiMAX 네트워크에서 TV에 연결되거나 TV와의 연결을 해제할 수 있도록 허용합니다." "앱이 휴대전화를 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다." @@ -485,7 +485,7 @@ "앱이 터치 스크린의 보정 매개변수를 수정할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다." "DRM 인증서에 액세스" "애플리케이션이 DRM 인증서를 프로비저닝하고 사용하도록 허용합니다. 일반 앱에서는 필요하지 않습니다." - "Android Beam 전송 상태 수신" + "Android Beam 전송 상태 수신" "이 애플리케이션이 현재 Android Beam 전송 관련 정보를 수신하도록 허용합니다." "DRM 인증서 삭제" "애플리케이션이 DRM 인증서를 삭제하도록 허용합니다. 일반 앱에서는 필요하지 않습니다." @@ -1091,11 +1091,11 @@ "포맷하는 중…" "삽입하지 않음" "일치하는 활동이 없습니다." - "미디어 출력 연결" + "미디어 출력 연결" "앱이 미디어 출력을 기타 외부 기기에 연결할 수 있도록 허용합니다." - "설치 세션 읽기" + "설치 세션 읽기" "애플리케이션의 설치 세션 읽기를 허용하면, 활성 패키지 설치에 대한 세부 정보를 볼 수 있습니다." - "패키지 설치 요청" + "패키지 설치 요청" "애플리케이션이 패키지 설치를 요청하도록 허용합니다." "확대/축소하려면 두 번 터치하세요." "위젯을 추가할 수 없습니다." diff --git a/core/res/res/values-ku/cm_strings.xml b/core/res/res/values-ku/cm_strings.xml new file mode 100644 index 0000000000000..eb98dc2417264 --- /dev/null +++ b/core/res/res/values-ku/cm_strings.xml @@ -0,0 +1,158 @@ + + + + + + وێنەگرتنی ڕوونما + + وەرگرتنی کورتەنامەی پارێزراو + + ڕێگە بە بەرنامەکە بدە کە کورتەنامە پارێزراوەکەی داهاتوو وەربگرێت. + + دەستکاریکردنی لیستی کورتەنامە پارێزراوەکان + + ڕێگەدان بە بەرنامەکە بۆ دەستکاریکردنی لیستی کورتەنامە پارێزراوەکان. + + ئاسایش + + مۆڵەت پێدان پەیوەندی زانیاری ئاسایشی ئامێرەکە. + + خوێندنەوەی بلۆکی تەلەفۆن + + ڕێگەدان: بە بەرنامەیەک بۆ خوێندنەوەی زانیاریەکان دەربارەی ژمارەی تەلەفۆنەکە کە بلۆک کراوە بۆ نامەو تەلەفۆنکردنی هاتوو. + + گۆڕنی تەلەفۆن لە لیستی ڕەش + + ڕێگەدان بە بەرنامەکە بۆ ئەو ژمارانەی بلۆک کراون بۆ نامەو تەلەفۆن. + + دانانی کلیلە پارێز بۆ دیوارپۆش + + ڕێگەدان: بە بەرنامەیەک بۆ گۆڕینی قوفڵی ڕوونمای دیوارپۆش. + + دوبارە خستنەگەڕ + + ئێستا + + + سه‌رله‌نوێ خستنه‌ڕێ + + ڕیکەڤەری + + بووتلەودەر + + داگرتن + + کارپێکردنه‌وه‌ی قوڵ + + ئیشپێکردنەوە + + سه‌رله‌نوێ خستنه‌ڕێ دەبێت. + تەلەفۆنەکە سه‌رله‌نوێ ده‌کوژێته‌وه‌ و داده‌گیرسێته‌وه‌. + + سه‌رله‌نوێ خستنه‌ڕێ\u2026 + + بەرنامە داخرا + + ABD سه‌روو هێڵ کارده‌کات + + ABD سه‌روو USB و هێڵ کارده‌کات + + ئێره‌ لێبده‌ بۆ له‌کارخستنی هه‌ڵدۆزینه‌وه‌. + + + + %s دانەمەزراوە + + + + + چالاکردن یان لەکارخستنی بەرگری تایبەتی + ڕێگە دان بە بەرنامەکە بۆ گۆڕینی کەشوهەوای بەرنامەیەکی تر لە تایبەتی. کاتێک بەرنامەکە ئەکەوێتە کار لەگەڵ تایبەتی .هیچ ڕێگەیەکی نیە بۆ ئەوەی زانیاری تایبیەتیت بەکاربهێنێت وەکو ،ناوەکان،تەلەفۆن لۆگ یان نامە. + پاسەوانی تایبەتی چالاکراوە + %1$s ناتوانێت زانیاری تایبەتی بەکاربهێنێت + پاسەوانی تایبەتی + %1$s حەز ئەکەی بۆ %2$s. + + بیرخستنەوەی هەڵبژاردنەکەم + + ڕێگەدان بەکامێرا + ڕێگەی ناوچەی + تێبنینیەکانت بخوێنەوە + VPN چالاککردنی + کردنەوەی لەکاتی هەڵبوونی ئامێردا + سڕینەوەی تۆمارەکانی پەیوەندیت + سڕینەوەی ناوەکانت + MMS سڕینەوەی پەیامە ڕەنگاڵەییەکان + SMS سڕینەوەی پەیامەکانت + ڕاکێشانی پەنجەرەکە بۆ سەرەوە + هێنانی بەرنامەی ئاماری بەکارهێنان + دانانی ئامێرەکە بە کراوەی + تەلەفۆن بکە + نوێکردنه‌وه‌ی ڕۆژمێرەکەت + نوێکردنه‌وه‌ی تۆماری تەلەفۆن + سڕینەوەی وێنە + نوێکردنه‌وه‌ی ناوەکانت + نوێکردنه‌وه‌ی ڕێکخستنی سیستەم + کپکردن/کپنەکردنی بیستۆک + لێدانی دەنگ + ناردنی تێبینی + پرۆژەی ڕەنگاڵە + خوێندنەوەی ڕۆژمێر + خوێندنەوەی تۆماری تەلەفۆن + خوێندوەی کلیپبۆرد + خوێندنەوەی ناوەکانت + خوێندنوەی نامەی MMSکانت + خوێندنەوەی SMS کانت + گەیشتنی نامەی SMS + تۆمارکردنی دەنگ + ناردنی نامەی MMS + ناردنی نامەی SMS + دەستپێکردنی چالاککردنی هێز + پیشاندانی تێبینی تازە + گۆڕینی بلوتوس + گۆڕینی دۆخی NFC + کۆنترۆڵی دەنگی زەنگ + کۆنترۆڵی تیشکۆی دەنگ + کۆنترۆڵکردنی دەنگی بلوتوس + کۆنترۆڵکردنی دەنگی سەرەکی + بەکارهێنانی دوگمەی ڕەنگاڵە + کۆنترۆڵی دەنگی ڕەنگاڵە + کۆنترٶڵی دەنگی تێبنینی + کۆنترۆڵی دەنگی زەنگ + بەکارهێنانی بەرپەرچدانی Haptic + کۆنترۆڵی دەنگی تەلەفۆن + نوسنی نامەی MMS + نوسینی نامەی SMS + بەدەستهێنانی ڕێگەپێدانی ڕۆت + + + ئامێر پەیوەست نەکراوە + %1$s ئامێر پەیوەستکراوە + %1$s ئامێری پەیوەستکراو + + + + + + + + diff --git a/core/res/res/values-ku/strings.xml b/core/res/res/values-ku/strings.xml new file mode 100644 index 0000000000000..fc74ec65aa1ce --- /dev/null +++ b/core/res/res/values-ku/strings.xml @@ -0,0 +1,2977 @@ + + + + + + بایت + + کیلۆبایت + + مێگابایت + + گیگابایت + + تێرابایت + + پیکۆبایت + + + + + + + + + + + + + + + <بێ ناونیشان> + + (هیچ ژماره‌ ته‌له‌فۆنێک نییه‌) + + + دەنگەپۆست + + MSISDN1 + + + + کێشه‌ی په‌یوه‌ندی هه‌یه‌ یان کۆدی MMI ناڕاستە. + + کردارەکە تەنیا بۆ ژمارە جێگیرکراوەکان سنووربەندکراوە. + + خزمه‌تگوزارییەکە چالاککرا. + + خزمه‌تگوزارییەکە چالاککرا بۆ: + + خزمه‌تگوزارییەکە ناچالاککراوە. + + خۆتۆمارکردن سه‌رکه‌وتوو بوو. + + سڕینه‌وه‌ سه‌رکه‌وتوو بوو. + + تێپه‌ڕەوشه‌ ناڕاستە. + + کۆدی MMI تەواوە. + + (PIN)ە کۆنه‌کە کە نووسیوتە ڕاست نییە. + + (PUK)ەکە کە نووسیوتە ڕاست نییە. + + (PIN)ەکان کە نووسیوتن له‌یه‌کناچن. + + (PIN)ەک بنووسه‌ که‌ ٤ بۆ ٨ ژماره‌ بێت. + + (PUK)ەکەیەک بنووسە کە ٨ ژمارە یان درێژتر بێت. + + سیمکارته‌که‌ت داخراوە به‌ PUK، بۆ کردنه‌وه‌ی کۆدی PUK بنووسە. + تکایه‌ PUK2 بنووسه‌ بۆ کردنەوەی سیمکارت. + + سه‌رکه‌وتوو نه‌بوو ، تکایه‌ داخەری SIM/RUIM چالاک بکه‌. + + + %d هه‌وڵت ماوه‌ پێش ئه‌وه‌ی سیمکارت دابخرێت. + %d هه‌وڵت ماوه‌ پێش ئه‌وه‌ی سیمکارت دابخرێت. + + + IMEI + + MEID + + هاتنی پێناسه‌ی پەیوەندیکه‌ر + + ڕۆیشتنی پێناسەی په‌یوه‌ندیکه‌ر + + + + ناردنەوەی په‌یوه‌ندی + + چاوەڕوانیی پەیوەندی + + نەهێشتنی پەیوەندی + + گۆڕینی تێپه‌ڕەوشه‌ + + گۆڕینی PIN + ژماره‌ی په‌یوه‌ندی ئاماده‌یە + ژماره‌ی په‌یوه‌ندی سنووربەند کراوە + په‌یوه‌ندیکردنی سێ ڕێگایی + بەرپەرچ دانەوەی په‌یوه‌ندییە بێزارکەرەکان و نەخوازراوەکان + گەیاندنی ژماره‌ی په‌یوه‌ندیکردن + مەمشێوێنە + + پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنووربەندکراوە. په‌یوه‌ندیی داهاتوو: سنووربەند کراوە + + پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنووربەندکراوە. بەڵام په‌یوه‌ندیی داهاتوو: سنووربەند نەکراوە + + پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنووربەندکراو نییه‌. بەڵام په‌یوه‌ندیی داهاتوو: سنووربەند کراوە + + پێناسەی په‌یوه‌ندیکه‌ر له‌سه‌ر سنوورداره نییه‌. په‌یوه‌ندیی داهاتوو: سنووردار نییه‌ + + خزمه‌تگوزاری به‌رده‌ست نییه‌. + + ناتوانیت ڕێکخستنی پێناسەی په‌یوه‌ندیکه‌ر بگۆڕیت. + + دەستگەیاندنی سنووردار گۆڕدرا + + خزمەتگوزاریی دراوە به‌ستراوه‌. + + خزمەتگوزاریی فریاکەوتن به‌ستراوه‌. + + خزمەتگوزاریی ده‌نگ به‌ستراوه‌. + + هه‌موو خزمەتگوزارییەکانی ده‌نگ به‌ستراون. + + خزمەتگوزاریی کورتەنامە به‌ستراوه‌. + + خزمەتگوزارییەکانی ده‌نگ و داتا به‌ستراون. + + خزمەتگوزارییەکانی ده‌نگ و کورتەنامە به‌ستراون. + + هه‌موو خزمەتگوزارییەکانی ده‌نگ، داتا و کورتەنامە به‌ستراون. + + + + + ده‌نگ + + داتا + + فاکس + + کورتەنامە + + ناهاوکاتگەری + + هاوکاتگەری + + گورزەی دراوە + + نەزانراو + + + + دیارخه‌ری ڕۆمینگ هەڵکراوە + دیارخه‌ری ڕۆمینگ کوژاوه‌ته‌وه‌ + دیارخه‌ری ڕۆمینگ چاو دادەگرێ + له‌ ده‌ره‌وه‌ی گه‌ڕه‌ک + له‌ ده‌ره‌وه‌ی خانوو + ڕۆمینگ - سیستەمی بەباشزانراو + ڕۆمینگ - سیستەمی به‌رده‌ست + ڕۆمینگ - هاوپەیمانی یەکگرتوو + ڕۆمینگ - هاوپەیمانی باشتر + ڕۆمینگ - کارکردی تەواوی خزمەتگوزاری + ڕۆمینگ - کارکردی بەشێک لە خزمەتگوزاری + هێمای ڕۆمینگ هەڵکراوە + هێمای ڕۆمینگ کوژاوه‌ته‌وه‌ + گه‌ڕان به‌دوای خزمه‌تگوزاری + + + + + + + + + + + + + + + + {0}: پەیوەندی ئاراستە نەکراوە + + {0}: {1} + + {0}: {1} دوای {2} چرکه‌ + + {0}: پەیوەندی ئاراستە نەکراوە + + {0}: پەیوەندی ئاراستە نەکراوە + + + + کۆدی تایبەت ته‌واو بوو. + + کێشه‌ی گرێدان هه‌یه‌ یان کۆدی تایبەت ناڕاسته‌. + + + + باشه‌ + + هه‌ڵه‌یه‌ک له‌ تۆڕدا هه‌بوو. + + نه‌یتوانی ناونیشانی ئینتەرنێتی بدۆزێته‌وه‌. + + پلانی پارێزپرسیی ماڵپه‌ڕ پشتگیری ناکرێت. + + نەیتوانی پارێزپرسی تێپەڕ بکات. + + تێپەڕکردنی پارێزپرسی له‌ ڕێی ڕاژه‌کاری پرۆکسی سه‌رکه‌وتوو نه‌بوو. + + نه‌یتوانی گرێبدرێت به‌ ڕاژه‌کاره‌وه‌. + + نه‌یتوانی گرێبدرێت به‌ ڕاژه‌کاره‌وه‌. دواتر هه‌وڵبده‌وه‌. + + کاتی گرێدان به‌ ڕاژه‌کاره‌وه‌ به‌سه‌ر چوو. + + په‌ڕه‌که‌ پڕە لە ئاراستەگۆڕینی ڕاژه‌کار. + + پرۆتۆكۆڵەکە پشتگیری ناکرێت. + + نەیتوانی گرێدانێکی دڵنیا دابمه‌زرێنێت. + + نەیتوانی په‌ڕه‌که‌ بکاته‌وه‌ لەبەر ئەوەی ناونیشانه‌که‌ ڕاست نییه‌. + + نەیتوانی دەست بگەیەنێتە فایلەکە. + + نەیتوانی فایلی داواکراو بدۆزێته‌وه‌. + + داواکاریی زۆر خراوه‌ته‌ ڕوو. دواتر هه‌وڵبده‌وه‌. + + + + هه‌ڵه‌ له‌ چوونه‌ژووره‌وه‌ بۆ %1$s + + + + هاوکاتگەری + + هاوکاتگەری + + هەندێک %s دەسڕێنەوە. + + بیرگه‌ی تابلێت پڕە. هه‌ندێک فایل بسڕه‌وه‌ بۆ ئازادکردنی بۆشایی. + + + + بیرگه‌ی تەلەفۆن پڕە. هه‌ندێک فایل بسڕه‌وه‌ بۆ ئازادکردنی بۆشایی. + + + + له‌وانه‌یه‌ تۆڕه‌که‌ چاودێری کرابێت + + له‌لایه‌ن به‌شی نه‌ناسراوی سێیه‌مه‌وه‌ + + + له‌لایه‌ن %s + + + + + + + + + + + + من + + + + بژارده‌کانی تابلێت + + + بژارده‌کانی ته‌له‌فۆن + + دۆخی بێده‌نگ + + داگیرساندنی بێته‌ل + + کوژاندنه‌وه‌ی بێته‌ل + + داخەری ڕوونما + + کوژاندنه‌وه‌ + + کوژاندنه‌وه‌ی زه‌نگلێدەر + + زەنگلێدەر لەسەر دۆخی لەرین + + بەکارخستنی زه‌نگلێدەر + + + + کوژاندنه‌وه‌ی\u2026 + + تابلێته‌که‌ت ده‌کووژێته‌وه‌. + + + + ته‌له‌فۆنه‌که‌ت ده‌کووژێته‌وه‌. + + ده‌ته‌وێت بکوژێته‌وه‌؟ + + دەسپێکردنەوە بۆ سەر دۆخی دڵنیاکراو + + ده‌ته‌وێت دەست پێ بکەیتەوە بۆ دۆخی دڵنیاکراو؟ + ئه‌م کرداره‌ هه‌موو ئه‌و به‌رنامه‌ لاوه‌کییانه‌ ده‌سڕێته‌وه‌ که‌ داتمه‌زراندوون. + ئەوانە دەگەڕێنەوە باری خۆیان، کاتێک سەر لە نوێ دەست پێ دەکەیتەوە. + + نوێ + + هیچ به‌رنامه‌یەکی نوێ نییه‌. + + بژارده‌کانی تابلێت + + + بژاردەکانی ته‌له‌فۆن + + داخەری ڕوونما + + کوژاندنه‌وه‌ + + ڕاپۆرتی کەلێن + + گرتنەوەی ڕاپۆرتی کەلێن + + ئه‌م کردارە سەبارەت بە ئامێری ئێستات زانیاری کۆ ده‌کاته‌وه‌ + و بە شێوەی پۆستی ئەلەکترۆنی دەینێرێت. ماوەیەکی زۆر کەم دەخایەنێت + بۆ ئامادەکردنی ڕاپۆرتەکە تا ئەوکات کە دەنێردرێت: تکایە هێور بە. + + + دۆخی بێده‌نگ + + دەنگ کوژاوەیە + + دەنگ هەڵکراوە + + دۆخی فڕۆکە + + دۆخی فڕۆکه‌ کراوه‌یه‌ + + دۆخی فڕۆکه‌ کوژاوه‌یه‌ + + + + + + +٩٩٩ + + دۆخی دڵنیاکراو + + سیسته‌می ئه‌ندرۆید + + + + + + + + ڕۆژمێر + + + کورتەنامە + + + بیرگه‌ + + + بیستۆک + + تۆمارکردنی دەنگ + + کامێرا + + + مۆبایل + + + + + ناوەرۆكى پەنجەرە بگێڕەوە + + ناوەرۆكى پەنجەرەيێك دەپشكنێت تۆ ن + +لەگەڵ كار لە يەكتان كرد. + + وێبگەر بکەرەوە بە دەست لێدان + + برگەى بەركەوتن بەدەنگى بەرز قسە دەكرێن + +و شاشەكە دەتوانێت سەرنج بدەرێت بەكارهێنانى نيشانە. + + + وێبى زيادكراو بەكار بخە + +دەشێت لێى نزيك ببێتەوە يا بچێتە ناوى + + نوسراو لەوانەيە بۆ دا بمەزرێنرێن + +ناوەرۆكى بەرنامە ئاسان پەيدابووتر كرد. + + نووسين تێبينى بكە تۆ جۆر دەن + + وەكو متمانەى زانيارى كەسى بگرەوە + +كارت ڕەنووس دەكات و وشەى تێپەڕين. + + + + پەك دەخات بە يان میله‌ يان دۆخ دەگۆڕێت + + ڕێ دەدات بە بەرنامە تا شيشەكەى دۆخ پەك دەخات بێت يان زياد دەكات و ئايكۆنى سيستەم لا دەبات. + + + ڕێ دەدات بە بەرنامە تا شيشەكەى دۆخ ببێت. + + + شيشى دۆخى ڕووخان فراوان بكە + + ڕێ دەدات بە بەرنامە تا فراوان بكات يان ڕووخان شيشەكەى دۆخ. + + + + + + + + + + + + + + + + شۆتكەتس دا بمەزرێنە + + ڕێگه‌ دان بۆ زیادکردنی به‌رنامه‌ +قه‌د بڕ له‌سه‌ر ڕوونمای ماڵه‌وه‌ به‌بێ به‌کارهێنه‌ر. + + سڕینه‌وه‌ قه‌دبڕه‌کان + + ڕێگه‌دان به‌ بارنامه‌ بۆ سڕینه‌وه‌ +قه‌دبڕی ڕوونمای ماڵه‌وه‌ به‌بێ به‌کارهێنه‌ر. + + ته‌له‌فۆنکردنی ده‌ره‌وه‌ + + ڕێگه‌ دان به‌به‌رنامه‌که‌ بۆ بینینی ژماره‌کان که‌ لێدراوهن له‌کاتی ته‌له‌فۆنی ده‌ره‌وه‌ هه‌ڵبژارده‌ی ته‌له‌فۆن بۆ ڕێگه‌ دان به‌ ته‌له‌فۆنکردنی جیاواز. + + گه‌شتنی ده‌قه‌ نامه‌(SMS) + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ گه‌شتنی نامه‌.ئه‌مه‌ مانانی +ئه‌وه‌یه‌ به‌رنامه‌که‌ ئه‌توانێت نامه‌ بسڕێته‌وه‌ یان ناردنی بۆ ئامێره‌که‌ به‌ بێ پیشاندانی تۆ. + + گه‌شتنی ده‌قه‌ نامه‌ی(MMS) + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ گه‌شتنی نامه‌.ئه‌مه‌ مانانی +ئه‌وه‌یه‌ به‌رنامه‌که‌ ئه‌توانێت نامه‌ بسڕێته‌وه‌ یان ناردنی بۆ ئامێره‌که‌ به‌ بێ پیشاندانی تۆ. + + خوێندنه‌وه‌ی هه‌موو خانه‌ی په‌خشه‌ نامه‌کان + + + خوێندنه‌وه‌ی پێدانی به‌شداریپێکراو + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ وه‌رگرتنی زانیاری له‌باره‌ی خوێندنه‌وه‌ی پێدانی به‌شداریپێکراو. + + + ڕێ دەدات بە بەرنامە تا نامەى ئێس ئێم ئێس بنێرێت. + +ئەمە لەوانەيە ببێت بە هۆى تۆمەتى چاوەروان نەكراو. بەرنامەى قيناوى لەوانەيە تێ بچن لەلايەن پارەى تۆ + +ناردنى نامە بەبێ دووپات كردنت. + + خوێندنه‌وه‌ی نامه‌کان(MMS یان SMS) + + ڕێ دەدات بە بەرنامە تا ئێس ئێم ئێس بخوێنێتەوە + +نامە لەسەر كارتتى جۆر يان سيميان خەزن كرد. ئەمە ڕێ دەدەن بە بەرنامە تا هەموو بخوێنێتەوە + +نامەى ئێس ئێم ئێس، بێگوێدانەى ناوەرۆك يان برايانە. + + + ڕێ دەدات بە بەرنامە تا ئێس ئێم ئێس بخوێنێتەوە + +نامە لەسەر كارتتى تەلەفۆن يان سيميان خەزن كرد. ئەمە ڕێ دەدەن بە بەرنامە تا هەموو بخوێنێتەوە + +نامەى ئێس ئێم ئێس، بێگوێدانەى ناوەرۆك يان برايانە. + + گه‌شتنی نامه‌ی (WAP) + + ڕێ دەدات بە بەرنامە تا وەر بگرێت و كردار + +نامەى WAP. ئەمە ڕێگەپێدان توانايەكە دەگرێتەوە تا چاودێرى بكات يان دەسڕێتەوە + +بۆ نامە ناردى تۆ بۆ پيشاندانى ئەوان تۆ. + + گه‌ڕانه‌وه‌ی به‌رنامه‌ی له‌کار + + ڕێ دەدات بە بەرنامە تا زانيارى بگێڕێتەوە + +دەربارەى ئێستا و بەم دواييە ڕاكردنى ئەرك. ئەمە لەوانەيە ڕێ بدات بە بۆ بەرنامە + +زانيارى دەربارەى بدۆزەوە داوا كردن بەكار دێنرێن لەسەر ئامرازەكە. + + + + تۆمارکردنی به‌رنامه‌ی کراوه‌ + + ڕێگه‌ دان به‌ به‌رنامه‌که‌ بۆ گۆڕینی ئه‌رک بۆ سه‌رو پاشه‌وه‌ی پشته‌گه‌ڵاڵه‌. به‌رنامه‌که‌ بێ تۆ ئه‌یکات. + + چالاککردنی باری سه‌یاره‌ + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ چالاککردنی باری سه‌یاره‌. + + داخستنی به‌رنامه‌ی تر + + ڕێ دەدات بە بەرنامە تا كۆتايى پێ بهێنێت + +كردارى زەمينەى بەرنامەى ديكە. ئەمە لەوانەيە ببێتە هۆى بەرنامەى ديكە تا ڕا بگرن + +ڕاكردن. + + پیشاندان لە سەروی بەرنامەکانی ترەوە + + ڕێگە بە بەرنامەکە دەدا کە تێکەڵی روکاری بەرنامەکانی تر بێت.وە ئەوشتەی کەدەیبینیت بگۆرێت + + وا له‌ به‌رنامه‌که‌ بکرێت هه‌میشه‌ کرابێته‌وه‌ + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ به‌شکردنی خۆی له ناو بیرگەی. ئه‌مه‌ له‌وانه‌یه‌ بیرگەییه‌که‌ت سنوردار بکات بۆ به‌رنامه‌کانی تر که‌ تابلێته‌که‌ت خاو ده‌کاته‌وه‌. + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ به‌شکردنی خۆی له ناو بیرگەی. ئه‌مه‌ له‌وانه‌یه‌ بیرگەییه‌که‌ت سنوردار بکات بۆ به‌رنامه‌کانی تر که‌ مۆبایله‌که‌ت خاو ده‌کاته‌وه‌. + + مامه‌ڵه‌کردن له‌گه‌ڵ قه‌باره‌ی به‌کارنه‌هێنراو + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ وه‌رگرتنی کۆد ، زانیاری ، و قه‌باره‌ی فایله‌ زیاده‌کان + + گۆڕینی رێکخستنەکانی سیستەم + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ گۆڕینی زانیاری سیسته‌م.به‌رنامه‌ به‌دخووه‌کان بۆ تێکدانی سیسته‌م به‌کاریده‌هێنن ڕێگه‌ به‌ هه‌موو به‌رنامه‌یه‌ک مه‌ده‌. + + کارکردن له‌گه‌ڵ داگیرساندن + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خۆکارانه‌ ده‌ستپێکردن له‌گه‌ڵ داگیرساندنی تابلێته‌که‌ت. به‌ڵام له‌وانه‌یه‌ هۆکارێک بێت بۆ خاوبوونه‌وه‌ی داگیرساندن وه‌ خاوکردنه‌وه‌ی تابلێتکه‌. + + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خۆکارانه‌ ده‌ستپێکردن له‌گه‌ڵ داگیرساندنی مۆبایله‌که‌ت. به‌ڵام له‌وانه‌یه‌ هۆکارێک بێت بۆ خاوبوونه‌وه‌ی داگیرساندن وه‌ خاوکردنه‌وه‌ی مۆبایله‌که‌. + + ناردنی په‌خشی لکێنراو + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ ناردنی په‌خشی لکێندراو، که‌ ده‌مێنێته‌وه‌ دوای ته‌واوبونی په‌خشیش. له‌وانه‌یه‌ ببێته‌ هۆی سه‌رفکردنی زۆرێک له‌ بیرگه‌ و خاوکردنه‌وه‌ی تابلێت. +     + + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ ناردنی په‌خشی لکێندراو، که‌ ده‌مێنێته‌وه‌ دوای ته‌واوبونی په‌خشیش. له‌وانه‌یه‌ ببێته‌ هۆی سه‌رفکردنی زۆرێک له‌ بیرگه‌ و خاوکردنه‌وه‌ی مۆبایل. + + خوێندنه‌وه‌ی په‌یوه‌ندێكانت + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خوێندنه‌وه‌ی زانیاری له‌باره‌ی په‌یوه‌ندییه‌کانت له‌ناو تابلێته‌که‌ته‌، که‌ فریکوەنسی له‌گه‌ڵه‌ بۆ ته‌له‌فۆنکراوه‌کان، ئیمێلکراوه‌کان، کۆمه‌ڵایه‌تییه‌کان له‌ چه‌نده‌ها ڕێگای تره‌وه‌.ده‌سته‌ڵاته‌که‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ که‌ په‌یوه‌ندییه‌کانت پاشه‌که‌وت بکات له‌گه‌ڵ زانیارییه‌کانیان.به‌ڵام وریای به‌رنامه‌ به‌دخووه‌کان به‌ بۆ مه‌به‌ستی خراپ به‌کارده‌هێنن. + + + ڕێگه‌دان به‌ به‌رنامه‌که‌ بۆ خوێندنه‌وه‌ی زانیاری له‌باره‌ی په‌یوه‌ندییه‌کانت له‌ناو مۆبایله‌که‌ت. که‌ فریکوەنسی له‌گه‌ڵه‌ بۆ ته‌له‌فۆنکراوه‌کان، ئیمێلکراوه‌کان، کۆمه‌ڵایه‌تییه‌کان له‌ چه‌نده‌ها ڕێگای تره‌وه‌.ده‌سته‌ڵاته‌که‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ که‌ په‌یوه‌ندییه‌کانت پاشه‌که‌وت بکات له‌گه‌ڵ زانیارییه‌کانیان.به‌ڵام وریای به‌رنامه‌ به‌دخووه‌کان به‌ بۆ مه‌به‌ستی خراپ به‌کارده‌هێنن. + + گۆڕانکاری لە ژمارەی پەیوەندیەکانتدا بکە + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی زانیاری له‌باره‌ی په‌یوه‌ندییه‌ پاشه‌که‌وتکراوه‌کان له‌ تابلێته‌که‌ت، که‌ فریکوه‌نسی تێدایه‌ په‌یوه‌ندیت پێوه‌کردوون،ئیمێل،یان هه‌ر شتێکی تری کۆمه‌ڵایه‌تی، ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ داتاکانت بسڕێته‌وه‌. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی زانیاری له‌باره‌ی په‌یوه‌ندییه‌ پاشه‌که‌وتکراوه‌کان له‌ مۆبایله‌که‌ت، که‌ فریکوه‌نسی تێدایه‌ په‌یوه‌ندیت پێوه‌کردوون،ئیمێل،یان هه‌ر شتێکی تری کۆمه‌ڵایه‌تی، ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ داتاکانت بسڕێته‌وه‌. + + خوێندنه‌وه‌ی ته‌له‌فۆنی تۆمارکراو + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی تۆماری په‌یوه‌ندییه‌کان، که‌ زانیاری تێدایه‌ له‌باره‌ی په‌یوه‌ندی هاتوو وه‌ ڕۆشتوو.ئه‌م ده‌سته‌لاته‌ ڕێگه به‌ به‌رنامه‌که‌ ده‌دات بۆ خه‌زن کردنی تۆماری په‌یوه‌ندییه‌کانت.وه‌ به‌رنامه‌ به‌دخووه‌کان بۆ مه‌به‌ستی بڵاوکردنه‌وه‌یان به‌کاریده‌هێنن به‌بێ زانیاری تۆ. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی تۆماری په‌یوه‌ندییه‌کان، که‌ زانیاری تێدایه‌ له‌باره‌ی په‌یوه‌ندی هاتوو وه‌ ڕۆشتوو.ئه‌م ده‌سته‌لاته‌ ڕێگه به‌ به‌رنامه‌که‌ ده‌دات بۆ خه‌زن کردنی تۆماری په‌یوه‌ندییه‌کانت.وه‌ به‌رنامه‌ به‌دخووه‌کان بۆ مه‌به‌ستی بڵاوکردنه‌وه‌یان به‌کاریده‌هێنن به‌بێ زانیاری تۆ. + + نوسینی تۆماری په‌یوه‌ندییه‌کان + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی تۆماری په‌یوه‌ندییه‌کانت.که‌ زانیاری له‌باره‌ی په‌یوه‌ندی هاتوو و وه‌ ڕۆشتووی تێدایه‌.به‌رنامه‌ به‌دخووه‌کان به‌کاری ئه‌هێنن بۆ سڕینه‌وه‌ی تۆماره‌کان. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی تۆماری په‌یوه‌ندییه‌کانت.که‌ زانیاری له‌باره‌ی په‌یوه‌ندی هاتوو و وه‌ ڕۆشتووی تێدایه‌.به‌رنامه‌ به‌دخووه‌کان به‌کاری ئه‌هێنن بۆ سڕینه‌وه‌ی تۆماره‌کان. + + + + خوێندنه‌وه‌ی ڕووداوه‌کانی ڕۆژژمێر بۆ زانیاری شاراوه‌ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی هه‌موو ڕووداوه‌کانی ناو ڕۆژژمێره‌کان له‌ ئامێره‌که‌ت، وه‌ک هاوڕێکان و شوانه‌کان. ئه‌مه‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ده‌دات بۆ به‌شداریپێکردنی یان پاشه‌که‌وتکردنی زانیاری ڕۆژژمێره‌که‌ت وریابه‌. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی هه‌موو ڕووداوه‌کانی ناو ڕۆژژمێره‌کان له‌ ئامێره‌که‌ت، وه‌ک هاوڕێکان و شوانه‌کان. ئه‌مه‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ده‌دات بۆ به‌شداریپێکردنی یان پاشه‌که‌وتکردنی زانیاری ڕۆژژمێره‌که‌ت وریابه‌. + + زیادکردن یان گۆڕینی ڕووداو له‌ناو ڕۆژژمێر و ناردنی ئیمێل بۆ میوانه‌کان به‌بێ زانیاری له‌ باره‌ی دروستکه‌ره‌که‌ی + + + + + ده‌سته‌ڵاتی شوێنی زیاتر بۆ فرمانی دابینکردن + + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌ستکه‌وتنی شوێنی ته‌واوی تۆ به‌ GPS یان خه‌ته‌که‌ت وه‌ک وایه‌رلێس و هێڵ.خزمه‌تگوزاری شوێن پێویسته‌ کاربکات بۆ ئه‌وه‌ی به‌رنامه‌کان شوێن بدۆزنه‌وه‌.به‌رنامه‌کان ده‌توانن بزانن له‌ کوێیت به‌ GPS ، ئه‌م کاره‌ باتری مۆبایله‌که‌ت که‌م ده‌کات. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌ستکه‌وتنی شوێنی نزیکی تۆ به‌ GPS یان خه‌ته‌که‌ت وه‌ک وایه‌رلێس و هێڵ.خزمه‌تگوزاری شوێن پێویسته‌ کاربکات بۆ ئه‌وه‌ی به‌رنامه‌کان شوێن بدۆزنه‌وه‌.به‌رنامه‌کان ده‌توانن بزانن له‌ کوێیت به‌ GPS ، ئه‌م کاره‌ باتری مۆبایله‌که‌ت که‌م ده‌کات. + + گۆڕینی ڕێکخستنه‌کانی ده‌نگ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی ڕێکخستنی ده‌نگی گشتی وه‌ک ده‌نگی بڵنگۆ به‌کاردێت بۆ ده‌رچه‌. + + تۆمارکردنی دەنگ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ تۆمارکردنی ده‌نگ له‌گه‌ڵ مایکرۆفۆنه‌که‌. ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ ئه‌دات به‌ به‌رنامه‌که‌ هه‌رکاتێک بیه‌وێت ده‌نگ تۆماربکات. + + + + گرتنی وێنه‌ یان ڤیدیۆ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گرتنی وێنه‌ و ڤیدیۆ له‌گه‌ڵ کامێراکه‌، ئه‌م ده‌سته‌ڵاته‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ئه‌دات کامێرا به‌کاربهێنێ هه‌رکات بیه‌وێت. + + سه‌رپه‌رشتیکردنی له‌رین + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ سه‌رپه‌رشتی کردنی له‌رینه‌وه‌. + + سه‌رپه‌رشتیکردنی ڕووناکی فلاش + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ سه‌رپه‌رشتیکردنی ڕووناکی فلاش. + + په‌یوه‌ندی کردنی ژماره‌کان ڕاسته‌وخۆیی + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردن به‌ ژماره‌وه‌ به‌بێ زانینی تۆ.له‌وانه‌یه‌ ئه‌نجامه‌که‌ی خراپ بێت بۆ په‌یوه‌ندی کردن. +تێبینی:ئه‌مه‌ ڕێگه‌ نادات به‌ به‌رنامه‌که‌ په‌یوه‌ندی به‌ ڕوداوی له‌ناکاو و کتوپڕ بکات. +به‌رنامه‌ خراپه‌کان به‌کاریده‌هێنن بۆ سه‌رفکردنی باڵانسه‌کانت. + + + + خوێندنه‌وه‌ی باری ئامێر و ناسنامه‌ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌سته‌ڵاتکردنی خزمه‌ته‌کانی ئامێر.ئه‌مه‌ ڕێگه‌ به‌ به‌رنامه‌که‌ ئه‌دات بۆ دیاریکردنی ژماره‌ی مۆبایل و ID ئامێر، کاتێک که‌ په‌یوه‌ندی له‌کاردایه‌ ، یان ژماره‌یه‌کی دووره‌ده‌ست په‌یوه‌ندییه‌ بۆ په‌یوه‌ندی. + + ڕێگری کردن له‌ تابلێت بۆ نوستن + + + ڕێگری کردن له‌ مۆبایل بۆ نوستن + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێگری کردن له‌ تابلێت بۆ نوستن. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێگری کردن له‌ مۆبایله‌که‌ت بۆ نوستن. + + گوێزه‌ره‌وه‌ی خوارسوور + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گواستنه‌وه‌ی خوارسور. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گواستنه‌وه‌ی خوارسور. + + دانانی دیوارپۆش + + ڕێگەدانی بەرنامە بۆ دانانی دیوارپۆشی سیستەم. + + گونجاندنی قەبارەی دیوارپۆش + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ دانانی قه‌باره‌ی سه‌رڕوونما. + + کاتی ناوچەیی رێکبخە + + ڕێگە بە نمواڵەکە بدە کاتی ناوچەیی تاتەبژمێرەکە بگۆرێت. + + + ڕێگە بە نمواڵەکە بدە کاتی ناوچەیی تەلەفونەکە بگۆرێت. + + هەژمارەکان لە سەر ئامێرەکە بدۆزەرەوە + + ڕیگە بە نمواڵەکە بدە لیستی هەژمارە ناسراوەکان بەدەستبخات لەلایەن تاتەبژمیرەکەوە. ئەمە لەوانەیە هەریەکێ لە هەژمارەکان بگریتەوە کە لەلایەن نەرمەواڵا دابەزینراوەکانەوە دروست کرابێت. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ به‌ده‌ستهێنانی لیستی هه‌موو هه‌ژماره‌کان له‌لایه‌ن ئامێره‌وه‌ ناسراون. له‌وانه‌یه‌ ئه‌مه‌ هه‌موو هه‌ژمارێکی تیابێت که‌ له‌لایه‌ن به‌رنامه‌کانه‌وه‌ دروستت کردووه‌. + + بینینی په‌یوه‌ندییه‌کانی خه‌ت + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی زانیاری له‌باره‌ی په‌یوه‌ندی خه‌ت وه‌ک چ خه‌تێک هه‌یه‌ و چی په‌یوه‌ندیپێوه‌کراوه‌. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ دروستکردنی زانیاری خه‌ت و به‌کارهێنانی پرۆتۆکۆڵ.وه‌ وێبگه‌ره‌که‌ و به‌رنامه‌ی تر که‌ مانات ده‌داتێ وه‌ک ناردنی داتا بۆ ئینته‌رنێط.ئه‌م ده‌سته‌ڵاته‌ پێویست نییه‌ بۆ ناردنی داتا بۆ ئینته‌رنێت. + + گۆڕینی په‌یوه‌ندی خه‌ت + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی باری په‌یوه‌ندی تۆڕ. + + گۆڕینی په‌یوه‌ندی به‌شداریپێکراو + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی باری په‌یوه‌ندی به‌شداریپێکراوی تۆڕ. + + بینینی په‌یوه‌ندی وایه‌رلێس + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی زانیاری له‌باره‌ی وایه‌رلێس،وه‌ک ئایا وایه‌رلێس کارده‌کات یان ناوی وایه‌رلیسی په‌یوه‌ندی پێکراو. + + په‌یوه‌ندی یان پچڕان له‌ وایه‌رلێسه‌وه‌ + + ڕێگه‌پێدان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردن یان په‌یوه‌ندی پچڕان له‌ ده‌سته‌ڵاتی وایه‌رلێسه‌وه‌ وه‌ گۆڕینی ئامیر بۆ وایه‌رلێس. + + ڕێگه‌دان بۆ وایه‌رلێس 2 قبوڵبکات + + ڕێگه‌دان به‌ به‌رنامه‌کان بۆ وه‌رگرتنی پاکه‌تی په‌یوه‌ندی بۆ هه‌موو ئامێره‌کان له‌ وایه‌رلێسه‌وه‌ بۆ ناونیشانی دوانی.نه‌ک ته‌نیا بۆ تابلێته‌که‌ت.بۆ زۆر هیزی تر به‌کاردێت نه‌ک ته‌نیا دوانی. + + ڕێگه‌دان به‌ به‌رنامه‌کان بۆ وه‌رگرتنی پاکه‌تی په‌یوه‌ندی بۆ هه‌موو ئامێره‌کان له‌ وایه‌رلێسه‌وه‌ بۆ ناونیشانی دوانی.نه‌ک ته‌نیا بۆ ئامێره‌که‌ت.بۆ زۆر هیزی تر به‌کاردێت نه‌ک ته‌نیا دوانی. + + چوونه‌ ناو ڕێکخستنه‌کانی بلوتوس + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێکخستنی بلوتوسی ناوه‌کی تابلێت.وه‌ دۆزینه‌وه‌ و ناساندنی دووره‌ ئامێر. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ڕێکخستنی بلوتوسی ناوه‌کی مۆبایل.وه‌ دۆزینه‌وه‌ و ناساندنی دووره‌ ئامێر. + په‌یوه‌ندی یان پچڕان له‌ وایماکسه‌وه‌ + ڕێگه‌دان به‌ به‌رنامه‌ بۆ بڕیاردان که‌ی وایماکس کار بکات و زانیاری له‌باره‌ی وایماکس که‌ په‌یوه‌ندی پێوه‌کراوه‌.  + ڕێگه‌دان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردنی تابلێت یان پچڕانی تابلێت له‌ وایماکسه‌وه‌. + ڕێگه‌دان به‌ به‌رنامه‌ بۆ په‌یوه‌ندی کردنی مۆبایل یان پچڕانی مۆبایل له‌ وایماکسه‌وه‌. + + ناساندن له‌گه‌ڵ ئامێری بلوتوس + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی ڕێکخستنی بلوتوس له‌سه‌ر تابلێت، وه‌ک قبوڵکردن و دروستکردنی په‌یوه‌ندی له‌گه‌ڵ ناسرێنراوه‌کان. + + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ بینینی ڕێکخستنی بلوتوس له‌سه‌ر مۆبایله‌که‌ت. وه‌ک قبوڵکردن و دروستکردنی په‌یوه‌ندی له‌گه‌ڵ ناسرێنراوه‌کان. + + سه‌رپه‌رشتیکردنی په‌یوه‌ندییه‌ نزیکه‌کان. + + رێگە بە بەرنامەکە دەدات کە کۆنترۆلی پەیوەندی لەرێگەی Near Field Communicationەوە بکات + + ناچالاککردنی داخەری ڕوونما + + ڕێگە بە بەرنامەکە دەدا کە قوفلی دوکمەکان و وشە نهێنیەکەنیان لەکار بخا .بۆ نمونە مۆبایلەکەت لە کاتی هاتنی پەیوەندی ،قوفڵەکە بۆ ماوەیەکی کاتی لەکار دەخا بۆ ئەوەی بتوانی وەڵام بدەیتەوە + + + + + + + + + + + + + + + + + + + + + + + + + خوێندنەوەی زانیاریەکەنی هاوتاکردن + + ڕیگە بە بەرنامەکە دەدا کە زانیاری دەربارەی هاوتاکردن بخوێنێتەوە.بۆ نمونە ئەمە دیاری دەکەت کە ئایا بەرنامەی Pepole لەگەڵ هیچ هەژمارێک هاوتا کراوە یان نە + + هاوتاکردن بکوژێنەوە یان داگیرسێنە + + ڕێگە بە بەرنامەکە دەدا کە دەستکاری رێکخستنی هاوتاکردن بکات.بۆ نمونە ئەمە دەتوانریت بۆ هاوتاکردنی بەرنامەی pepole لەگەڵ هەژمارێک بەکاربێت + + خوێندنه‌وه‌ی هاوتاکردنی ئامارکردنه‌کان + + ڕێگه‌دان به‌ به‌رنامه‌یه‌ک بۆ هاوتاکردنی ئامار بۆ هه‌ژمارێک، وه‌ک مێژووی هاوتاکردنی ڕووداوه‌کان وه‌ چه‌ند داتا هاوتاکراوه‌.  + + خوێندنه‌وه‌ی به‌شه‌کانی ناو بیرگه‌ی USB. + + خوێندنه‌وه‌ی پێکهاته‌ی ناو بیرگه‌ی ناوه‌کی + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی پێکهاته‌ی ناو بیرگه‌ی USB. + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی پێکهاته‌ی ناو بیرگه‌ی ناوه‌کی. + + گۆڕین یان سڕینه‌وه‌ی پێکهاته‌ی بیرگه‌ی USB + + گۆڕین یان سڕینه‌وه‌ی پێکهاته‌ی بیرگه‌ی ناوه‌کی + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ نوسینی بیرگه‌ی USB. + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ نوسینی بیرگه‌ی ناوه‌کی. + + + + + + + + + + + + + + + + خوێندنه‌وه‌ی تۆماری به‌کارهێنانی تۆڕ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ خوێندنه‌وه‌ی تۆماری به‌کارهێنانی تۆڕ بۆ تۆڕێکی تایبه‌ت و به‌رنامه‌. + + به‌ڕێوه‌بردنی ڕه‌وگه‌ی تۆڕ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ به‌ڕێوه‌بردنی ڕه‌وگه‌ی تۆڕ و یاسایی تایبه‌تی به‌رنامه‌. + + گۆڕینی به‌کارهێنانی هەژماری تۆڕ + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ گۆڕینی به‌کارهێنانی هەژماری تۆڕ.بۆ به‌رنامه‌ی ئاسایی به‌کارنایه‌ت. + + ده‌سته‌ڵاتی تێبینییه‌کان + + ڕێگه‌دان به‌ به‌رنامه‌ بۆ ده‌سته‌لاتی وه‌رگرتن و کارپێکردن و پاککردنه‌وه‌ی ئاگادارکردنه‌وه‌کان.وه‌ک پۆسته‌کانی به‌رنامه‌کان. + + گوێ نەدان بە خزمەتگوزاری بیسەری تێبینییەکان + + ڕێگە بە هەڵگر بە بۆ لەکار خستنی دۆخی ئاست-بەرزی خزمەتگوزاری بیسەری تێبینییەکان. هیچکات پێویست نابێت بۆ بەرنامە ئاساییەکان. + + + + + + داواکاری ڕێپێدان بۆ بەرنامەی ڕێکبەندەکانی ئۆپەراتۆر + + ڕێگە بە هەڵگر بە بۆ داواکاری ڕێپێدان بۆ بەرنامەی ڕێکبەندەکانی ئۆپەراتۆر. بۆ بەرنامە ئاساییەکان هیچکات پێویست نابێت. + + گوێدان بە تێبینییەکانی ناو بار و دۆخی تۆڕ + + ڕێگە بە بەرنامەیەک بدە بۆ گوێدان بە تێبینییەکانی ناو بار و دۆخی تۆڕ. بۆ بەرنامە ئاساییەکان هیچکات پێویست ناکات. + + + + + + + + + + + + + + دانانی یاسایی وشه‌ی نهێنی + + + هەوڵەکانی چالاککردنی پێشانگا تۆماربکە + + ژمارەی نهێنوشە هەڵەکان تۆمار بکە + کە ئەنووسرێن کاتی چالاککردنی پێشانگا، تابلێتەکە دابخە یان هەموو زانیارییەکانی + ناو تابلێت بسڕەوە ئەگەر نهێنوشەی هەڵە زۆر جار نووسراوە. + + + ژمارەی نهێنوشە هەڵەکان تۆمار بکە + کە ئەنووسرێن کاتی چالاککردنی پێشانگا، مۆبایلەکە دابخە یان هەموو زانیارییەکانی + ناو مۆبایل بسڕەوە ئەگەر نهێنوشەی هەڵە زۆر جار نووسراوە. + + + + قوفڵی سه‌رڕوونما + + چاودێری پێسانگە بکە کە چۆن و کەی دادەخرێت. + + سڕینەوەی هەموو دراو + + هەموو زانیارییەکانی تابلێتەکە بسڕەوە بێ نیگەرانی لە ڕێکخستنەوەی داتاکانی کارگە. + + + هەموو زانیارییەکانی مۆبایلەکە بسڕەوە بێ نیگەرانی لە ڕێکخستنەوەی داتاکانی کارگە. + + + + + + دانانی پرۆکسی جیهانی بۆ ئامێرەکەت + + + + + نهێنیکردنی بیرگە + + پێویستە کە بەرنامەی هەڵگیراو نهێنی بکرێت. + + لەکارخستنی کامیراکان + + رێگرتن لە بەکارهێنانی هەمو کامیرەکان + + + + + + + ماڵ + موبایل + کار + کاری فاکس + ماڵی فاکس + پەڕە + دیکە + دروستکراو + + + + + + ماڵ + کار + دیکە + دروستکراو + + + + + + ماڵ + کار + دیکە + دروستکراو + + + + + + ماڵ + کار + دیکە + دروستکراو + + + + + + کار + دیکە + دروستکراو + + + + + + ئامانج + Windows Live + یاهوو + سکایپ + QQ + Google Talk + ICQ + Jabber + + + دروستکراو + + ماڵ + + موبایل + + کار + + کاری فاکس + + ماڵی فاکس + + Pager + + دیکە + + Callback + + ئۆتۆمۆبیل + + کۆمپانیای سەرەکی + + ISDN + + سەرەکی + + فاکسی دیکە + + Radio + + تێلێکس + + TTY TDD + + کاری مۆبایل + + Work Pager + + یاریدەدەر + + MMS + + تایبەت + + ڕۆژی لە دایک بوون + + یادکردنەوە + + جۆری تر + + تایبەت + + ماڵەوە + + کار + + جۆری تر + + مۆبایل + + تایبەت + + ماڵەوە + + کار + + دیکە + + ده‌ستکرد + + ماڵه‌وه‌ + + کار + + دیکە + + دەستکرد + + AIM + + Windows Live + + یاهوو + + سکایپ + + QQ + + Hangouts + + ICQ + + Jabber + + NetMeeting + + کار + + دیکە + + دەستکرد + + دەستکرد + + یاریدەدەر + + برا + + مناڵ + + هاوبەشی خۆماڵی + + باوک + + هاوڕێ + + بەڕێوەبەر + + دایک + + باوان + + هاوڕێ + + ئاماژەبۆکراوە لەلایەن + + خزم + + خوشک + + هاوسەر + + دەستکرد + + ماڵەوە + + کار + + دیکە + + هیچ به‌رنامه‌یه‌ک نه‌دۆزرایه‌وه‌ بۆ بینینی ئه‌م په‌یوه‌ندییه‌. + + نوسینی PIN کۆد + + نووسینی PUK لەگەڵ PIN کۆدی نوێ + + PUK کۆد + + PIN کۆدی نوێ + + دەست لێدان بۆ نووسینی تێپه‌ڕوشه‌ + + نوسینی تێپەڕە وشە بۆ کردنه‌وه‌ + + PIN بنووسه‌ بۆ کردنه‌وه‌ + + کۆدی PIN هەڵەیە. + + بۆ کردنه‌وه‌، پەنجە بنێ بە لیست و پاشان 0. + + ژمارەی فریاگوزاری + + + + خزمەتگوزاری نیە. + + شاشە قفلدراوە. + + پەنجە بنێ بە لیست بۆ چالاککردنی یان دانانی تەلەفۆنی فریاگوزاری. + + پەنجە بنێ بە لیست بۆ کردنەوە. + + شێوەکە راکێشە بۆ چالاککردن + + + گەڕانەوە بۆ تەلەفۆن + + ڕاست! + + دوبارە هەوڵبدەرەوە + + دووباره‌ هەوڵ بدەوە + + چالاککردنی قوفڵ بە ڕوخسار هەوڵ زۆر دراوە + + سیمکارتی تیا نیە + + سیمکارت نیە لە تاتەبژمێر. + + + سیمکارت نیە لە تەلەفۆن. + + سیمکارتی تیا بکە. + + سیمکارتەکە تیایە نیە یان نایخوێنێتەوە. سیمکارتی تێبکە. + + سیمکارتەکە بەکارنایەت. + + سیمکارتەکە لە کارخرا .\n پەیوەندی بکە بە کۆمپانیای بێ تەلەوە بۆ سیمێکی تر. + + + + + + + + + ته‌نها په‌یوه‌ندی كتوپڕ + + تۆڕ قوفڵکراوە + + سیمکارتەکە PUK-قوفڵکراوە. + + بینینی تێبینی بەکارهێنەر یان پەیوەندی بکە بە خزمەتگوزاری یارمەتیدەرەوە. + + سیمکارتەکە داخراوه‌. + + کردنەوەی سیمکارت\u2026 + + + تۆ قوفڵی کێشانەکەت بە هەڵە لێداوە %d جار. + \n\nدوبارە هەوڵبدەروەە %d دوەم. +    . + + + + بەهەڵە چەند جارێک تێپەڕە وشەت لێداوە %d جار. + \n\nدوبارە هەوڵبدەرەوە %d دوەم. +    . + + + + چەند جارێک بە هەڵە PIN نوسیوە %d times. + \n\nدوبارە هەوڵبدەرەوە %d دوەمجار. +    . + + + + بەهەڵە هەوڵی چالاککردنی کێشانەکەت داوە بۆ چالاککردن %d times. + After %dزۆر هەوڵدان زیاتر ئەوە پرسیارت لێ ئەکەت بە بەکارهیانی هەژمارەکەت بچیتە ژورەوە.\n\n + Try again in %d دوەم. +    . + + + + + بەهەڵە هەوڵی چالاککردنی کێشانەکەت داوە بۆ چالاککردن %d times. + After %dزۆر هەوڵدان زیاتر ئەوە پرسیارت لێ ئەکەت بە بەکارهیانی هەژمارەکەت بچیتە ژورەوە.\n\n + Try again in %d دوەم. +    . + + + + چەند جارێک هەوڵی کردنەوەی تاتەبژمێرەکەت داوە بە‌ەلە %d times. + After %d بەهەڵە لێی بدەیتەوە ئەوە تاتەبژمێرەکەت ئەچێتەوە باری بنەڕەت و هەموو داتاکان و فایلەکان ئەسڕێتەوە. +    . + + + + + چەند جارێک هەوڵی چالاککردنی تاتەبژمێرەکەت داوە بە‌ەلە %d times. After %d بەهەڵە لێی بدەیتەوە ئەوە تاتەبژمێرەکەت ئەچێتەوە باری بنەڕەت و هەموو داتاکان و فایلەکان ئەسڕێتەوە. + + + + تۆ بەهەڵە هەوڵت داوە تاتە بژمێرەکە بکەیتەوە %d times. + Tزۆر هەڵە لێدانی فایلەکان ئەسڕێتەوە بۆ باری بنەڕەتی ئەچێتەوە. +    . + + + + + بەهەڵە هەوڵت داوە بۆ چالاککردنی تەلەفۆنەکەت %d times. + تەلەفۆنەکە ئێستا ئەجیتەوە باری بنەڕەتی. +    . + + + دوبارە هەوڵبدەرەوە %d دووەم. + + بیرچونی کێشانەکە? + + کردنەوەی هەژمارەکە + + زۆر هەوڵت داوە قوفڵە کێشان دانێیت + + بۆ کردنەوە.بچۆ ژورەوە بە هەژماری Googleەکەت. + + ناو(ئیمەیڵ) + + تێپەڕەوشە + + چونەژورەوە + + ناو لە کارە نیە یان تێپەڕە وشە. + + ناو یان تێپەڕە وشەکەت بیرچوە؟\?\nVisit google.com/هەمار/recovery. + + پشکنین\u2026 + + چالاککردن + + چالاککردنی دەنگ + + ناچالاککردنی دەنگ + + قوفڵ کێشان دەستی پێکرد + + کێشانەکە پاکرایەوە + + خانە زیادکرا + + + کێشانەکە تەواوکرا + + ناوچەی کێشان. + + %1$s. وێدج%2$d of %3$d. + + زیادکردنی کورته‌وێنه‌. + + بەتاڵ + + کردنەوی ناوچە بڵاوکرایەوە. + + ناوچەی چالاککردن لەناوچوون. + + %1$s widget. + + هەڵبژاردەی بەکارهێنەر + + ئاست + + کامێرا + + کۆنترۆڵی ڕاگه‌یێنه‌کان + + دوبارە کورته‌وێنه‌ەکە داوابکە. + + داواکردنی وێدجەکان کۆتایهات. + + کورته‌وێنه‌ %1$s سڕایەوە. + + بڵاوکردنەوەی ناوچەی کردنەوە. + + کردنەوە بە لادان. + + کردنه‌وه‌ بە گه‌یاندن. + + چالاککردن بە ڕووخسار. + + کردنەوە بە کۆد. + + کردنەوە بە تێپەڕەوشە. + + ناوچەی کێشان. + + ناوچەی لادان. + + + + \?123 + + ABC + + ALT + + کارەکتەر + + وشە + + بەستەرە + + هێڵ + + "%-l%P" + + "%-l%p" + + گەڕانەوە بۆ باری ئاسایی سەرنەکەوت + + چالاکی بۆ باری بنەڕەتی +تەنها پاڵپشتی ئەوانە دەکات کە دامەزراون لە سیستەم/بەرنامە. + + هیچ گورزەیەک نەدۆرایەوە کە + فرمانی تاقیکاری کارگە لە خۆ بگرێت. + + دووباره‌ داگیرساندنه‌وه‌ + + + + پەڕەکە لە \"%s\" ئەڵێت: + + جاڤاسکریپت + + دڵنیاکردنەوەی ڕێدۆزەر + + جێهێشتنی ئەم پەڕەیە + + مانەوە لەسەر ئەم پەڕەیە + + %s\n\nتۆى دڵنيان تۆ دەوێتان تا دوور لە ئەمە لاپەڕەوە بەناودا بڕوات؟ ? + + دلنیاکردنەوە + + سەر: دوجار -لێدان بۆ زوم نزیک و دەرەوە. + + خۆکارپڕ + + دانانی خۆکارپڕ + + \u0020 + + $1$2$3 + + ,\u0020 + + $1$2$3 + + سەرنجدان|attn + + province|region|other|provincia|bairro|suburb + + company|business|organization|organisation|department|firma|firmenname|empresa|societe|société|ragione.?sociale|会社|название.?компании|单位|公司 + + address.?line|address1|addr1|street|strasse|straße|hausnummer|housenumber|house.?name|direccion|dirección|adresse|indirizzo|住所1|morada|endereço|Адрес|地址 + + ناونیشان|adresse|indirizzo|住所|地址 + + ناونیشان.?line2|address2|addr2|street|suite|unit|adresszusatz|ergänzende.?angaben|direccion2|colonia|adicional|addresssuppl|complementnom|appartement|indirizzo2|住所2 + + ناونیشان.?line3|address3|addr3|street|line3|municipio|batiment|residence|indirizzo3 + + وڵات|ناوچه‌|国|国家 + + zip|postal|post code|pcode|^1z$|postleitzahl|cp|cdp|cap|郵便番号|codigo|codpos|cep|Почтовый.?Индекс|邮政编码|邮编|郵遞區號 + + zip|^-$|post2|codpos2 + + city|town|ort|stadt|suburb|ciudad|provincia|localidad|poblacion|ville|commune|localita|市区町村|cidade|Город|市|分區 + + state|county|region|province|land|county|principality|都道府県|estado|provincia|область|省|地區 + + وەکو هەمان + + بەکارهێنانی + + گەڵاڵە + + ناردن + + e.?mail|メールアドレス|Электронной.?Почты|邮件|邮箱|電郵地址 + + user.?name|user.?id|vollständiger.?name|用户名 + + ^name|full.?name|your.?name|customer.?name|firstandlastname|nombre.*y.*apellidos|^nom|お名前|氏名|^nome|姓名 + + ^name|^nom|^nome + + irst.*name|initials|fname|first$|vorname|nombre|forename|prénom|prenom|名|nome|Имя + + ةاوەند.*initial|m\\.i\\.|mi$ + + ناوی ناوەنجی.*ناو|mname|ناوەند$|apellido.?materno|کۆتای ناو + + last.*name|lname|surname|last$|nachname|apellidos|famille|^nom|cognome|姓|morada|apelidos|surename|sobrenome|Фамилия + + phone|telefonnummer|telefono|teléfono|telfixe|電話|telefone|telemovel|телефон|电话 + + ناوچە.*کۆد|acode|ناوچە + + prefix|preselection|ddd + + پاشگر + + ext|ramal + + card.?holder|name.?on.?card|ccname|owner|karteninhaber|nombre.*tarjeta|nom.*carte|nome.*cart|名前|Имя.*карты|信用卡开户名|开户名|持卡人姓名|持卡人姓名 + + ناو + + گونجاندن|کارتidentification|cvn|security code|cvv code|cvc + + ژمارە|کارت.?#|card.?no|ccnum|nummer|credito|numero|número|numéro|カード番号|Номер.*карты|信用卡号|信用卡号码|信用卡卡號 + + بەسەرچوون|exp.*مانگ|نمونە.*ڕۆژ|ccmonth|gueltig|gültig|monat|fecha|date.*exp|scadenza|有効期限|لەکارە|Срок действия карты|月 + + exp|^/|year|ablaufdatum|gueltig|gültig|yahr|fecha|scadenza|有効期限|validade|Срок действия карты|年|有效期 + + ^کارت + + فاکس|télécopie|telecopie|ファックス|факс|传真|傳真 + + وڵات.*کۆد|ccode|_cc + + ^\\($ + + ^-$|^\\)$ + + ^-$ + + پارێزگا + + کۆدی پۆستان + + دەوڵەت + + کۆدی پۆستە + + وڵات + + دوورگە + + ناوچە + + بەش + + ولایەت + + پاریس + + ناوچە + + میرنشین + + خوێندنەوەی وێبنیشانکەرەکە و مێژوو + + رێگە بە بەرنامە بە بۆ خوێندنەوەی + مێژووی هەموو ئەو وێبپەڕانەی کە وێبگەڕەکەت سەردانی کردوون، لەگەڵ هەموو وێبپەڕە + هیماکراوەکان. تێبینی: ئەم ڕێدانە لەوە ئەچێ پابەند نەبێت بە وێبگەڕە یاریدەدەرەکانەوە + یان ئەو بەرنامانەی کە توانایی گەڕانی وێبیان هەبێت. + + نوسینی په‌رتوکنیشانکه‌ری وێبگه‌ر و مێژو + + + + + دانانی زەنگ + + + زیادکردنی نامەی دەنگی + + ڕێگەدان بە بەرنامەکە بۆ زیادکردنی نامەکان +بۆ سندوقی دەنگە نامە. + + لابردنی تازەکردنەوەی شوێنی جوگرافی وێبگەر + + ڕێ دەدات بە بەرنامە تا بگۆڕێت + +ڕێگەپێدانى شوێنی جوگرافی براوزە. بەرنامەى ڤایرۆسی + +لەوانەيە ئەمە بەكار بهێنێت تا ڕێ بدات بە بۆ ناردنى وێبسايتى زانياريى شوێن هەرەمەكى. + + ئایا دەتەوێت وێبگەڕەکەت ئەم نهێنووشەیە بە یادت بهێنێتەوە؟ + + ئێستا نا + + وەبیرهاتنەوە + + هەرگیز + + تۆ ڕێگەت نیە بۆ چالاککردنی ئەم پەڕەیە. + + دەقەکە لەبەریگیرایەوە بۆ پارێزەر. + + زیاتر + + پێڕست+ + + بۆشایی + + دانان + + سڕینەوە + + + + گەڕان + + + گەڕان + + داوای گەڕان + + پاکردنەوەی داوا + + ناردنی داوا + + گەڕانی دەنگی + + چالاککردنی گەڕان بە دەستلێدان + + + %1$sبوێ تا لەلايەن دەست لێدان سەرنج بدات. + +كاتێك لەلايەن دەست لێدان بەكار دەخرێت، تۆ دەتوانن ببيستن يان باسكردنى دەبينن ئەوەى كەى لەژێر + +پەنجەت يان نيشانە ئەنجام دەدات تا لەگەڵ حەبەكە كار لە يەك بكەن. + + + %1$sبوێ تا لەلايەن دەست لێدان سەرنج بدات. + +كاتێك لەلايەن دەست لێدان بەكار دەخرێت، تۆ دەتوانن ببيستن يان باسكردنى دەبينن ئەوەى كەى لەژێر + +پەنجەت يان نيشانە ئەنجام دەدات تا لەگەڵ حەبەكە كار لە يەك بكەن. + + 1 مانگ لەمەوپێش + + لە پێش 1 مانگ لەمەپێش + + + مانگی دوایین + + بەتەمەنتر + + لەسەر%s + + لەسەر%s + + لەناو%s + + رۆژ + + رۆژەکان + + کاژێر + + کاژێرەکان + + خولەک + + خولەکەکان + + چرکە + + چرکەکان + + هەفتە + + هەفتەکان + + ساڵ + + ساڵەکان + + + + + کێشەی ڤیدیۆ + + ڤیدیۆکە لەکارە نیە لەسەر ئەم ئامێرە. + + ناتوانرێت ئەم ڤیدیۆیە لێدرێت + + باشه‌ + + "%1$s, %2$s" + + "نیوەڕۆ" + + "نیوەڕۆ" + + "نیوەشەو" + + "نیوەشەو" + + %1$02d:%2$02d + + %1$d:%2$02d:%3$02d + + دیاریکردنی هەموو + + بڕین + + لەبەرگرتنەوە + + لكاندن + + لەبریدانان\u2026 + + سڕینه‌وه‌ + + لەبەرگرتنەوەURL + + هەڵبژاردنی دەق + + دەقی دیاریکراو + + زیادبکە بۆ فەرهەنگ + + سڕینه‌وه‌ + + تێكردن ڕێگە + + چالاکی دەق + + بیرگەی بۆشایی خەریکە نامێنێت + + هەمان کرداری سیستەم لەوانەیە ئیش نەکات + + + %1$s + لە کارە + + دەستلێدان بۆ زانیاری زیاتر +یان بەرنامەکە بوەستێنە. + + باشه‌ + + هەڵوەشاندنەوە + + باشه‌ + + هەڵوەشاندنەوە + + ئاگاداری + + دامەزراندنی\u2026 + + چالاککردن + + کووژاوە + + تەواوکردنی بەکارهێنانی چالاکیەکە + + + + + + + + + + + بەکارهێنانی بنەڕەت بۆ ئەم چالاکیە. + + + پاکردنەوەی بنەڕەت لە ڕێکخستنی سیستەم وgt; Apps وgt; دابەزی. + + چالاکیەک هەڵبژێرە + + هەڵبژاردنی بەرنامەیک بۆ ئامێری USB + + ‌هیچ بەرنامەیەک ناتوانێت ڕۆڵی ئەم چالاکیە ببینێت. + + + + بەداخەوە, %1$sوەستا. + + بەداخەوە پرۆسەکە %1$s وەستا. + + + + %2$s وەڵام نادانتەوە.\n\nئەتەوێت دایخەیت? + + چالاکی%1$s وەڵام ناداتەوە.\n\nئەتەوێت دایخەیت? + + %1$s وەڵام ناداتەوە ئەتەوێت دایخەیت? + + پرۆسەکە%1$sوەڵام نادرێتەوە .\n\nئەتەوێت دایخەیت? + + باشه‌ + + ڕاپۆرت + + چاوەڕێ + + ئەم پەڕەیە کارا نەماوە.\n\nئایا دەتەوێ دایبخەی؟ + + بەرنامە گواسترایەوە + + %1$s ئێستا له‌کاره‌. + + %1$s لە بنەڕەتدا دەستپێکرابوو. + + پێوانە + + هەمیشە پیشانبدە + + سەر لەنوێ ئەمە چالاک بکەوە لە ڕێکبەندەکانی سیستەم وgt; بەرنامەکان وgt; دابەزێندراوەکان. + + بەرنامەی %1$s + (ئەرکی %2$s) بە شێوەی خۆسەپاو لە دۆخێکی دژواری پاراستن سەرپێچی کردووە. + + ئەرکی %1$s has + بە شێوەی خۆسەپاو لە دۆخێکی دژواری پاراستن سەرپێچی کردووە. + + ئەندرۆید لە نوێکاریدایە\u2026 + + + + باشینەسازی بەرنامە + %1$d ی + %2$d. + + + دەستپێکردنی بەرنامەکان. + + تەواوبوونی بووت. + + %1$s کارکردن + + لێدە بۆ گۆڕین بۆ بەرنامە + + گۆڕینی بەرنامەکان؟ + + بەرنامەیەکی دیکە لە کارادایە + کە ئەبێ بوەستێندرێت پێش ئەوەی کە دانەیەکی نوێ دەستپێبکەیت. + گەڕانەوە بۆ %1$s + بەرنامەی نوێ دەست پێ مەکە. + دەستپێکردنی %1$s + بەرنامە کۆنەکە بوەستێنە بێ پاشەکەوتکردن. + + + + + + فرمانێک هەڵبژێرە بۆ نووسراوە + + قەبارەی دەنگی زەنگ لێدەر + + ده‌نگی ڕاگه‌یێنه‌کان + + لێدان لەڕێگەی بلوتوسەوە + + دانانی زەنگی بێدەنگ دانرا + + دەنگی تەلەفۆنی هاتوو + + دەنگی تەلەفۆن لە ڕیگەی بلوتوسەوە + + ده‌نگی بیرخه‌ره‌وه‌ + + ده‌نگی تێبینی + + دەنگ + + ده‌نگی بلوتوس + + دەنگی زەنگ + + دەنگی تەلەفۆن + + ده‌نگی ڕاگه‌یێنه‌کان + + ده‌نگی تێبینی + + + + زەنگی بنەڕەتی + + زەنگی بنەڕەتی (%1$s) + + هیچ + + دەنگی زەنگ + + زەنگی نەناسراو + + + Wi-Fi تۆڕ لەکارە + Wi-Fi تۆڕ لەکارە + + + + Wi-Fi تۆڕی کراوە لە کارە + Wi-Fi تۆڕەکانی کراوە لە کارە + + + + + %1$s + + + + ناتوانرێت پەیوەستبکرێت بە Wi-Fiەوە + + هێڵی \u0020 ئینته‌رنێتێکی لاوازی هه‌یه‌. + + + + + + Wi-Fi ڕاستەوخۆ + دەستپێکردنی Wi-Fi. ئەمە Wi-Fi /هۆتسپۆت ئەکوژێنێتەوە. + ناتوانرێت Wi-Fi یەکسەر بکەوێتە کار. + Wi-Fi ڕاستەوخۆ لە کارە + سوین بۆ ڕێکخستن + پەسەند کردن + ڕەتکردنەوە + بانگەشەکردنەکە نێردرا + بانگەشەکردن بۆ پەیوەندکردن + لە:  + بۆ:  + PINی پێویست بنووسە: + PIN: + تابلێت بۆ ماوەی کاتی پەیوەندی Wi-Fi ئەپچڕێنێت کاتێک بەستراوەتەوە بە %1$s + تەلەفۆن بۆ ماوەی کاتی پەیوەندی Wi-Fi ئەپچڕێنێت کاتێک بەستراوەتەوە بە %1$s + + تێخستنی نووسە + + + + ناردنی کورتە نامە + + وlt;bوgt;%1$sوlt;/bوgt; خەریکە ژمارەیەکی زۆر کورتە نامە دەنێرێت. ئایا دەتەوێت ڕێگە بەم بەرنامە بدەیت بۆ ناردنی کورتەنامەکان؟ + + رێدان + + نکوڵی + + + + وlt;bوgt;%1$sوlt;/bوgt; داخوازی ناردنی کورتە نامەی بۆ وlt;bوgt;%2$sوlt;/bوgt;. + + + + ناردن + + هەڵوەشاندنەوە + + بیرم بهێنەوە هەڵبژاردەکەم + + ئەتوانی ئەمە دواتر بگۆڕیت لە ڕێکخستن\u00A0وgt;\u00A0Apps\" + + هەمیشە ڕێگە بدە + + هەرگیز ڕێگە مەدە + + + + سیمکارتەکە دەرکرا + + + ئه‌نجام درا + + سیمکارتەکە زیادکرا + + + لەنۆکردنەوە + + + دیاریکردنی کات + + دیاریکردنی ڕۆژ + + دانان + + کراو + + + تازە: + + ئامادەکرا لەلایەن %1$s. + + هیچ یارمەتیەک داوانەکراوە + + ئەمە پێ ئەچێت پارەت لێبسێنێت + + + بارستەی USB بیرگە + + USB په‌یوه‌ست کرا + + تۆ بەستراویتەوە بە کۆمپیوتەرەکەت بە USB. دوگمەی خوارەوە لێدە ئەگەر تۆ دەتەوێت فیلەکانت کۆپی بکەی لە نێوان کۆمپیوتەر و بیرگەی USB ئەندرۆیدەکەت. + + تۆ بەستراویتەوە بە کۆمپیوتەرەکەت بە USB. دوگمەی خوارەوە لێدە ئەگەر تۆ دەتەوێت فیلەکانت کۆپی بکەی لە نێوان کۆمپیوتەر و بیرگەی هەڵگرتنی ئەندرۆیدەکەت. + + هەڵکردنی بیرگه‌ی USB + + هەڵەیەک هەیە لە بەکار هێنانی بیرگەی USB بۆ بیرگه‌ی USB. + + هەڵەیەک هەیە لە بەکار هێنانی بیرگەی هەڵگرتنی بۆ بیرگه‌ی USB. + + USB بەسترایەوە + + دەست لێدە بۆ کۆپی کردنی فایلەکان بۆ/لە ناو کۆمپیوتەرەکەتدا. + + کوژاندنەوەی بیرگه‌ی USB + + دەست لێدە بۆ کوژاندنەوەی بیرگه‌ی USB. + + + + بیرگەی USB لە کارادایە + + پێش ئەوەی بیرگەی USB بکووژێنیتەوە، بیرگەی USB ئەندرۆیدەکەت لە ناو کۆمپیوتەرەکەت (\"بهێنەدەر\") دەربکێشە. + + پێش ئەوەی بیرگەی USB بکووژێنیتەوە، بیرگەی کارتی هەڵگرتنی ئەندرۆیدەکەت لە ناو کۆمپیوتەرەکەت (\"بهێنەدەر\") دەربکێشە. + + کوژاندنەوەی کۆگای USB + + هەڵەیەک ڕوویدا کاتی کووژاندنەوەی بیرگه‌ی USB. بزانە بیرگەی USB و هەڵگرتنی دەرهێنراون، پاشان دووبارە هەوڵبدەوە. + + هەڵکردنی کۆگای USB + + ئەگەر بیرگه‌ی USB هەڵبکەیت، هەندێک بەرنامە کە لە ئێستادا بەکاریان ئەهێنی ئەوێستن و لەوە ئەچێ بەردەستیش نەبن تاکو بیرگه‌ی USB دەکوژێنیتەوە. + + سەرکەوتو نەبوو USB فرمانی + + باشه‌ + + + + + + USB په‌یوه‌ست کرا وەک یاریدەدەری + + + ‌هەڵەدۆزینەوەی USB بەستراوەتەوە + + دەست لێدە بۆ ناچالاککردنی هەڵەدۆزینەوەی USB. + + + + + + + + + + رەقەکاڵا + + چۆری تەختەکلیل دیاریبکە + + پەنجەی پێدا بنێ بۆ دیاریکردنی تەختەکلیل. + \u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ + \u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ + دەستنیشانکراوەکان + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + پشکنین\u2026 + + + + + + + + + + هیچ چلاکییەکی لەیەک چوو نەدۆزرایەوە. + + + ڕێگە بە بەرنامەیەک بدە تاکو ڕێپیشاندەری بەرهەمی میدیا بکات بۆ دیکەی ئامێرە دەرەکییەکان. + + + + + + دووجار دەست لێدە بۆ چاودێری گەورەکردنەوە + + ناتوانرێت کورتە وێنۆچک‌ زیادبکرێت. + + بڕۆ + + گه‌ڕان + + ناردن + + دواتر + + کراو + + پێشوو + + بەجێهێنان + + + + ژمارە بگرە\nبە بەکارهێنانی %s + + دروستکردنی ناو\nبەهۆی %s + + + + یەک یان چەند بەرنامەی ناوبراو داوای ڕێگەپێدان ئەکەن بۆ دەسی پێ گەیشتنی ئەژمێرەکەت، ئێستا و لە داهاتوودا. + ئەتەوێ ڕێگە بدەیت بەم داواکارییە؟ + داواکردنی ڕێگەپێدان + رێگەدان + نکۆڵی + داواکردنی مۆڵەت پێدان + داواکردنی مۆڵەت پێدان \nfor account %s. + + + + شێوازی نوسین + + هاوکاتکردن + + توانای ده‌ستپێگه‌شتن + + وێنەی سەرشاشە + + گۆڕینی دیوارپۆش + + گوێگری تێبینییەکان + + + + VPN چالاکرا + + VPN چالاکراو لەلایەن %s + + دەست لێدە بۆ بەڕێوەبردنی تۆڕەکە. + + گرێدراوە بە %s. دەست لێدە بۆ بەڕێوەبردنی تۆڕەکە. + + \"VPN\"ی هەردەم چالاک گرێدەدرێت\u2026 + + \"VPN\"ی هەردەم چالاک گرێدرا + + \"VPN\"ی هەردەم چالاک هەڵەی دا + + دەست لێدان بۆ سازدان + + + هەڵبژاردنی پەڕگە + + هیچ فایلێک دەستنیشان نەکراوە + + ڕێکخستنەوە + + پێشکەشکردن + + + دۆخی ئۆتۆمۆبیل چالاک کرا + دەست لێدان بۆ ده‌رچوون لە دۆخی ئۆتۆمۆبیل. + + + چالاککردن و به‌ستنه‌وه‌ی hotspot + دەست لێدان بۆ جێگیركردن. + + گەڕانەوە + دواتر + + تێپەڕاندن + + هیچ ئەنجامێک نیە + + دۆزینەوە لە پەڕە + + + + 1 هاوتا + + %d لە %d + + + تەواو + + + سڕینەوەی بیرگەیUSB\u2026 + + سڕینەوەی بیرگەی دەرەکی\u2026 + + + هاوبه‌شیکردن + + دۆزینەوە + + بەدواگەڕانی وێب + + دۆزینەوەی داهاتوو + + دۆزینەوەی پێشوو + + داواکردنی شوێن لە %s + + داواکردنی شوێن + + داواکراوە لەلایەن%1$s (%2$s) + + بەڵێ + + نەخێر + + سڕینەوەی سنوور زیاد لە پێویست + + بە ژماردە %1$d بڕگەی سڕیاو هەیە بۆ %2$s, ئەژمێری %3$s. دەتهەوێ چی بکەی؟ + + سڕینەوەی بڕگەکان + + هه‌ڵوه‌شاندنه‌وەی سڕینەوەکان + + هیچ مەکە بۆ ئێستا + + هەژمارێک هەڵبژێرە + "زیادکردنی هەژمار" + + دانانی هەژمار + + + زیادکردن + + کەمکردن + + %s دەستلێدە و بوەستە. + + لادان سەرۆ بۆ کەمکردن و بۆ خوارۆ بۆ زیادکردن. + + + زۆربوونی خولەک + + کەمبوونەوەی خولەک + + زۆربوونی کاژێر + + کەمبوونەوەی کاژێر + + دانای ئێوارە + + دانای بەیانی + + + زۆربوونی مانگ + + کەمبوونەوەی مانگ + + زۆربوونی رۆژ + + کەمبوونەوەی رۆژ + + زۆربوونی ساڵ + + کەمبوونەوەی ساڵ + + + + + Alt + + پاشگەزبونەوە + + تاقیکردنەوەی ئەژمێر + + ئه‌نجام درا + + گۆڕینی جۆر + + شوێنگۆڕین + + دانان + + + داخستنی بەرنامەیەک + + نەتوانرا دەستپێبکات %s + + + بەشداری لەگەڵ + + بەشداری لەگەڵ %s + + + "لادانی دەستی. دەستلێدانوamp; هەڵگرتن." + + لایدە بۆ چالاککردن. + + بیستۆک ببەستەوە بۆ بیستنی دەنگی کلیلەکان کاتی نوسینی نهێنوشە. + + خاڵ. + + بڕۆ بۆ ماڵەوە + + بڕۆ بۆ سەرەوە + + بەربژاردەی زیاتر + + %1$s, %2$s + + %1$s, %2$s, %3$s + + بیرگەی ناوەکی + + بیرەگەی دەرەکی + + + + + هەڵگری USB + + ئاگادارکردنەوەی بەکارهێنانی داتا + + دەست لێدە بۆ بینینی بەکارهێنانەکان و ڕێکبەندەکان. + + + + + + + 2G-3G زانیاری سنوردار به‌سه‌رچوو + + زانیاری سنورداری 4G به‌سه‌رچوو + + + Wi-Fi زانیاری سنور به‌سه‌رچو + + %s سنورداری دیاریکراو. + + زانیاری پشتەگەڵاڵە سنوردارکرا + + دەستلێدان بۆ سڕینەوەی سنوردارکردن. + + + بڕوانامه‌ی پاراستن + + بروانامەکە تەواو نیە. + + بڵاوکراوە بۆ: + + ناوی هاوبەش: + + ڕێکخراو: + + یه‌که‌ی ڕێکخراوی: + + بڵاوکراوە لەلایەن: + + له‌کاره‌: + + ده‌رچوه‌ له‌: + + بەسەردەچێ لە: + + زنجیرە ژمارە: + + په‌نجه‌مۆر: + + SHA-256 په‌نجه‌مۆر: + + SHA-1 په‌نجه‌مۆر: + + هەموو ببينە + + هەڵبژاردنی چالاکی + + هاوبەشی بکە بە ناوی + + ", " + + ناردن\u2026 + + چالاککردنی وێبگەر؟ + + پەیوەندی وەردەگرێت؟ + + هەمیشە + + ته‌نیا یه‌کجار + + + تابلێت + + + مۆبایل + + بیستۆک + + بڵندگۆی له‌نگه‌ر + + HDMI + + سیستەم + + ده‌نگی بلوتوس + + نیشاندانی وایه‌رلێسی + + + په‌یوه‌ندی کردن به‌ ئامێر + + ڕێگه‌گرتنی ڕوونما بۆ ئامێر + + گه‌ڕان به‌دوای ئامێر\u2026 + + ڕێکخستنه‌کان + + په‌یوه‌ندی پچڕان + + پشکنین... + + په‌یوه‌ندیكردن... + + ئاماده‌ + + ئاماده‌ نیه‌ + + سەرقاڵە + + + دروست کراو-لە شاشە + + شاشەی HDMI + + دادەپۆشى #%1$d + + %1$s: %2$dx%3$d, %4$d dpi + + , پارێزراو + + + بیرچونی کێشانەکە + + کێشان هەڵە + + تێپەڕەوشەی هەڵە + + PIN هەڵەیە + + دوبارە هەوڵبدەرەوە %1$d چرکە. + + قوفڵی کێشان بکێشە + + دانانی کۆدی سیمکارت + + PIN بنوسە + + نهێنوشە بنوسە + + سیمکارتەکە لە کارکەوتوە ئێستا.PUK لێ بدە بۆ بەردەوام بوون. بۆ وردەکاری زیاتر پەیوەندی بکە بە ئۆپەراتۆر. + + کۆدێکی PIN بەخواستی خۆت دابنێ + + کۆدی PIN دوپاتکەرەوە + + کردنەوەی سیمکارت\u2026 + + کۆدی PIN ناڕاستە. + + (PIN)ەک بنووسه‌ که‌ ٤ بۆ ٨ ژماره‌ بێت. + + + دوبارە کۆدی PUK دروست تێبنووسەوە. هەوڵدانە دوبارەکراوەکان بۆ هەمیشە سیمکارتەکەت لاچالاک ئەکات. + + کۆدەکانی PIN لە یەکتر ناچن + + هەوڵی کێشانی ئێجگار زۆری شێوەئاسا + + بۆ کردنەوە، بە هەژماری گوگڵ بچۆ ژووره‌وه‌. + + ناوی بەکارهێنەر (ئیمەیڵ) + + تێپەڕەوشە + + چوونەژوورەوە + + ناو یان تێپه‌ڕوشه‌ ڕاست نییه‌. + + ناو یان تێپەڕەوشەت لە بیرچووە\?\nVisit google.com/accounts/recovery. + + تاقیکردنەوەی ئەژمێر\u2026 + + + بە هەڵە %d جار PIN ت نووسیوە. + \n\nله‌ %d چرکه‌دا سەرلەنوێ هەوڵبدەوە. + +    . + + + + بەهەڵە %d جار تێپەڕەوشەت لێداوە. + \n\nله‌ %d چرکه‌دا سەرلەنوێ هەوڵبدەوە. + +    . + + + تۆ بە ناڕاست %d جار چنراوی کردنەوەت کێشاوە. + \n\nلە %d چرکەدا سەرلەنوێ هەوڵبدەوە. + + + + تۆ بە ناڕاست %d times جار هەوڵی کردنەوەی تابلێته‌که‌ت داوە. + پاش %d هه‌وڵی سه‌رنه‌که‌وتووی زیاتر، + تابلێته‌که‌ ڕێکدەخرێتەوە بۆ بنەڕەتی کارگە هەروەها هه‌موو دراوەکانی به‌کارهێنه‌ر بزر دەبن. + + +    . + + + + + تۆ بە ناڕاست %d times جار هەوڵی کردنەوەی مۆبایلەکەت داوە. + پاش %d هه‌وڵی سه‌رنه‌که‌وتووی زیاتر، + مۆبایلەکە ڕێکدەخرێتەوە بۆ بنەڕەتی کارگە هەروەها هه‌موو دراوەکانی به‌کارهێنه‌ر بزر دەبن. + + +    . + + + + تۆ بە ناڕاست %d جار هەوڵی کردنەوەی تابلێتەکەت داوە. + تابلێتەکە ڕێکدەسرێتەوە بۆ بنەڕەتی کارگە. + + + + + تۆ بە ناڕاست %d جار هەوڵی کردنەوەی مۆبایلەکەت داوە. + مۆبایلەکە ڕێکدەسرێتەوە بۆ بنەڕەتی کارگە. + + + + تۆ بەهەڵە شیوازی کردنەوەت %d جار کێشاوە. + دوای %d جاری دیکە هەوڵدانی هەڵە, + داوای ئەژمێری ئیمێڵەکەت لێئەکرێت بۆ کردنەوەی تابلێتەکەت.\n\n + دوبارە هەوڵبدەوە لە %d چرکەی دیکەدا. + + + + + تۆ بەهەڵە شیوازی کردنەوەت %d جار کێشاوە. + دوای %d جاری دیکە هەوڵدانی هەڵە, + داوای ئەژمێری ئیمێڵەکەت لێئەکرێت بۆ کردنەوەی مۆبایلەکەت.\n\n + دوبارە هەوڵبدەوە لە %d چرکەی دیکەدا. + + + " \u2014 " + + سڕینەوە + + + دو قامکت ڕاگرە لەکاتی کێشان بۆ خوارەوە بۆ چالاککردنی خزمەتگوزاری بەئاسانی بەدەست گەیشتن. + + خزمەتگوزاری بەئاسانی بەدەست گەیشتن چالاککرا. + + توانای ده‌ستپێگه‌شتن پاشگەزبووەوە. + + بەکارهێنەری ئێستا %1$s. + + + خاوەن + + هەڵە + + + هیچ نەرمەواڵایەک نەدۆزرایەوە تاکو ئەم کردارە لەخۆ بگرێت + ‌هەڵوەشاندنەوه + + + ISO A0 + + ISO A1 + + ISO A2 + + ISO A3 + + ISO A4 + + ISO A5 + + ISO A6 + + ISO A7 + + ISO A8 + + ISO A9 + + ISO A10 + + ISO B0 + + ISO B1 + + ISO B2 + + ISO B3 + + ISO B4 + + ISO B5 + + ISO B6 + + ISO B7 + + ISO B8 + + ISO B9 + + ISO B10 + + ISO C0 + + ISO C1 + + ISO C2 + + ISO C3 + + ISO C4 + + ISO C5 + + ISO C6 + + ISO C7 + + ISO C8 + + ISO C9 + + ISO C10 + + نامە + + نامەی حکومی + + یاسا + + یاسایی پەیوەند + + دەفتەری تێبینی + + پڕوێنە + + Index Card 3x5 + + Index Card 4x6 + + Index Card 5x8 + + Monarch + + Quarto + + Foolscap + + ROC 8K + + ROC 16K + + PRC 1 + + PRC 2 + + PRC 3 + + PRC 4 + + PRC 5 + + PRC 6 + + PRC 7 + + PRC 8 + + PRC 9 + + PRC 10 + + PRC 16K + + Pa Kai + + Dai Pa Kai + + Jurro Ku Kai + + JIS B10 + + JIS B9 + + JIS B8 + + JIS B7 + + JIS B6 + + JIS B5 + + JIS B4 + + JIS B3 + + JIS B2 + + JIS B1 + + JIS B0 + + JIS Exec + + Chou4 + + Chou3 + + Chou2 + + Hagaki  + + Oufuku  + + Kahu + + Kaku2 + + You4 + + روخسار نەناسراو + + شێوە ئاسۆی نەناسراو + + پاشگەزبووەوە + + هەڵە لە نووسینی ناوەڕۆک + + نەناسراو + + خزمەتگوزاری چاپکەر نا چالاکە + + %s خزمەتگوزاری دامەزرا + + لێدان بۆ چالاککردن + + PIN ‌بەڕێوەبەرێكى ئامراز بنووسە + + PIN بنووسە + + نادرووست + + PIN هەنووکە + + PIN نوێ + + پشتڕاستکردنەوەی PIN نوێ + + PIN دروست بکە بۆ گۆڕینی بەسترانەوەکان + + PIN ناگونجێت. دوبارە هەوڵبدەرەوە. + + PIN زۆر کورتە. ئەبێ لانیکەم 4 ژمارە بێت. + + + + دوبارە هەوڵبدەرەوە لە 1 چرکەی تر + دوبارە هەوڵبدەرەوە لە %d چرکەکان + + + دواتر دووبارە هەوڵبدە + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + مەمشێوێنە + + + + + + + + + + + + + + + بەربژاردەی زیاتر + + + + + + diff --git a/core/res/res/values-ky-rKG-watch/strings.xml b/core/res/res/values-ky-rKG-watch/strings.xml index 3f167acf67169..cf64bc6ff8368 100644 --- a/core/res/res/values-ky-rKG-watch/strings.xml +++ b/core/res/res/values-ky-rKG-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d ичинен %1$d колднм." + "Сенсорлор" diff --git a/core/res/res/values-ky-rKG/cm_strings.xml b/core/res/res/values-ky-rKG/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-ky-rKG/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml index b0a5963700cfa..398f936134f98 100644 --- a/core/res/res/values-ky-rKG/strings.xml +++ b/core/res/res/values-ky-rKG/strings.xml @@ -254,7 +254,7 @@ "Кредиттик карта номурлары жана сырсөздөр сыяктуу өздүк берилиштерди камтыйт." "абал тилкесин өчүрүү же өзгөртүү" "Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет." - "абал тилкеси" + "абал тилкесинин милдетин аткаруу" "Колдонмого абал тилкеси болуу мүмкүнчүлүгүн берет." "абал тилкесин жайып көрсөтүү/жыйнап коюу" "Колдонмого абал тилкесин жайып көрсөтүү же жыйнап коюу мүмкүнчүлүгүн берет." @@ -282,7 +282,7 @@ "Колдонмого WAP билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет." "иштеп жаткан колдонмолорду түшүрүп алуу" "Колдонмого учурдагы жана акыркы убакытта пайдаланылган колдонмолор тууралуу маалымат алууга уруксат берет. Бул колдонмого түзмөктө кандай колдонмолор колдонулаарын билип алууга жол бериши мүмкүн." - "Профилди жана түзмөк ээлерин башкаруу" + "профилди жана түзмөк ээлерин башкаруу" "Колдонмолорго профиль ээлерин жана түзмөк ээсин орнотуу мүмкүнчүлүгүн берет." "иштеп жаткан колдонмолорду иреттештирүү" "Колдонмо процесстерди фонго же алдыңкы планга жылдыруу уруксатын алат. Колдонмо муну сиздин ырастооңузсуз кыла алат." @@ -324,7 +324,7 @@ "Колдонмого планшетиңиздин чалуулар тизмегин, анын ичинде, чыгыш жана кириш чалууларына тиешелүү берилиштерди өзгөртүү уруксатын берет. Зыяндуу колдонмолор муну колдонуп чалуулар тизмегин өзгөртө же жок кыла алышат." "Колдонмого сыналгыңыздын чалуулар таржымалын, ошондой эле келүүчү жана чыгуучу чалуулар тууралуу дайындарды өзгөртүү мүмкүнчүлүгү берилет. Зыянкеч колдонмолор ушуну менен чалуулар таржымалыңызды жок кылып же өзгөртүп коюшу мүмкүн." "Колдонмого телефонуңуздун чалуулар тизмегин, анын ичинде, чыгыш жана кириш чалууларына тиешелүү берилиштерди өзгөртүү уруксатын берет. Зыяндуу колдонмолор муну колдонуп чалуулар тизмегин өзгөртө же жок кыла алышат." - "дене-бой сенсорлору (жүрөктүн кагышын өлчөгүчтөр сыяктуу)" + "дене-бой сенсорлоруна (жүрөктүн кагышын өлчөгүчтөр сыяктуу) уруксат" "Колдонмого жүрөгүңүздүн согушу сыяктуу дене-бой абалыңызды көзөмөлдөгөн сенсорлордогу дайындарды көрүп туруу мүмкүнчүлүгүн берет." "күнбарак иш-аракеттерин жана купуя маалыматтарды окуу" "Колдонмого планшетиңизде сакталган сиздин, досторуңуздун жана кесиптештериңиздин күнбарак окуяларын окуганга уруксат берет. Бул колдонмого күнбарак берилиштерин, алардын купуялуулугана жана маанилүүлүгөн карабастан бөлүшүү же сактоо уруксатын берет." @@ -336,15 +336,15 @@ "Колдонмого сиз телефонуңуздан өзгөртө ала турган, сиздин, досторуңуздун же кесиптештериңиздин күнбарак окуяларын кошуу, жок кылуу, өзгөртүү уруксатын берет. Бул, колдонмого күнбарак ээлеринен келген сыяктуу көрүнгөн билдирүүлөрдү жөнөтүү, же ээсине билгизбей окуяларды өзгөртүү уруксатын берет." "жайгашкан жерди аныктагычтын кошумча буйруктарын пайдалануу" "Колдонмого жайгашкан жерди табуучу кошумча жабдуучулардын буйруктарын колдонуу мүмкүнчүлүгүн берет. Ушуну менен колдонмо GPS\'тин ишине жана башка жайгашкан жерлерди аныктоо кызматтарына кийлигише алат." - "так жайгаштыруу (GPS жана түйүн негизинде)" + "так аныкталган жайгашкан жерге (GPS жана тармактын негизинде) уруксат" "Колдонмого Глобалдык Позициялоо Системасын (GPS), же базалык станциялар жана Wi-Fi сыяктуу түйүндүк булактардын жайгашуусунун пайдалануу аркылуу сиздин так жайгашууңузду аныктоого уруксат берет. Колдонмолор муну пайдалана алышы үчүн, жайгаштыруу кызматтары жандырылган жана түзмөгүңүзгө жеткиликтүү болушу керек. Колдонмолор муну сиздин жайгашкан жериңизди аныкташ үчүн пайдаланышы жана кошумча батарей кубаты сарпталышы мүмкүн." - "божомолдуу жайгаштыруу (түйүн негизинде)" + "болжолдуу жайгашкан жерге (тармактын негизинде) уруксат" "Колдонмого сиздин болжолдуу жайгашууңузду аныктоо уруксаты берет. Мындай жайгаштыруу базалык станциялар жана Wi-Fi сыяктуу түйүндүк булактардын жайгашуусу аркылуу аныкталат. Колдонмоңуз буларды пайдалана алышы үчүн, мындай жайгаштыруу кызматтары жандырылган жана түзмөгүңүзгө жеткиликтүү болушу керек. Колдонмолор муну сиздин жайгашкан жериңизди болжолдош үчүн пайдаланышы мүмкүн." "аудио жөндөөлөрүңүздү өзгөртүңүз" "Колдонмого үн деңгээли жана кайсы динамик аркылуу үн чыгарылышы керек сыяктуу түзмөктүн аудио тууралоолорун өзгөртүүгө уруксат берет." "аудио жаздыруу" "Колдонмого микрофон аркылуу аудио жаздыруу уруксатын берет. Бул уруксат колдонмого сиздин ырастооңузсуз, каалаган убакта аудио жаздыруу уруксатын берет." - "sim-карта менен байланышуу" + "SIM-картага буйруктарды жөнөтүү" "Колдонмого SIM-картага буйруктарды жөнөтүү мүмкүнчүлүгүн берет. Бул абдан кооптуу." "сүрөт жана видео тартуу" "Колдонмого камера аркылуу видео жана сүрөт тартуу уруксатын берет. Бул уруксат, камераны каалаган убакта, сиздин ырастооңузсуз колдонуу уруксатын берет." @@ -382,7 +382,7 @@ "Колдонмого телефонго белгилүү эсептердин тизмегин алуу уруксатын берет. Буларга сиз орноткон колдонмолор аркылуу түзүлгөн эсептер кириши мүмкүн." "түйүн туташууларын көрүү" "Колдонмого желелердин бардыгы жана байланыштар сыяктуу желе маалыматтарын көргөнгө уруксат берет." - "желеге толук жетки алуу" + "тармакка толук мүмкүнчүлүк алуу" "Колдонмого түйүн сокеттерин түзүү жана ылайыкташтырылган түйүн протоколдорун пайдалануу уруксаттарын берет. Серепчи жана башка колдонмолорго интернетке берилиштерди жөнөтүү жолдорун берет, ошондуктан, интернетке берилиштерди жөнөтүү үчүн, бул уруксатты алуу талап кылынбай." "тармак туташымдуулугун өзгөртүү" "Колдонмого тармактык туташуунун абалын өзгөртүү мүмкүнчүлүгүн берет." @@ -402,7 +402,8 @@ "Колдонмого жергиликтүү Bluetooth телефонун конфигурациялап, ыраактагы түзмөктөрдү таап, жупташуу мүмкүнчүлүгүн берет." "WiMAX түйүнүнө туташуу жана андан ажыроо" "Колдонмого WiMAX жандырылгандыгы жана туташкан WiMAX түйүндөрү тууралуу маалыматтарын көрүүгө уруксат берет." - "WiMAX абалын өзгөртүү" + + "Колдонмого планшетти WiMAX түйүндөрүнө туташтыруу жана ажыратуу уруксаттары берилет." "Колдонмого сыналгыны WiMAX тармактарына туташтырып, алардан ажыратуу мүмкүнчүлүгүн берет." "Колдонмого телефонду WiMAX түйүндөрүнө туташтыруу жана ажыратуу уруксаттары берилет." @@ -485,7 +486,7 @@ "Колдонмого сенсордук экрандын калибрлөө параметрлерин өзгөртүү мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбайт." "DRM тастыктамаларына кирүү" "Колдонмого DRM тастыктамаларын ишке киргизип, колдонуу мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбайт." - "Android Beam өткөрүү абалын алуу" + "Android Beam өткөрүү абалын кабыл алуу" "Бул колдонмого учурдагы Android Beam өткөрүүлөрү жөнүндө маалымат алуу мүмкүнчүлүгүн берет" "DRM тастыктамаларын алып салуу" "Колдонмого DRM тастыктамаларын алып салуу мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбайт." @@ -1098,11 +1099,11 @@ "Форматталууда…" "Сайылган жок" "Туура келген аракеттер табылбады." - "Медиа чыгарылышын багыттоо" + "медиа чыгарылышын багыттоо" "Колдонмого  медиа мазмунду башка тышкы түзмөктөргө багыттоо уруксатын берет." - "Орнотуу сеанстарын окуу" + "орнотуу сеанстарын окуу" "Колдонмого орнотуу сеанстарын окуу мүмкүнчүлүгүн берет. Ушуну менен, ал жигердүү топтом орнотууларынын чоо-жайын көрө алат." - "Топтомдорду орнотууга уруксат суроо" + "орнотуу топтомдорун суроо" "Колдонмо топтомдорду орнотууга уруксат сурай алат." "Чен өлчөмүн көзөмөлдөө үчүн эки жолу тийип коюңуз" "Виджетти кошуу мүмкүн болбоду." diff --git a/core/res/res/values-lb/cm_strings.xml b/core/res/res/values-lb/cm_strings.xml new file mode 100644 index 0000000000000..79c12064170c2 --- /dev/null +++ b/core/res/res/values-lb/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Schiermfoto + + Geschützten SMSen empfänken + + Erlaabt der App, erakommend geschützten SMS z\'empfänken. + + Lëscht vun de geschützten SMSen änneren + + Erlaabt der App, d\'Lëscht vun de geschützten SMS-Adressen z\'änneren. + + Sécherheet + + Berechtegungen déi mat der Sécherheet vum Apparat ze dinn hunn. + + Schwaarz Lëscht ausliesen + + Erlaabt der App, Informatiounen iwwer blockéiert Telefonsnummere fir erakommend Uriff oder Messagen ze liesen. + + Schwaarz Lëscht änneren + + Erlaabt der App, d\'blockéiert Telefonsnummere fir erakommend Uriff oder Messagen z\'änneren. + + Hannergrondbild vum Spärschierm setzen + + Erlaabt der App, d\'Hannergrondbild vum Spärschierm z\'änneren. + + Nei starten + + Aktuell + + + Nei starten + + Recuperatioun + + Bootloader + + Eroflueden + + Séieren Neistart + + Nei starten + + Däin Tablet gëtt nei gestart. + Däin Telefon gëtt nei gestart. + + Gëtt nei gestart\u2026 + + App zougemaach + + ADB iwwer Netzwierk aktivéiert + + ADB iwwer USB an Netzwierk aktivéiert + + Drécke fir Debugging ze desaktivéieren. + + ADB: %1$s + USB an Netzwierk + USB + Netzwierk + + App-Start offänken + + %s ass net installéiert + + Prioritéit + Keen + + WLAN-Zougrëffspunkt gouf opgrond vun Ännerunge am SIM-Abonnement desaktivéiert + + WLAN ausschalten + + Privatsphärschutz aktivéieren oder desaktivéieren + Erlaabt der App, z\'änneren ob eng aner App mam Privatsphärschutz leeft. Wann eng App mam Privatsphärschutz leeft, huet se keen Accès op perséinlech Date wéi Kontakter, Uruffprotokoller oder Messagen. + Privatsphärschutz aktiv + %1$s huet keen Accès op perséinlech Daten + Privatsphärschutz + %1$s wëll %2$s. + + Mäi Choix verhalen + + op d\'Kamera zougräifen + op de Standuert zougräifen + op d\'Notifikatiounen zougräifen + E VPN aktivéieren + Automatesch starten + Den Uruffhistorique läschen + Kontakter läschen + MMS-Messagë läschen + SMS-Messagë läschen + Virun aneren Appen ablenden + App-Benotzungsstatistiken ausliesen + de Rouzoustand desaktivéieren + en Telefonsuruff maachen + de Kalenner änneren + d\'Urufflëscht änneren + d\'Tëschenoflag änneren + d\'Kontakter änneren + d\'Systemastellungen änneren + Mikro aus-/uschalten + Toun ofspillen + eng Notifikatioun erstellen + Projektioun vu Medieninhalter + de Kalenner liesen + d\'Urufflëscht liesen + d\'Tëschenoflag liesen + d\'Kontakter liesen + MMS-Messagë liesen + SMS-Messagë liesen + en SMS-Message empfänken + Toun ophuelen + en MMS-Message schécken + eng SMS-Message schécken + automatesch starten + Kuerzzäit-Notifikatiounen uweisen + Bluetooth un-/ausschalten + Mobil Daten un-/ausschalten + NFC un-/ausschalten + WLAN un-/ausschalten + d\'Lautstäerkt vum Wecker änneren + den Tounfokus änneren + d\'Bluetooth-Lautstäerkt änneren + d\'Gesamtlautstäerkt änneren + d\'Medieknäppercher benotzen + d\'Medielautstäerkt änneren + d\'Notifikatiounslautstäerkt änneren + d\'Schelllautstäerkt änneren + de Vibratiounsalarm steieren + d\'Sproochlautstäerkt änneren + eng MMS schreiwen + eng SMS schreiwen + Fangerofdrock benotzen + eng Sproochnoriicht bäisetzen + op Telefon-Status zougräifen + WLAN-Netzwierker scannen + Hannergrondbild änneren + Ënnerstëtzungsstruktur benotzen + Schiermfoto maachen + Kierpersensore benotzen + Cell-Broadcasts liesen + Standuert simuléieren + externe Späicher ausliesen + op externe Späicher schreiwen + Schierm uschalten + Konte vum Apparat opruffen + WLAN-Status änneren + Root-Accès kréien + + Fir dëse Schierm lasszeléisen, dréck den Zréck-Knäppchen an hal e gedréckt. + + Kee connectéierten Apparat + %1$s connectéierten Apparat + %1$s connectéiert Apparater + + + + Start vun der Aktivitéit blockéiert + %1$s ass vum Starten ofgehale ginn. Klick, fir d\'App ze authentifizéieren an nei ze starten. + + Akku ganz opgelueden + Stecker aus dem Apparat zéien, fir d\'Liewensdauer vum Akku ze verlängeren. + + Akkustatistiken zrécksetzen + + Erlaabt enger App, den Detail vun der Akkubenotzung zréckzesetzen. + + D\'SIM-Kaarte goufe gewiesselt + Dréck, fir d\'Standardastellunge fir d\'SIM-Kaart festzeleeën + diff --git a/core/res/res/values-lb/strings.xml b/core/res/res/values-lb/strings.xml new file mode 100644 index 0000000000000..a6416ed964677 --- /dev/null +++ b/core/res/res/values-lb/strings.xml @@ -0,0 +1,3007 @@ + + + + + + B + + kB + + MB + + GB + + TB + + PB + + + %1$d Deeg + + %1$d Dag %2$d St. + + %1$d Dag %2$d St. + + %1$d St. + + %1$d St. %2$d Min. + + %1$d St. %2$d Min. + + %1$d Min. + + %1$d Min. + + %1$d Min. %2$d Sek. + + %1$d Min. %2$d Sek. + + %1$d Sek. + + %1$d Sek. + + <Ouni Titel> + + (Keng Telefonsnummer) + + Onbekannt + + Sproochopnam + + MSISDN1 + + + + Connectiounsproblem oder ongëltegen MMI-Code. + + De Virgank ass just fir deng zougeloosse Ruffnummer méiglech. + + Service gouf aktivéiert. + + Service gouf aktivéiert fir: + + Service gouf desaktivéiert. + + Registréierung war erfollegräich. + + Ausläsche war erfollegräich. + + Inkorrekt Passwuert. + + MMI komplett. + + Déi al PIN, déi s du aginn hues, ass net korrekt. + + De PUK, deen s du aginn hues, ass net korrekt. + + D\'PINen, déi s du aginn hues, stëmmen net iwwereneen. + + Gëff e PIN an, deen tëscht 4 an 8 Zifferen huet. + + Gëff e PUK an, deen 8 oder méi Zifferen huet. + + Deng SIM-Kaart ass PUK-gespaart. Gëff de PUK-Code an, fir en z\'entspären. + Gëff de PUK2 vun der SIM-Kaart an, fir se z\'entspären. + + Feeler. Aktivéier d\'SIM-/RUIM-Spär. + + + Du hues nach %d Versuch iwwreg ier deng SIM gespaart ass. + Du hues nach %d Versich iwwreg ier deng SIM gespaart ass. + + + IMEI + + MEID + + Erakommend Uruffer-ID + + Erausgoend Uruffer-ID + + ID vun der verbonnener Leitung + + Aschränkunge fir d\'ID vun der verbonnener Leitung + + Gespréich-Weiderleedung + + Gespréich pauséiert + + Uruffspär + + Passwuert-Ännerung + + PIN-Ännerung + Ruffnummer disponibel + Rufnummer begrenzt + Dräierkonferenz + Refus vun onerwënschten Uriff + Iwwermëttlung fir Ruffnummeren + Net stéieren + + D\'Uruffer-ID ass standardméisseg ageschränkt. Nächsten Uruff: Ageschränkt + + D\'Uruffer-ID ass standardméisseg ageschränkt. Nächsten Uruff: Net ageschränkt + + D\'Uruffer-ID ass standardméisseg net ageschränkt. Nächsten Uruff: Ageschränkt + + D\'Uruffer-ID ass standardméisseg net ageschränkt. Nächsten Uruff: Net ageschränkt + + Service net ageriicht. + + D\'Astellung fir d\'Uruffer-ID kann net geännert ginn. + + Begrenzten Zougrëff geännert + + Dateservice ass gespaart. + + Noutruff ass gespaart. + + Sproochservice ass gespaart. + + All Stëmmservicer si gespaart. + + SMS-Service ass gespaart. + + Sprooch-/Dateservicer si gespaart. + + Sprooch-/SMS-Servicer si gespaart. + + Alle Sprooch-/Date-/SMS-Servicer si gespaart. + + Peer huet TTY-Modus \"Vollstänneg\" ugefrot + Peer huet TTY-Modus \"HCO\" ugefrot + Peer huet TTY-Modus \"VCO\" ugefrot + Peer huet TTY-Modus \"Aus\" ugefrot + + + + Stëmm + + Daten + + FAX + + SMS + + Async + + Sync + + Pak + + PAD + + + + Roaming-Anzeig un + Roaming-Anzeig aus + Roaming-Anzeig blénkend + Aus der Noperschaft eraus + Aus dem Gebai eraus + Roaming - Preferéierte System + Roaming - Disponibele System + Roaming - Allianzpartner + Roaming - Premiumpartner + Roaming - Voll Déngschtleeschtungsfunktionalitéit + Roaming - Partiell Déngschtleeschtungsfunktionalitéit + Roaming-Banner Un + Roaming-Banner Aus + E Service gëtt gesicht + + + + + + + + + + + + + + + + {0}: Net weidergeleet + + {0}: {1} + + {0}: {1} no {2} Sekonnen + + {0}: Net weidergeleet + + {0}: Net weidergeleet + + + + Funktiounscode ofgeschloss. + + Connectiounsproblem oder ongëltege Funktiounscode. + + + + OK + + Et gouf en Netzwierkfeeler. + + URL gouf net fonnt. + + Den Authentifizéierungsschema vun der Säit ass net ënnerstëtzt. + + Konnt net authentifizéieren. + + D\'Authentifizéierung iwwer de Proxy Server war net erfollegräich. + + Konnt keng Connectioun mam Server hierstellen. + + Konnt net mam Server kommunikéieren. Probéier méi spéit nees. + + Zäitiwwerschreidung bei der Connectioun mam Server. + + D\'Säit huet zevill Serverweiderleedungen. + + De Protokoll ass net ënnerstëtzt. + + Konnt keng sécher Connectioun hierstellen. + + Konnt d\'Säit net opmaache well d\'URL net gëlteg ass. + + Konnt net op de Fichier zougräifen. + + Konnt den ugefrote Fichier net fannen. + + Et ginn ze vill Ufroe beaarbecht. Probéier méi spéit nees. + + + + Feeler bei der Umeldung fir %1$s + + + + Sync + + Sync + + Ze vill %s geläscht. + + Den Tabletsspäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn. + + Den Auerespäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn. + + Den Tëleespäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn. + + Den Telefonsspäicher ass voll. Läsch Dateien, fir Späicherplaz fräizeginn. + + + + D\'Netzwierk kéint iwwerwaacht sinn + + Vun engem onbekannten Drëtten + + Vum Administrateur vun dengem Aarbechtsprofil + + Vu(n) %s + + + + Aarbechtsprofil geläscht + + Aarbechtsprofil geläscht well d\'Admin-App feelt. + + D\'Admin-App fir den Aarbechtsprofil feelt oder ass futti. Dowéinst gouf däin Aarbechtsprofil an all d\'Daten déi dozougehéiere geläscht. Kontaktéier däin Administrateur fir Hëllef ze kréien. + + + + + Däin Apparat gëtt geläscht + + D\'Admin-App kann net benotzt ginn, well se futti ass oder Komponente feelen. D\'Daten op dengem Apparat ginn elo geläscht. Kontaktéier däin Administrateur fir Hëllef ze kréien. + + Ech + + + + Tabletoptiounen + + Tëleesoptiounen + + Telefonsoptiounen + + Stëlle Modus + + Funk umaachen + + Funk ausmaachen + + Schiermspär + + Ausmaachen + + Schelltoun aus + + Schellmodus \"Vibratioun\" + + Schelltoun un + + + + Gëtt ausgemaach\u2026 + + Däin Tablet gëtt ausgemaach. + + Deng Tëlee schallt sech aus. + + Deng Auer schalt sech aus. + + Däin Telefon gëtt ausgemaach. + + Wëlls du den Apparat ausmaachen? + + An de séchere Modus wiesselen + + Wëlls du an de séchere Modus wiesselen? Doduerch ginn all d\'Appe vun Drëttubidder desaktivéiert, déi s du installéiert hues. Se ginn no engem weideren Neistart awer nees hiergestallt. + + Rezent + + Keng rezent Appen. + + Tabletoptiounen + + Tëleesoptiounen + + Telefonsoptiounen + + Schiermspär + + Ausmaachen + + Feelerbericht + + Feelerbericht maachen + + Bei dësem Feelerbericht ginn Daten iwwer den aktuelle Status vum Apparat erfaasst an als E-Mail verschéckt. Vum Start vum Bericht bis bei d\'Verschécke kann et ee Moment daueren; ee Moment Gedold. + + + Stëlle Modus + + Den Toun ass AUS + + Den Toun ass UN + + Fligermodus + + Fligermodus ass UN + + Fligermodus ass AUS + + Astellungen + + + + Elo spären + + 999+ + + Séchere Modus + + Android-System + + + Aarbecht + + + + + + Kalenner + + + SMS + + + Späicher + + + Mikro + + Toun ophuelen + + Fotoapparat + + + Telefon + + + + + Fënsterinhalter ofruffen + + D\'Inhalter vun der Fënster mat där s du interagéiers ginn ofgeruff. + + \"Drécken an Entdecken\" aktivéieren + + Beréiert Elementer gi virgelies an de Schierm ka mat Gesten entdeckt ginn. + + Verbessert Web-Benotzbarkeet uschalten + + Skripter kënnen installéiert ginn, fir den Zougrëff op App-Inhalter ze vereinfachen. + + Text observéieren deen s du agëss + + Huet perséinlech Date wéi Kreditkaartennummeren a Passwierder als Inhalt. + + + Statusläischt desaktivéieren oder änneren + + Erlaabt der App, d\'Statusläischt ze desaktivéieren oder System-Symbolbiller dobäizesetzen oder ze läschen. + + + Erlaabt der App, d\'Statusläischt ze sinn. + + Statusläischt op-/zouklappen + + Erlaabt der App, d\'Statusläischt aus- oder zesummenzeklappen. + + Ofkierzungen installéieren + + Erlaabt der App, Ofkierzungen ouni Benotzeragrëff op de Startschierm ze setzen. + + Ofkierzungen desinstalléieren + + Erlaabt der App, Ofkierzungen ouni Benotzeragrëff vum Startschierm ze läschen. + + Erausgoend Uriff ëmleeden + + Erlaabt der App, ze gesi wéi eng Nummer grad gewielt gëtt an erméiglecht den Uruff op eng aner Nummer ëmzeleeden oder den Uruff ofzebriechen. + + SMSen empfänken + + Erlaabt der App, SMSen z\'empfänken an ze veraarbechten. Dat bedeit datt d\'App Messagen déi s du geschéckt kriss iwwerwaachen oder läsche kann ouni datt s du se gesäis. + + MMSen empfänken + + Erlaabt der App, MMSen z\'empfänken an ze veraarbechten. Dat bedeit datt d\'App Messagen déi s du geschéckt kriss iwwerwaachen oder läsche kann ouni datt s du se gesäis. + + Messagë vun Zelliwwerdrounge liesen + + + Abonnéiert Feeds liesen + + Erlaabt der App, Detailer iwwer déi momentan synchroniséiert Feeds ofzeruffen. + + + Erlaabt der App, SMSen ze schécken. Doduerch kéinten onerwaart Käschten entstoen. Béiswëlleg Appe kéinten dech Sue kaschten andeem se Messagen ouni deng Bestätegung verschécken. + + SMSen oder MMSe liesen + + Erlaabt der App, SMSen ze liesen déi um Tablet oder op der SIM-Kaart gespäichert sinn. Doduerch kann d\'App all d\'SMSe liesen, onofhängeg vum Inhalt an egal wéi vertraulech se sinn. + + Erlaabt der App SMSen ze liesen déi op der Tëlee oder op der SIM-Kaart gespäichert sinn. Doduerch kann d\'App all d\'SMSe liesen, onofhängeg vum Inhalt an egal wéi confidentiell se sinn. + + Erlaabt der App, SMSen ze liesen déi um Telefon oder op der SIM-Kaart gespäichert sinn. Doduerch kann d\'App all d\'SMSe liesen, onofhängeg vum Inhalt an egal wéi vertraulech se sinn. + + Textmessagen (WAP) empfänken + + Erlaabt der App, WAP-Messagen z\'empfänken an ze beaarbechten. Dës Berechtegung huet d\'Fäegkeet, Messagen déi s du geschéckt kriss z\'iwwerwaachen oder ze läschen, ouni datt s du se ze gesi kriss. + + Lafend Appen ausliesen + + Erlaabt der App, Informatiounen iwwer Aufgaben ofzeruffen déi grad lafen oder viru kuerzem gelaf sinn. Dat kéint der App erméiglechen, Informatiounen z\'entdecken iwwer d\'Appen déi um Apparat benotzt ginn. + + + + Lafend Appen ëmzortéieren + + Erlaabt der App, Aufgabe vum Virgrond an den Hannergrond ze réckelen. D\'App kéint dat ouni däin Awierke maachen. + + Automodus aktivéieren + + Der App erlaben den Automodus z\'aktivéieren. + + Aner Appen zoumaachen + + Erlaabt der App, Hannergrondprozesser vun aneren Appen zouzemaachen. Doduerch kéinten aner Appen ophale mat funktionéieren. + + Iwwer aner Appen uweisen + + Erlaabt der App, fir iwwer aner Applikatiounen oder Deeler vum Benotzerinterface ze zeechnen. Dat kéint mat denge Benotzungsgewunneschten interferéieren, oder ännere wat s du an aneren Appe mengs ze gesinn. + + App permanent ausféieren + + Erlaabt der App, Deeler vu sech selwer am Späicher ze persistéieren. Dat kann de Späicher dee fir aner Appen disponibel ass limitéieren an doduerch den Tablet méi lues maachen. + + Erlaabt der App, Deeler vu sech selwer am Späicher ze persistéieren. Dat kann de Späicher dee fir aner Appen disponibel ass limitéieren an doduerch d\'Tëlee méi lues maachen. + Erlaabt der App, Deeler vu sech selwer am Späicher ze persistéieren. Dat kann de Späicher dee fir aner Appen disponibel ass limitéieren an doduerch den Telefon méi lues maachen. + + Späicherplaz vun Appe moossen + + Erlaabt der App, säi Code, seng Daten a seng Tëschespäicher-Gréissten auszeliesen + + Systemastellungen änneren + + Erlaabt der App, d\'Systemastellungsdaten z\'änneren. Béisaarteg Appe kéinten doduerch d\'Konfiguratioun vun dengem System beschiedegen. + + Beim Start ausféieren + + Erlaabt der App, sech selwer ze starte soubal de System fäerdeg gelueden ass. Doduerch kéint den Tablet méi laang brauche fir ze starten an d\'App kéint de gesamten Tablet méi lues maache wa se stänneg leeft. + + Erlaabt der App sech selwer ze starte soubal de System fäerdeg gelueden ass. Doduerch kéint d\'Tëlee méi laang brauche fir ze starten an d\'App kéint déi gesamt Tëlee méi lues maache wa se stänneg leeft. + + Erlaabt der App, sech selwer ze starte soubal de System fäerdeg gelueden ass. Doduerch kéint den Telefon méi laang brauche fir ze starten an d\'App kéint de gesamten Telefon méi lues maache wa se stänneg leeft. + + Dauerhafte Broadcast schécken + + Erlaabt der App, dauerhaft Broadcasten ze schécken, déi no der Iwwerdroung bestoe bleiwen. Exzessiv Benotzung kéint den Tablet méi lues oder instabil maachen, andeem ze vill Späicher benotzt gëtt. + + Erlaabt der App, dauerhaft Broadcasten ze schécken, déi no der Iwwerdroung bestoe bleiwen. Exzessiv Benotzung kéint d\'Tëlee méi lues oder instabil maachen, andeem ze vill Späicher benotzt gëtt. + + Erlaabt der App, dauerhaft Broadcasten ze schécken, déi no der Iwwerdroung bestoe bleiwen. Exzessiv Benotzung kéint den Telefon méi lues oder instabil maachen, andeem ze vill Späicher benotzt gëtt. + + Kontakter liesen + + Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Tablet gespäichert sinn ze liesen, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten z\'änneren, a béisaarteg Appe kéinte Kontaktdaten ouni däi Wëssen deelen. + + Erlaabt der App, Daten iwwer d\'Kontakter déi op denger Tëlee gespäichert sinn ze liesen, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten z\'änneren, a béisaarteg Appe kéinte Kontaktdaten ouni däi Wëssen deelen. + + Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Telefon gespäichert sinn ze liesen, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten z\'änneren, a béisaarteg Appe kéinte Kontaktdaten ouni däi Wëssen deelen. + + Kontakter änneren + + Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Tablet gespäichert sinn z\'änneren, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten ze läschen. + + Erlaabt der App, Daten iwwer d\'Kontakter déi op denger Tëlee gespäichert sinn z\'änneren, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten ze läschen. + + Erlaabt der App, Daten iwwer d\'Kontakter déi op dengem Telefon gespäichert sinn z\'änneren, inklusiv der Frequenz mat där s de spezifesch Kontakter ugeruff hues, hinnen E-Maile geschéckt hues, oder anerwäerts mat hinne kommunikéiert hues. Dës Berechtegung erméiglecht et Appen, Kontaktdaten ze läschen. + + Urufflëscht liesen + + Erlaabt der App, d\'Urufflëscht vum Tablet auszeliesen, inklusiv Daten iwwer erakommend an erausgoend Uriff. Dës Berechtegung erlaabt et Appen, d\'Daten aus denger Urufflëscht ze späicheren, a béisaarteg Appe kéinten dës Daten ouni däi Wëssen deelen. + + Erlaabt der App, d\'Urufflëscht vun der Tëlee auszeliesen, inklusiv Daten iwwer erakommend an erausgoend Uriff. Dës Berechtegung erlaabt et Appen, d\'Daten aus denger Urufflëscht ze späicheren, a béisaarteg Appe kéinten dës Daten ouni däi Wëssen deelen. + + Erlaabt der App, d\'Urufflëscht vum Telefon auszeliesen, inklusiv Daten iwwer erakommend an erausgoend Uriff. Dës Berechtegung erlaabt et Appen, d\'Daten aus denger Urufflëscht ze späicheren, a béisaarteg Appe kéinten dës Daten ouni däi Wëssen deelen. + + Urufflëscht änneren + + Erlaabt der App, d\'Urufflëscht vum Tablet z\'änneren, inklusiv Daten iwwer erakommend an erausgoend Uriff. Béisaarteg Appe kéinten dës Berechtegung benotze fir d\'Daten ouni däi Wëssen ze läschen oder z\'änneren. + + Erlaabt der App, d\'Urufflëscht vun der Tëlee z\'änneren, inklusiv Daten iwwer erakommend an erausgoend Uriff. Béisaarteg Appe kéinten dës Berechtegung benotze fir d\'Daten ouni däi Wëssen ze läschen oder z\'änneren. + + Erlaabt der App, d\'Urufflëscht vum Telefon z\'änneren, inklusiv Daten iwwer erakommend an erausgoend Uriff. Béisaarteg Appe kéinten dës Berechtegung benotze fir d\'Daten ouni däi Wëssen ze läschen oder z\'änneren. + + + Erlaabt der App, op d\'Date vu Sensoren zouzegräifen, déi deng kierperlech Verfaassung iwwerwaachen, z. B. däi Puls. + + Kalenner-Rendezvousen a vertraulech Informatioune liesen + + Erlaabt der App, all d\'Kalenner-Evenementer déi um Tablet gespäichert sinn ze liesen, inklusiv deene vu Frënn a Mataarbechter. Doduerch kéint d\'App deng Kalennerdate späicheren oder deelen, onofhängeg vun der agestallter Konfidentialitéit. + + Erlaabt der App, all d\'Kalenner-Evenementer déi op der Tëlee gespäichert sinn ze liesen, inklusiv deene vu Frënn a Mataarbechter. Doduerch kéint d\'App deng Kalennerdate späicheren oder deelen, onofhängeg vun der agestallter Konfidentialitéit. + + Erlaabt der App, all d\'Kalenner-Evenementer déi um Telefon gespäichert sinn ze liesen, inklusiv deene vu Frënn a Mataarbechter. Doduerch kéint d\'App deng Kalennerdate späicheren oder deelen, onofhängeg vun der agestallter Konfidentialitéit. + + Kalenner-Rendezvousen dobäisetzen oder änneren an E-Mailen u Gäscht ouni d\'Wësse vun de Benotzer schécken + + Erlaabt der App, Rendezvousen, déi s du op dengem Tablet ännere kanns, dobäizesetzen, ze läschen an z\'änneren, inklusiv deene vu Frënn oder Kollegen. Doduerch kann d\'App Noriichte verschécken, déi sou ausgesi wéi wa se vum Besëtzer vum Kalenner géife stamen, oder Rendezvousen änneren ouni datt de Besëtzer et matkritt. + + Erlaabt der App, Rendezvousen, déi s du op denger Tëlee ännere kanns, dobäizesetzen, ze läschen an z\'änneren, inklusiv deene vu Frënn oder Kollegen. Doduerch kann d\'App Noriichte verschécken, déi sou ausgesi wéi wa se vum Besëtzer vum Kalenner géife stamen, oder Rendezvousen änneren ouni datt de Besëtzer et matkritt. + + Erlaabt der App, Rendezvousen, déi s du op dengem Telefon ännere kanns, dobäizesetzen, ze läschen an z\'änneren, inklusiv deene vu Frënn oder Kollegen. Doduerch kann d\'App Noriichte verschécken, déi sou ausgesi wéi wa se vum Besëtzer vum Kalenner géife stamen, oder Rendezvousen änneren ouni datt de Besëtzer et matkritt. + + Op zousätzlech Serviceproviderbefeeler fir de Standuert zougräifen + + + + Erlaabt der App, iwwer de Globale Positionéierungs-System (GPS) oder iwwer Netzwierkquelle wéi Funkmasten oder WLAN däi genaue Standuert ze bestëmmen. Dës Standuert-Servicer mussen ugeschalt a fir däin Apparat disponibel si fir datt d\'App se ka benotzen. Appe kéinten dat benotze fir ze bestëmme wou s de dech ophäls, an doduerch zousätzlech Akkuleeschtung beusprochen. + + + Erlaabt der App, däin ongeféiere Standuert ze bestëmmen. De Standuert gëtt unhand vun Netzwierkstanduertquellen, wéi Funkmasten oder WLAN ofgeleent. Dës Standuert-Servicer mussen ugeschalt a fir däin Apparat disponibel si fir datt d\'App se ka benotzen. Appe kéinten dat benotze fir ze bestëmme wou ongeféier s de dech ophäls. + + Tounastellungen änneren + + Erlaabt der App, déi global Audioastellungen ze steieren, z. B. d\'Lautstäerkt oder wéi ee Lautsprecher benotzt soll ginn. + + Toun ophuelen + + Erlaabt der App, Toun mam Mikro opzehuelen. Dës Berechtegung erlaabt der App zu all Moment Toun ouni deng Bestätegung opzehuelen. + + + Erlaabt der App, Befeeler un d\'SIM ze schécken. Dat ass immens geféierlech. + + Biller a Videoen ophuelen + + Erlaabt der App, Biller a Videoe mat der Kamera opzehuelen. Dës Berechtegung erlaabt der App, d\'Kamera zu all Moment ouni däin Awierken ze benotzen. + + Vibratioun steieren + + Erlaabt der App, d\'Vibratioun ze steieren. + + Täscheluucht steieren + + Erlaabt der App, d\'Täscheluucht ze steieren. + + Telefonsnummeren direkt uruffen + + Erlaabt der App, Telefonsnummeren ouni deng Awierkung unzeruffen. Doduerch kéinten onerwaart Käschten oder Uriff entstoen. D\'App kann heiduerch awer keng Noutfallnummeren uruffen. Béiswëlleg Appe kéinte Käschte verursaachen andeem se Nummeren ouni deng Bestätegung uruffen. + + + + Status an Identitéit vum Telefon liesen + + Erlaabt der App, op d\'Telefonsfunktioune vum Apparat zouzegräifen. Mat dëser Berechtegung kann d\'App d\'Telefonsnummer an d\'Identifikatiounsnummer vum Apparat, a wann en Uruff aktiv ass och d\'Telefonsnummer vum Gespréichspartner, ausliesen. + + Tablet vum Schlofen ofhalen + + Rouzoustand vun der Tëlee ze desaktivéieren + + Telefon vum Schlofen ofhalen + + Erlaabt der App, den Tablet dorun ze hënneren an de Rouzoustand ze wiesselen. + + Erlaabt der App d\'Tëlee dorun ze hënneren an de Rouzoustand ze wiesselen. + + Erlaabt der App, den Telefon dorun ze hënneren an de Rouzoustand ze wiesselen. + + Infrarout iwwerdroen + + Erlaabt der App, den Infrarout-Sender vum Tablet ze benotzen. + + Erlaabt der App, den Infrarout-Sender vun der Tëlee ze benotzen. + + Erlaabt der App, den Infrarout-Sender vum Telefon ze benotzen. + + Hannergrondbild setzen + + Erlaabt der App, d\'Hannergrondbild vum System ze setzen. + + Gréisst vum Hannergrondbild ajustéieren + + Erlaabt der App, d\'Gréisstenhiwäiser fir d\'Systemhannergrondbiller ze definéieren. + + Zäitzon setzen + + Erlaabt der App, d\'Zäitzon vum Tablet z\'änneren. + + Erlaabt der App, d\'Zäitzon vun der Tëlee z\'änneren. + + Erlaabt der App, d\'Zäitzon vum Telefon z\'änneren. + + Konten op dësem Apparat sichen + + Erlaabt der App, eng Lëscht vun de Konten auszeliesen déi dem Tablet bekannt sinn. Dat kéint Konten aschléissen, déi vun Appen ugeluecht goufen, déi s du installéiert hues. + + Erlaabt der App, eng Lëscht vun de Konten auszeliesen déi der Tëlee bekannt sinn. Dat kéint Konten aschléissen, déi vun Appen ugeluecht goufen, déi s du installéiert hues. + + Erlaabt der App, eng Lëscht vun de Konten auszeliesen déi dem Telefon bekannt sinn. Dat kéint Konten aschléissen, déi vun Appen ugeluecht goufen, déi s du installéiert hues. + + Netzwierkconnectiounen ukucken + + Erlaabt der App, Informatiounen iwwer Netzwierkconnectiounen auszeliesen, wéi z. B. wéi eng Netzwierker existéieren a wéi eng verbonne sinn. + + + Erlaabt der App, Netzwierk-Sockets z\'erstellen an eegen Netzwierkprotokoller ze benotzen. De Browser an aner Appe bidde Méiglechkeeten, Daten iwwer den Internet ze verschécken. Dohier ass dës Berechtegung net néideg fir Daten iwwer den Internet ze schécken. + + Netzwierk-Connectivitéit änneren + + Erlaabt der App, de Status vun der Netzwierkconnectivitéit z\'änneren. + + Gethethert Connectivitéit änneren + + Erlaabt der App, de Status vun der getetherter Netzwierkconnectivitéit z\'änneren. + + WLAN-Connectiounen uweisen + + Erlaabt der App, Informatiounen iwwer d\'WLAN-Netzwierker auszeliesen. Beispillsweis ob WLAN un ass a wéi eng Nimm déi connectéiert WLAN-Apparater hunn. + + WLAN-Connectiounen hierstellen an trennen + + Erlaabt der App, Connectioune mat WLAN-Zougankspunkten hierzestellen an ze trennen a fir Ännerungen un der Konfiguratioun vun de WLAN-Netzwierker virzehuelen. + + WLAN-Multicast-Empfang erlaben + + Erlaabt der App, Päck z\'empfänken, déi iwwer Multicast-Adressen u sämtlech Apparater an engem WLAN verschéckt ginn, net just un däin Tablet. Dat kascht méi Leeschtung wéi den Net-Multicast-Modus. + + Erlaabt der App, Päck z\'empfänken, déi iwwer Multicast-Adressen u sämtlech Apparater an engem WLAN verschéckt ginn, net just un deng Tëlee. Dat kascht méi Leeschtung wéi den Net-Multicast-Modus. + Erlaabt der App, Päck z\'empfänken, déi iwwer Multicast-Adressen u sämtlech Apparater an engem WLAN verschéckt ginn, net just un däin Telefon. Dat kascht méi Leeschtung wéi den Net-Multicast-Modus. + + Op d\'Bluetooth-Astellungen zougräifen + + Erlaabt der App, Bluetooth um Tablet ze konfiguréieren, an anerer Apparater z\'entdecken a Koppelunge mat hinnen hierzestellen. + + Erlaabt der App, Bluetooth opo der Tëlee ze konfiguréieren, an anerer Apparater z\'entdecken a Koppelunge mat hinnen hierzestellen. + + Erlaabt der App, Bluetooth um Telefon ze konfiguréieren, an anerer Apparater z\'entdecken a Koppelunge mat hinnen hierzestellen. + WiMAX-Connectiounen hierstellen an trennen + Erlaabt der App, festzestellen ob WiMAX aktivéiert ass an Informatiounen iwwer all WiMAX-Netzwierker déi connectéiert sinn. + Erlaabt der App, den Tablet mat WiMAX-Netzwierker ze connectéieren an deconnectéieren. + Erlaabt der App, eng Connectioun tëscht der Tëlee a WiMAX-Netzwierker z\'erstellen an ze trennen. + Erlaabt der App, den Telefon mat WiMAX-Netzwierker ze connectéieren an deconnectéieren. + + Mat Bluetooth-Apparater koppelen + + Erlaabt der App, d\'Bluetooth-Konfiguratioun um Tablet ze liesen, a Connectioune mat gekoppelten Apparater hierzestellen. + + Erlaabt der App, d\'Bluetooth-Konfiguratioun op der Tëlee ze liesen, a Connectioune mat gekoppelten Apparater hierzestellen. + + Erlaabt der App, d\'Bluetooth-Konfiguratioun um Telefon ze liesen, a Connectioune mat gekoppelten Apparater hierzestellen. + + No-Feld-Communicatioun (NFC) kontrolléieren + + Erlaabt der App, iwwer No-Feld-Communicatioun (NFC) Badgen, Kaarten a Liesapparater ze kontrolléieren. + + Schiermspär desaktivéieren + + Erlaabt der App, d\'Tastespär an déi liéiert Passwuertsécherheet ze desaktivéieren. Den Telefon desaktivéiert beispillsweis d\'Tastespär wann en Uruff erakënnt, a reaktivéiert se wann den Uruff ofgeschloss ass. + + + + + + + + + + + + + + + + + + + + + + + + + Synchroniséierungsastellunge liesen + + Erlaabt der App, d\'Synchroniséierungsastellunge fir e Kont ze liesen. Doduerch ka beispillsweis festgestallt ginn ob d\'Kontakter mat engem Kont synchroniséiert sinn. + + Synchronisatioun un- an ausschalten + + Erlaabt der App, d\'Synchroniséierungsastellunge fir e Kont z\'änneren. Doduerch ka beispillsweis d\'Synchroniséierung vun de Kontakter mat engem Kont aktivéiert ginn. + + Synchronisatiounsstatistike liesen + + Erlaabt der App, d\'Synchroniséierungs-Statistike fir ee Kont ze liesen, inklusiv dem Verlaf vun de Synchronisatiountsevenementer a wéi vill Date synchroniséiert ginn. + + Inhalter vun dengem USB-Späicher liesen + + Inhalter vun denger SD-Kaart liesen + + Erlaabt der App, d\'Inhalter vum USB-Späicher ze liesen. + + Erlaabt der App, d\'Inhalter vun der SD-Kaart ze liesen. + + Inhalter vum USB-Späicher änneren oder läschen + + Inhalter vun der SD-Kaart änneren oder läschen + + Erlaabt der App, op den USB-Späicher ze schreiwen. + + Erlaabt der App, op d\'SD-Kaart ze schreiwen. + + SIP-Uriff maachen/empfänken + + Erlaabt der App, SIP-Uriff ze maachen an entgéintzehuelen. + + Nei SIM-Telekommunikatiounsverbindunge registréieren + + Erlaabt der App, nei SIM-Telekommunikatiounsverbindungen ze registréieren. + + Nei Telekommunikatiounsverbindunge registréieren + + Erlaabt der App, nei SIM-Telekommunikatiounsverbindungen ze registréieren. + + Telekommunikatiounsverbindunge verwalten + + Erlaabt der App, Telekommunikatiounsverbindungen ze verwalten. + + Mam Uruffschierm interagéieren + + Erlaabt der App, ze kontrolléiere wien a wéi de Benotzer den Uruffschierm gesäit. + + Mat Telefonsservicer interagéieren + + Erlaabt der App, mat Telefonsservicer z\'interagéieren, fir Uriff ze maachen/z\'empfänken. + + Uruffoptioune fir de Benotzer ubidden + + Erlaabt der App, Uruffoptioune fir de Benotzer unzebidden. + + Historesch Netzwierkdate liesen + + Erlaabt der App, historesch Netzwierkbenotzungsdate fir spezifesch Netzwierker an Appen ze liesen. + + Netzwierkrichtlinne verwalten + + Erlaabt der App, Netzwierkrichtlinnen ze geréieren an App-spezifesch Regelen ze definéieren. + + Statistike vun der Netzwierkbenotzung änneren + + Erlaabt der App, z\'ännere wéi d\'Netzwierkbenotzung vun aneren Appe gemooss gëtt. Net fir normal Appe geduecht. + + Op Notifikatiounen zougräifen + + Erlaabt der App, Notifikatiounen z\'empfänken, z\'analyséieren an ze läschen, inklusiv deenen déi vun aneren Appe geschriwwe goufen. + + Un en Notifikatiouns-Lauschter-Service ubannen + + Erlaabt der App, sech um ieweschten Niveau vun engem Notifikatiouns-Lauschter-Service unzebannen. Sollt ni fir normal Appen néideg sinn. + + Un e Konditiounsubidder-Service ubannen + + Erlaabt der App, sech um ieweschten Niveau vun engem Konditiounsubidder-Service unzebannen. Sollt ni fir normal Appen néideg sinn. + + Un en Dramservice ubannen + + Erlaabt der App, sech op ieweschtem Niveau un d\'Schnëttstell vun engem Dramservice unzebannen. Sollt ni fir normal Appen néideg sinn. + + Konfiguratiounsapp vum Provider opruffen + + Erlaabt dem Besëtzer, d\'Konfiguratiounsapp vum Provider opzeruffen. Sollt ni fir normal Appen néideg sinn. + + Informatiounen iwwer d\'Netzwierkkonditiounen offänken + + Erlaabt der App, Informatiounen zu den Netzwierkkonditiounen z\'erfaassen. Sollt ni fir normal Appen néideg sinn. + Kalibréierung fir Methode fir anzeginn änneren + + Erlaabt der App d\'Kalibratiounsparametere vum Touchscreen z\'änneren. Sollt ni fir normal Appen néideg sinn. + + Op DRM-Zertifikater zougräifen + + Erlaabt enger App, op DRM-Zertifikater zouzegräifen a se ze provisionéieren. Sollt ni fir normal Appen néideg sinn. + Erlaabt der App, Informatiounen iwwer aktuell Android-Beam-Iwwerdroungen z\'empfänken + + DRM-Zertifikater läschen + + Erlaabt enger App, DRM-Zertifikater ze läschen. Sollt ni fir normal Appen néideg sinn. + + Un engem Provider-SMS/MMS-Service bannen + + Erlaabt de Besëtzer an d\'Iwwerfläch vum SMS/MMS-Service-Provider op dem ieweschten Niveau ze bannen. Sollt ni fir normal Appen néideg sinn. + + + + + + + Passwuertregelen definéieren + + + Versich fir d\'Entspäre vum Schierm iwwerwaachen + + Unzuel vun de falsche Passwierder beim Entspäre vum Schierm iwwerwaachen an den Tablet spären oder all d\'Daten um Tablet läsche wann ze dacks een e falscht Passwuert aginn huet. + + Unzuel vun de falsche Passwierder beim Entspäre vum Schierm iwwerwaachen an d\'Tlee spären oder all d\'Daten um Telefon läsche wann ze dacks een e falscht Passwuert aginn huet. + + Unzuel vun de falsche Passwierder beim Entspäre vum Schierm iwwerwaachen an den Telefon spären oder all d\'Daten um Telefon läsche wann ze dacks een e falscht Passwuert aginn huet. + + + + De Schierm spären + + Festleeë wéi a wéini de Schierm späert. + + All Date läschen + + Ouni Warnung op d\'Wierksastellungen zrécksetzen an Date vum Tablet läschen. + + Ouni Warnung op d\'Wierksastellungen zrécksetzen an Date vun der Tëlee läschen. + + Ouni Warnung op d\'Wierksastellungen zrécksetzen an Date vum Telefon läschen. + + + + + + De globale Proxy-Server fir den Apparat festleeën + + + + + Späicherverschlësselung + + Gespäichert App-Date musse verschlësselt ginn. + + Kameraen desaktivéieren + + D\'Benotzung vun alle Kameraen um Apparat verhënneren. + + + + + + + Doheem + Mobil + Aarbecht + Aarbechtsfax + Fax doheem + Pager + Aner + Personaliséiert + + + + + + Doheem + Aarbecht + Aner + Personaliséiert + + + + + + Doheem + Aarbecht + Aner + Personaliséiert + + + + + + Doheem + Aarbecht + Aner + Personaliséiert + + + + + + Aarbecht + Aner + Personaliséiert + + + + + + AIM + Windows Live + Yahoo + Skype + QQ + Google Talk + ICQ + Jabber + + + Personaliséiert + + Doheem + + Mobil + + Aarbecht + + Aarbechtsfax + + Fax doheem + + Pager + + Aner + + Réckruff + + Auto + + Firma + + ISDN + + Haapt + + Anere Fax + + Radio + + Telex + + TTY/TDD + + Handy (Aarbecht) + + Pager (Aarbecht) + + Assistent + + MMS + + Personaliséiert + + Gebuertsdag + + Joresdag + + Aner + + Personaliséiert + + Doheem + + Aarbecht + + Aner + + Mobil + + Personaliséiert + + Doheem + + Aarbecht + + Aner + + Personaliséiert + + Doheem + + Aarbecht + + Aner + + Personaliséiert + + AIM + + Windows Live + + Yahoo + + Skype + + QQ + + Hangouts + + ICQ + + Jabber + + NetMeeting + + Aarbecht + + Aner + + Personaliséiert + + Personaliséiert + + Assistent + + Brudder + + Kand + + Liewenspartner + + Papp + + Frënd + + Manager + + Mamm + + Elterendeel + + Partner + + Recommandéiert vu(n) + + Verwandten + + Schwëster + + Éierpartner + + Personaliséiert + + Doheem + + Aarbecht + + Aner + + Keng Applikatioun fonnt fir dëse Kontakt unzekucken. + + PIN-Code aginn + + PUK an neie PIN-Code aginn + + PUK-Code + + Neie PIN-Code + + Drécke fir d\'Passwuert anzeginn + + Passwuert agi fir z\'entspären + + PIN agi fir z\'entspären + + Falsche PIN-Code. + + Menü an dann 0 drécke fir z\'entspären. + + Noutruffnummer + + + + Kee Service. + + Schierm gespaart. + + Menü drécke fir z\'entspären oder en Noutruff ze maachen. + + Menü drécke fir z\'entspären. + + Muster zeechne fir z\'entspären + + + Zréck bei d\'Gespréich + + Korrekt! + + Probéier nees + + Probéier nees + + Maximal Versich fir mam Gesiicht z\'entspären iwwerschratt + + Keng SIM-Kaart + + Keng SIM-Kaart am Tablet. + + Keng Sim-Kaart an der Tëlee. + + Keng SIM-Kaart am Telefon. + + SIM-Kaart asetzen. + + D\'SIM-Kaart feelt oder ass net liesbar. Setz eng SIM-Kaart an. + + Onbenotzbar SIM-Kaart. + + Deng SIM-Kaart gouf permanent ausgeschalt.\n +Kontaktéier däi Provider fir eng aner SIM-Kaart ze kréien. + + Viregen Titel + + Nächsten Titel + + Paus + + Ofspillen + + Stopp + + Zréckspullen + + Virspullen + + Just Noutriff + + Netzwierk gespaart + + SIM-Kaart ass PUK-gespaart. + + D\'Benotzerhandbuch ukucken oder de Clientsservice kontaktéieren. + + D\'SIM-Kaart ass gespaart. + + D\'SIM-Kaart gëtt entspaart\u2026 + + Du hues däin Entspärmuster %d-mol falsch gemoolt.\n\nProbéier nees a(n) %d Sekonnen. + + Du hues däi Passwuert %d-mol falsch aginn.\n\nProbéier nees a(n) %d Sekonnen. + + Du hues däi PIN %d-mol falsch aginn.\n\nProbéier nees a(n) %d Sekonnen. + + Du hues däin Entspärmuster %d-mol falsch gezeechent. No %d weidere feelgeschloene Versich muss du däin Tablet mat denge Login-Date vu Google entspären.\n\nProbéier a(n) %d Sekonnen nees. + + Du hues däin Entspärmuster %dmol- falsch gezeechent. No %d weidere feelgeschloene Versich muss du deng Tëlee mat denge Login-Date vu Google entspären.\n\nProbéier a(n) %d Sekonnen nees. + + Du hues däin Entspärmuster %d-mol falsch gezeechent. No %d weidere feelgeschloene Versich muss du däin Telefon mat denge Login-Date vu Google entspären.\n\nProbéier a(n) %d Sekonnen nees. + + Du hues %d-mol ouni Erfolleg versicht den Tablet z\'entspären. No %d weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer. + + Du hues %d mol ouni Erfolleg versicht d\'Tëlee z\'entspären. No %d weidere feelgeschloene Versich gëtt deng Tëlee op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer. + + Du hues %d-mol ouni Erfolleg versicht den Telefon z\'entspären. No %d weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer. + + Du hues %d-mol ouni Erfolleg versicht den Tablet z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat. + + Du hues %d-mol ouni Erfolleg versicht d\'Tëlee z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat. + + Du hues %d-mol ouni Erfolleg versicht den Telefon z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat. + + Probéier nees a(n) %d Sekonnen. + + Muster vergiess? + + Kont-Entspärung + + Ze vill Musterversich + + Fir z\'entspären, mell dech mat dengem Google-Kont un. + + Benotzernumm (E-Mail) + + Passwuert + + Aloggen + + Ongëltege Benotzernumm oder Passwuert. + + Benotzernumm oder Passwuert vergiess\?\nBesich google.com/accounts/recovery. + + Iwwerpréiwung\u2026 + + Entspären + + Toun un + + Toun aus + + Muster ugefaangen + + Muster geläscht + + Zell dobäigesat + + + Muster ofgeschloss + + Musterberäich. + + %1$s. Widget %2$d vu(n) %3$d. + + Widget dobäisetzen. + + Eidel + + Entspärberäich maximéiert. + + Entspärberäich miniméiert. + + %1$s Widget. + + Benotzerauswiel + + Status + + Fotoapparat + + Steierelementer fir Medien + + Neiuerdnung vun de Widgete gestart. + + Neiuerdnung vun de Widgete gestoppt. + + Widget %1$s geläscht. + + Erweider den Entspärberäich. + + Entspäre mat Fangerbeweegung. + + Entspäre mat Muster. + + Entspäre mam Gesiicht. + + Entspäre mat PIN. + + Entspäre mat Passwuert. + + Musterberäich. + + Beräich fir Fangerbeweegung. + + + + \?123 + + ABC + + ALT + + Zeechen + + Wuert + + Link + + Zeil + + "%-l%P" + + "%-l%p" + + Wierkstest feelgeschloen + + D\'FACTORY_TEST-Aktioun ass just ënnerstëtzt fir Päck déi am Dossier /system/app installéiert sinn. + + Et gouf kee Pak fonnt deen d\'FACTORY_TEST-Aktioun zur Verfügung stellt. + + Nei starten + + + + D\'Säit \"%s\" seet: + + JavaScript + + Navigatioun bestätegen + + Dës Säit verloossen + + Op dëser Säit bleiwen + + %s\n\nBass du sécher datt s du vun dëser Säit ewechnavigéiere wëlls? + + Bestätegen + + Tipp: Zweemol drécke fir eran- an erauszezoomen. + + Automatescht Ausfëllen + + Automatescht Ausfëllen astellen + + \u0020 + + $1$2$3 + + ,\u0020 + + $1$2$3 + + attention|attn + + province|region|other|provincia|bairro|suburb + + company|business|organization|organisation|department|firma|firmenname|empresa|societe|société|ragione.?sociale|会社|название.?компании|单位|公司 + + address.?line|address1|addr1|street|strasse|straße|hausnummer|housenumber|house.?name|direccion|dirección|adresse|indirizzo|住所1|morada|endereço|Адрес|地址 + + address|adresse|indirizzo|住所|地址 + + address.?line2|address2|addr2|street|suite|unit|adresszusatz|ergänzende.?angaben|direccion2|colonia|adicional|addresssuppl|complementnom|appartement|indirizzo2|住所2 + + address.?line3|address3|addr3|street|line3|municipio|batiment|residence|indirizzo3 + + country|location|国|国家 + + zip|postal|post code|pcode|^1z$|postleitzahl|cp|cdp|cap|郵便番号|codigo|codpos|cep|Почтовый.?Индекс|邮政编码|邮编|郵遞區號 + + zip|^-$|post2|codpos2 + + city|town|ort|stadt|suburb|ciudad|provincia|localidad|poblacion|ville|commune|localita|市区町村|cidade|Город|市|分區 + + state|county|region|province|land|county|principality|都道府県|estado|provincia|область|省|地區 + + same as + + use my + + bill + + ship + + e.?mail|メールアドレス|Электронной.?Почты|邮件|邮箱|電郵地址 + + user.?name|user.?id|vollständiger.?name|用户名 + + ^name|full.?name|your.?name|customer.?name|firstandlastname|nombre.*y.*apellidos|^nom|お名前|氏名|^nome|姓名 + + ^name|^nom|^nome + + irst.*name|initials|fname|first$|vorname|nombre|forename|prénom|prenom|名|nome|Имя + + middle.*initial|m\\.i\\.|mi$ + + middle.*name|mname|middle$|apellido.?materno|lastlastname + + last.*name|lname|surname|last$|nachname|apellidos|famille|^nom|cognome|姓|morada|apelidos|surename|sobrenome|Фамилия + + phone|telefonnummer|telefono|teléfono|telfixe|電話|telefone|telemovel|телефон|电话 + + area.*code|acode|area + + prefix|preselection|ddd + + suffix + + ext|ramal + + card.?holder|name.?on.?card|ccname|owner|karteninhaber|nombre.*tarjeta|nom.*carte|nome.*cart|名前|Имя.*карты|信用卡开户名|开户名|持卡人姓名|持卡人姓名 + + name + + verification|card identification|cvn|security code|cvv code|cvc + + number|card.?#|card.?no|ccnum|nummer|credito|numero|número|numéro|カード番号|Номер.*карты|信用卡号|信用卡号码|信用卡卡號 + + expir|exp.*month|exp.*date|ccmonth|gueltig|gültig|monat|fecha|date.*exp|scadenza|有効期限|validade|Срок действия карты|月 + + exp|^/|year|ablaufdatum|gueltig|gültig|yahr|fecha|scadenza|有効期限|validade|Срок действия карты|年|有效期 + + ^card + + fax|télécopie|telecopie|ファックス|факс|传真|傳真 + + country.*code|ccode|_cc + + ^\\($ + + ^-$|^\\)$ + + ^-$ + + Provënz + + Postleetzuel + + Staat + + Postleetzuel + + Landkrees + + Insel + + Bezierk + + Departement + + Präfektur + + Gemeng + + Gebitt + + Emirat + + Internet-Lieszeechen an däin Historique liesen + + Erlaabt der App, den Historique vun alle Säiten déi s de besicht hues an all dengem Browser seng Liesezeechen ze liesen. Hiwäis: dës Berechtegung gëtt eventuell net vu Browsere vun Drëtthiersteller oder aneren Appe mat Internetfäegkeete berücksichtegt. + + Internet-Lieszeeche schreiwen an den Historique änneren + + + Erlaabt der App, den Historique oder d\'Lieszeechen déi vun dengem Browser op der Tëlee gespäichert sinn z\'änneren. Dat kéint der App erméiglechen, d\'Browserdaten z\'änneren oder ze läschen. Wichteg: Dës Berechtegung kéint vu Browseren oder aneren Appe vun Drëtthiersteller net berücksichtegt ginn. + + + Wecker stellen + + + Mailboxopnamen dobäisetzen + + Erlaabt der App, Messagen op denger Mailbox ze späicheren. + + Geolokaliséierungs-Berechtegunge vum Browser änneren + + Erlaabt der App, d\'Geolokaliséierungs-Berechtegunge vum Browser z\'änneren. Béisaarteg Appe kéinten dat benotze fir Standuertinformatiounen un arbiträr Websäiten ze schécken. + + Wëlls du datt de Browser dëst Passwuert verhält? + + Net elo + + Erënneren + + Ni + + Du hues keng Berechtegung fir dës Säit opzemaachen. + + Text an d\'Tëschenoflag kopéiert. + + Méi + + Menü+ + + Espace + + Enter + + läschen + + + + Sichen + + Sichen… + + Sichen + + Sichufro + + Ufro läschen + + Ufro schécken + + Stëmmsich + + Drécken an Entdecken aktivéieren? + + %1$s wëll \"Drécken an Entdecken\" aktivéieren. +Wann \"Drécken an Endecken\" aktivéiert ass, kanns du Beschreiwunge vun Elementer héieren oder gesinn déi ënner dengem Fanger sinn oder iwwer Geste mam Tablet interagéieren. + + %1$s wëll \"Drécken an Entdecken\" aktivéieren. +Wann \"Drécken an Endecken\" aktivéiert ass, kanns du Beschreiwunge vun Elementer héieren oder gesinn déi ënner dengem Fanger sinn oder iwwer Geste mam Telefon interagéieren. + + Virun 1 Mount + + Viru méi als 1 Mount + + + Leschte Mount + + Méi al + + um %s + + um %s + + am Joer %s + + Dag + + Deeg + + Stonn + + Stonnen + + min + + min + + s + + s + + Woch + + Wochen + + Joer + + Joer + + + 1 Sekonn + %d Sekonnen + + + + 1 Minutt + %d Minutten + + + + 1 Stonn + %d Stonnen + + + Videoproblem + + De Video ass net gëlteg fir op dësen Apparat gestreamt ze ginn. + + Dëse Video kann net ofgespillt ginn. + + OK + + "%1$s, %2$s" + + "Mëtteg" + + "Mëtteg" + + "Hallefnuecht" + + "Hallefnuecht" + + %1$02d:%2$02d + + %1$d:%2$02d:%3$02d + + All auswielen + + Schneiden + + Kopéieren + + Apechen + + Ersetzen\u2026 + + Läschen + + URL kopéieren + + Text auswielen + + Textauswiel + + An den Dictionnaire setzen + + Läschen + + Method fir anzeginn + + Textaktiounen + + De Späicher huet geschwë keng Plaz méi + + E puer Systemfunktioune funktionéiere vläicht net + + Net genuch Späicher fir de System. Stell sécher, datt s de 250MB fräi Späicherplaz hues a start nei. + + %1$s gëtt ausgeféiert + + Dréck fir méi Informatiounen + oder fir d\'App unzehalen. + + OK + + Ofbriechen + + OK + + Ofbriechen + + Opgepasst + + Gëtt gelueden\u2026 + + UN + + AUS + + Aktioun duerchféiere mat + + Aktioun mat %1$s ofschléissen + + Opmaache mat + + Opmaache mat %1$s + + Ännere mat + + Ännere mat %1$s + + Deele mat + + Deele mat %1$s + + Start-App auswielen + + %1$s als Start-App auswielen + + Standardméisseg fir dës Aktioun benotzen. + + Eng aner App benotzen + + D\'Standardastellunge kënnen ënner \"Astellungen > Appen > Erofgelueden\" geläscht ginn. + + Wiel eng Aktioun aus + + Wiel eng App fir den USB-Apparat aus + + Dës Aktioun ka vu kenger App duerchgefouert ginn. + + + + Leider huet %1$s opgehale mat Funktionéieren. + + Leider gouf de Prozess %1$s gestoppt. + + + + %2$s äntwert net.\n\nWëlls de d\'App zoumaachen? + + D\'Aktivitéit %1$s äntwert net.\n\nWëlls de se zoumaachen? + + %1$s äntwert net.\n\nWëlls de d\'App zoumaachen? + + De Prozess %1$s äntwert net.\n\nWëlls de e zoumaachen? + + OK + + Bericht + + Waart + + D\'Säit reagéiert net méi.\n\nWëlls de se zoumaachen? + + App ëmgeleet + + %1$s leeft elo. + + %1$s gouf ursprünglech gestart. + + Skaléieren + + Ëmmer uweisen + + Reaktivéierung ënner Astellungen > Appen > Erofgelueden. + + D\'App %1$s (Prozess %2$s) huet géint déi selwer operluechte StrictMode-Richtlinne verstouss. + + De Prozess %1$s huet géint déi selwer operluechte StrictMode-Richtlinne verstouss. + + Android gëtt aktualiséiert\u2026 + + Android gëtt gestart\u2026 + + Späicher optiméieren. + + Optiméierung vun der App %1$d / %2$d. + + + Appe gi gestart. + + Start gëtt ofgeschloss. + + %1$s leeft + + Drécke fir bei d\'App ze wiesselen + + Appe wiesselen? + + Et leeft schonn eng App déi muss gestoppt gi fir eng nei ze starten. + Zréck bei %1$s + Déi nei App net starten. + %1$s starten + Déi al App ouni ze späichere stoppen. + + + + + + Aktioun fir Text auswielen + + Schelltounlautstäerkt + + Medielautstäerkt + + Iwwer Bluetooth ofspillen + + Stëlle Schelltoun gesat + + Hörerlautstäerkt + + Hörerlautstäerkt iwwer Bluetooth + + Weckerlautstäerkt + + Notifikatiounslautstäerkt + + Lautstäerkt + + Bluetooth-Lautstäerkt + + Schelltounlautstäerkt + + Urufflautstäerkt + + Medielautstäerkt + + Notifikatiounslautstäerkt + + + + Standardschelltoun + + Standard-Schelltoun (%1$s) + + Keen + + Schelltéin + + Onbekannte Schelltoun + + + WLAN-Netzwierk disponibel + WLAN-Netzwierker disponibel + + + + Oppent WLAN-Netzwierk disponibel + Oppe WLAN-Netzwierker disponibel + + + + + %1$s + + + + Konnt net mam WLAN connectéieren + + \u0020huet eng schwaach Internetconnectioun. + + + + + + Wi-Fi Direct + Wi-Fi Direct starten. De WLAN-Zougankspunkt gëtt doduerch ausgeschalt. + Konnt Wi-Fi Direct net starten. + Wi-Fi Direct ass un + Dréck fir d\'Astellungen + Acceptéieren + Refuséieren + Invitatioun geschéckt + Invitatioun fir ze verbannen + Vun:  + Un:  + Gëff de benéidegte PIN an: + PIN:  + Den Tablet gëtt kuerzzäiteg vum WLAN deconnectéiert während e mat %1$s verbonnen ass + D\'Tëlee gëtt kuerzzäiteg vum WLAN deconnectéiert während e mat %1$s verbonnen ass + Den Telefon gëtt kuerzzäiteg vum WLAN deconnectéiert während e mat %1$s verbonnen ass + + Zeechen aginn + + + + SMS-Messagë gi geschéckt + + <b>%1$s</b> verschéckt eng grouss Zuel vun SMSen. Wëlls du der App erlabe weider Messagen ze verschécken? + + Erlaben + + Verweigeren + + + + <b>%1$s</b> wëll e Message un <b>%2$s</b> schécken. + + Doduerch kënne Käschten op denger Mobilrechnung entstoen. + + Doduerch entsti Käschten op dengem Mobilabo. + + Schécken + + Ofbriechen + + Mäi Choix verhalen + + Du kanns dat méi spéit ënner Astellungen\u00A0>\u00A0Appen änneren + + Ëmmer erlaben + + Ni erlaben + + + + SIM-Kaart erausgeholl + + D\'Mobilnetzwierk ass net disponibel bis de eng gëlteg SIM-Kaart asetz an nei starts. + + Fäerdeg + + SIM-Kaart dobäigesat + + Start den Handy nei fir op d\'Mobilnetz zouzegräifen. + + Nei starten + + + Zäit setzen + + Datum setzen + + Setzen + + Fäerdeg + + + NEI: + + Zur Verfügung gestallt vu(n) %1$s. + + Keng Berechtegungen néideg + + dëst kéint dech Sue kaschten + + + USB-Massespäicher + + USB connectéiert + + Du hues den Apparat iwwer USB un däi Computer ugeschloss. Dréck de Knäppchen hei drënner wann s du Fichieren tëscht dengem Computer an dem USB-Späicher vun dengem Android-Apparat wëlls kopéieren. + + Du hues den Apparat iwwer USB un däi Computer ugeschloss. Dréck de Knäppchen hei drënner wann s du Fichieren tëscht dengem Computer an der SD-Kaart vun dengem Android-Apparat wëlls kopéieren. + + USB-Späicher aktivéieren + + Beim Versuch däin USB-Späicher als USB-Massespäicher ze benotze gouf et e Problem. + + Beim Versuch deng SD-Kaart als USB-Massespäicher ze benotze gouf et e Problem. + + USB connectéiert + + Dréck fir Fichiere vum/op de Computer ze kopéieren. + + USB-Späicher desaktivéieren + + Dréck fir den USB-Späicher auszeschalten. + + + + USB-Späicher gëtt benotzt + + Ier s de den USB-Späicher ausschalts, trenn (\"ejectéieren\") dengem Android säin USB-Späicher vum Computer. + + Ier s de den USB-Späicher ausschalts, trenn (\"ejectéieren\") dengem Android seng SD-Kaart vum Computer. + + USB-Späicher desaktivéieren + + Et gouf e Problem beim Ausschalte vum USB-Späicher. Kontrolléier datt den USB-Host getrennt gouf a probéier nees. + + USB-Späicher aktivéieren + + Wann s du den USB-Späicher uschalts kéinte verschidden Appen ophale mat funktionéiere bis de den USB-Späicher nees ausschalts. + + USB-Operatioun feelgeschloen + + OK + + USB fir ze lueden + + + + + Als USB-Accessoire verbonnen + + + USB-Debugging verbonnen + + Dréck fir USB-Debugging auszeschalten. + + + + + + + Tastatur wiesselen + + Tastaturen auswielen + + Method fir anzeginn uweisen + + Hardware + + Tastaturlayout auswielen + + Dréck fir den Tastaturlayout auszewielen. + \u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ + \u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ + Kandidaten + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Iwwerpréiwung\u2026 + + + + + + + + + + Keng passend Aktivitéit fonnt. + + + Erlaabt der App, d\'Medienausgab un extern Apparater weiderzeleeden. + + + Erlaabt der App, Installatiounssëtzungen ze liesen. Dat erméiglecht der App, Detailer iwwer Päck ze gesinn, déi grad installéiert ginn. + + + + Zweemol drécke fir d\'Zoomastellungen + + Konnt de Widget net dobäisetzen. + + Lass + + Sichen + + Schécken + + Weider + + Fäerdeg + + Zréck + + Ausféieren + + + + Nummer\nmat %s auswielen + + Neie Kontakt\nmat %s erstellen + + + + Dës Appe brauchen eng Berechtegung fir elo an an Zukunft op däi Kont zouzegräifen. + Wëlls du dës Ufro erlaben? + Zougrëffsufro + Erlaben + Verweigeren + Erlaabnesufro + Erlaabnes ugefrot\nfir de Kont %s. + + Du benotz dës App ausserhalb vun dengem Aarbechtsprofil + + Du benotz dës App an dengem Aarbechtsprofil + + Method fir anzeginn + + Sync + + Accessibilitéit + + Hannergrondbild + + Hannergrondbild änneren + + Notifikatiouns-Nolauschterer + + Konditiounsubidder + + + VPN aktivéiert + + VPN ass aktivéiert vum %s + + Dréck fir d\'Netzwierk ze geréieren. + + Verbonne mat %s. Dréck fir d\'Netzwierk ze geréieren. + + Permanent aktive VPN gëtt connectéiert\u2026 + + Permanent aktive VPN connectéiert + + Feeler beim permanent aktive VPN + + Dréck fir anzestellen + + + Fichier auswielen + + Kee Fichier ausgewielt + + Zrécksetzen + + Schécken + + + Automodus aktivéiert + Dréck fir den Automodus auszemaachen. + + + Tethering oder Zougankspunkt aktiv + Fir ze setzen drécken. + + Zréck + Weider + + Iwwersprangen + + Keng Treffer + + Op der Säit fannen + + + + 1 Treffer + + %d vu(n) %d + + + Fäerdeg + + + Den USB-Späicher gëtt geläscht\u2026 + + SD-Kaart gëtt geläscht\u2026 + + + Deelen + + Sichen + + Websich + + Weidersichen + + Resultat virdrun + + Standuertoffro vu(n) %s + + Standuertoffro + + Ugefrot vum %1$s (%2$s) + + Jo + + Nee + + Läschlimitt erreecht + + Et ginn %1$d geläschten Elementer fir %2$s, Kont %3$s. Wat wëlls du maachen? + + Elementer läschen + + Läschen zrécksetzen + + Am Moment näischt maachen + + E Kont auswielen + "E Kont dobäisetzen" + + Kont dobäisetzen + + + Eropsetzen + + Erofsetzen + + %s drécken an unhalen. + + Eropwësche fir z\'erhéijen, erofwësche fir ze reduzéieren. + + + Minutt eropsetzen + + Minutt erofsetzen + + Stonn eropsetzen + + Stonn erofsetzen + + PM-Wäert setzen + + AM-Wäert setzen + + + Mount eropsetzen + + Mount erofsetzen + + Dag eropsetzen + + Dag erofsetzen + + Joer eropsetzen + + Joer erofsetzen + + + + + Alt + + Ofbriechen + + Läschen + + Fäerdeg + + Modusännerung + + Shift + + Enter + + + App auswielen + + Konnt %s net starten + + + Deele mat + + Deele mat %s + + + "Wëschgrëff. Drécken an halen." + + Wësche fir z\'entspären. + + Schléiss en Headset u fir d\'Passwuerttaste virgelies ze kréien. + + Punkt. + + Heem navigéieren + + Erop navigéieren + + Méi Optiounen + + %1$s. %2$s + + %1$s, %2$s. %3$s + + Interne Späicher + + SD-Kaart + + + + + USB-Späicher + + Dateverbrauchswarnung + + Drécke fir Verbrauch an Astellungen unzeweisen. + + 2G/3G Datelimitt erreecht + + 4G Datelimitt erreecht + + Mobil Datelimitt erreecht + + WLAN-Datelimitt erreecht + + Date pauséiert fir de Rescht vum Zyklus + + 2G- an 3G-Datelimitt iwwerschratt + + 4G-Datelimitt iwwerschratt + + Mobil Datelimitt iwwerschratt + + Wi-Fi-Datelimitt iwwerschratt + + %s iwwer der definéierter Limitt. + + Hannergronddaten ageschränkt + + Drécke fir d\'Restriktiounen opzehiewen. + + + Sécherheetszertifikat + + Dëst Zertifikat ass gëlteg. + + Ausgestallt fir: + + Allgemengen Numm: + + Organisatioun: + + Eenheet an der Organisatioun: + + Ausgestallt vun: + + Gëltegkeet: + + Ausgestallt den: + + Leeft of den: + + Seriennummer: + + Fangerofdréck: + + SHA-256-Fangerofdrock: + + SHA-1-Fangerofdrock: + + All uweisen + + Aktivitéit auswielen + + Deele mat + + ", " + + Gëtt geschéckt\u2026 + + Browser starten? + + Uruff unhuelen? + + Ëmmer + + Just eemol + + %1$s ënnerstëtzt keen Aarbechtsprofil + + Tablet + + Tëlee + + Telefon + + Kopfhörer + + Dock-Lautsprecher + + HDMI + + System + + Bluetooth-Audio + + Kabellose Schierm + + Iwwerdroen + + Mat Apparat verbannen + + Schierm op Apparat iwwerdroen + + Et gëtt no Apparater gesicht\u2026 + + Astellungen + + Deconnectéieren + + Gëtt gescannt... + + Gëtt connectéiert... + + Disponibel + + Net disponibel + + Gëtt benotzt + + + Agebaute Schierm + + HDMI-Schierm + + Overlay #%1$d + + %1$s: %2$dx%3$d, %4$d dpi + + , sécher + + + Muster vergiess + + Falscht Muster + + Falscht Passwuert + + Falsche PIN + + Probéier nees a(n) %1$d Sekonnen. + + Mol däi Muster + + SIM-PIN aginn + + PIN aginn + + Passwuert aginn + + D\'SIM ass elo desaktivéiert. Gëff e PUK-Code a fir weiderzemaachen. Kontaktéier däi Provider fir Detailer. + + Gëff de gewënschte PIN-Code an + + Bestäteg de gewënschte PIN-Code + + D\'SIM-Kaart gëtt entspaart\u2026 + + Falsche PIN-Code. + + Gëff e PIN an, deen tëscht 4 an 8 Zifferen huet. + + De PUK-Code sollt 8 Ziffere laang sinn. + + Gëff de korrekte PUK-Code nees an. Bei widderhuelende Versich gëtt d\'SIM permanent desaktivéiert. + + D\'PIN-Codë stëmmen net iwwereneen + + Zevill Muster-Versich + + Fir z\'entspären, mell dech mat dengem Google-Kont un. + + Benotzernumm (E-Mail) + + Passwuert + + Aloggen + + Ongëltege Benotzernumm oder Passwuert. + + Benotzernumm oder Passwuert vergiess\?\nBesich google.com/accounts/recovery. + + Kont gëtt iwwerpréift\u2026 + + Du hues däi PIN %d-mol falsch aginn.\n\nProbéier nees a(n) %d Sekonnen. + + Du hues däi Passwuert %d-mol falsch aginn.\n\nProbéier nees a(n) %d Sekonnen. + Du hues däin Entspärmuster %d-mol falsch gemoolt.\n\nProbéier nees a(n) %d Sekonnen. + + Du hues %d-mol ouni Erfolleg versicht den Tablet z\'entspären. No %d weidere feelgeschloene Versich gëtt den Tablet op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer. + + Du hues %d-mol ouni Erfolleg versicht d\'Tëlee z\'entspären. No %d weidere feelgeschloene Versich gëtt den Telefon op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer. + + Du hues %d-mol ouni Erfolleg versicht den Telefon z\'entspären. No %d weidere feelgeschloene Versich gëtt den Telefon op d\'Wierksastellungen zréckgesat an all d\'Benotzerdate gi verluer. + + Du hues %d-mol ouni Erfolleg versicht den Tablet z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat. + + Du hues %d-mol ouni Erfolleg versicht d\'Tëlee z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat. + + Du hues %d-mol ouni Erfolleg versicht den Telefon z\'entspären. E gëtt elo op d\'Wierksastellungen zréckgesat. + + Du hues däin Entspärmuster %d-mol falsch gezeechent. No %d weidere feelgeschloene Versich gëss de gefrot däin Tablet mat engem E-Mail-Kont z\'entspären.\n\nProbéier a(n) %d Sekonnen nees. + + Du hues däin Entspärmuster %d-mol falsch gemoolt. No %d weidere feelsgeschloene Versich gëss du gefrot deng Tëlee duerch en E-Mail-Kont z\'entspären. Probéier nees a(n) %d Sekonnen. + + Du hues däin Entspärmuster %d-mol falsch gezeechent. No %d weidere feelgeschloene Versich gëss de gefrot däin Telefon mat engem E-Mail-Kont z\'entspären.\n\nProbéier a(n) %d Sekonnen nees. + + " \u2014 " + + Ewechhuelen + + D\'Lautstäerkt iwwer de recommandéierten Niveau erhéijen?\n\nIwwer laang Periode bei héijer Lautstäerkt Musek lauschtere kéint däi Gehéier schiedegen. + + Mat zwee Fangeren drécke fir d\'Benotzungshëllefen z\'aktivéieren. + + Accessibilitéit aktivéiert. + + Accessibilitéit ofgebrach. + + Aktuelle Benotzer %1$s. + + Wiesselen op de Benotzer %1$s\u2026 + + Besëtzer + + Feeler + + Dës Ännerung ass duerch däin Administrateur net erlaabt + + Et gouf keng Applikatioun fonnt fir dës Aktioun auszeféieren + Zréckzéien + + + ISO A0 + + ISO A1 + + ISO A2 + + ISO A3 + + ISO A4 + + ISO A5 + + ISO A6 + + ISO A7 + + ISO A8 + + ISO A9 + + ISO A10 + + ISO B0 + + ISO B1 + + ISO B2 + + ISO B3 + + ISO B4 + + ISO B5 + + ISO B6 + + ISO B7 + + ISO B8 + + ISO B9 + + ISO B10 + + ISO C0 + + ISO C1 + + ISO C2 + + ISO C3 + + ISO C4 + + ISO C5 + + ISO C6 + + ISO C7 + + ISO C8 + + ISO C9 + + ISO C10 + + Letter + + Government Letter + + Legal + + Junior Legal + + Ledger + + Tabloid + + Index Card 3x5 + + Index Card 4x6 + + Index Card 5x8 + + Monarch + + Quarto + + Foolscap + + ROC 8K + + ROC 16K + + PRC 1 + + PRC 2 + + PRC 3 + + PRC 4 + + PRC 5 + + PRC 6 + + PRC 7 + + PRC 8 + + PRC 9 + + PRC 10 + + PRC 16K + + Pa Kai + + Dai Pa Kai + + Jurro Ku Kai + + JIS B10 + + JIS B9 + + JIS B8 + + JIS B7 + + JIS B6 + + JIS B5 + + JIS B4 + + JIS B3 + + JIS B2 + + JIS B1 + + JIS B0 + + JIS Exec + + Chou4 + + c + + Chou2 + + Hagaki  + + Oufuku  + + Kahu + + Kaku2 + + You4 + + Onbekannt Héichformat + + Onbekannt Queeschformat + + Ofgebrach + + Feeler beim Schreiwe vum Inhalt + + onbekannt + + Dréck-Service net aktivéiert + + %s Service installéiert + + Dréck fir z\'aktivéieren + + Administrateur-PIN aginn + + PIN aginn + + Inkorrekt + + Aktuell PIN + + Nei PIN + + Nei PIN bestätegen + + PIN fir d\'Ännerung vun Aschränkungen uleeën + + D\'PINe stëmmen net iwwereneen. Probéier nees w.e.g.. + + De PIN ass ze kuerz. E muss mindestens 4 Zifferen hunn. + + + + Probéier nees an 1 Sekonn + Probéier nees a(n) %d Sekonnen + + + Probéier méi spéit nees + + + + + Fäerdeg + + Kreesfërmege Regeler fir Stonnen + + Kreesfërmege Regeler fir Minutten + + Stonnen auswielen + + Minutten auswielen + + Mount an Dag auswielen + + Joer auswielen + + %1$s geläscht + + %1$s (Aarbecht) + + -- + + + + + + + Hal \"Zréck\" an \"Iwwersiicht\" matenee gedréckt fir dëse Schierm fräizeginn. + + Hal \"Iwwersiicht\" gedréckt fir dëse Schierm fräizeginn. + + + Schierm fixéiert + + Schierm fräiginn + + E PIN froe fir e Schierm fräizeginn + + En Entspärmuster froe fir e Schierm fräizeginn + + E Passwuert froe fir e Schierm fräizeginn + + + + + Den Energiespuermodus schount den Akku, andeem en d\'Leeschtung vum Apparat reduzéiert, d\'Vibratioun limitéiert an déi meescht Hannergronddatenaktivitéiten aschränkt. E-Mail, Messagen an aner Appen, déi op dengem Apparat synchroniséieren, gi méiglecherweis eréischt nom Opmaachen aktualiséiert.\n\nDen Energiespuermodus gëtt automatesch desaktivéiert, wann däin Apparat opgeluede gëtt. + + + Fir eng Minutt (bis %2$s) + Fir %1$d Minutten (bis %2$s) + + + + + Fir eng Stonn (bis %2$s) + Fir %1$d Stonnen (bis %2$s) + + + + + Fir eng Minutt + Fir %d Minutten + + + + + Fir eng Stonn + Fir %d Stonnen + + + + Bis %1$s + + + + + + Zouklappen + + Net stéieren + + + + + + Roueg gestallt duerch %1$s + + Mat dengem Apparat ass en interne Problem opgetrueden. Wann e sech instabil behuelt muss du en op d\'Wierksastellungen zrécksetzen. + + Mat dengem Apparat ass en interne Problem opgetrueden. Kontaktéier däin Hiersteller fir méi Detailer. + + D\'USSD-Ufro gouf an eng DIAL-Ufro ëmgewandelt. + D\'USSD-Ufro gouf an eng SS-Ufro ëmgewandelt. + D\'USSD-Ufro gouf an eng nei USSD-Ufro ëmgewandelt. + D\'SS-Ufro gouf an eng DIAL-Ufro ëmgewandelt. + D\'SS-Ufro gouf an eng USSD-Ufro ëmgewandelt. + D\'SS-Ufro gouf an eng nei SS-Ufro ëmgewandelt. + + + + + + + Méi Optiounen + + + + + + diff --git a/core/res/res/values-lo-rLA-watch/strings.xml b/core/res/res/values-lo-rLA-watch/strings.xml index a8c9cd2c30b42..4fb6671c43150 100644 --- a/core/res/res/values-lo-rLA-watch/strings.xml +++ b/core/res/res/values-lo-rLA-watch/strings.xml @@ -21,4 +21,5 @@ "ແອັບ %1$d ໃນ %2$d." + "ເຊັນເຊີ" diff --git a/core/res/res/values-lo-rLA/cm_strings.xml b/core/res/res/values-lo-rLA/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-lo-rLA/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index 30ecce50b6f5c..559b0ea0fbdd1 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -254,7 +254,7 @@ "ຮວມທັງຂໍ້ມູນສ່ວນໂຕເຊັ່ນ: ເລກບັດເຄຣດິດ ແລະລະຫັດຜ່ານ." "ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ" "ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້." - "ແຖບສະຖານະ" + "ເປັນ​ແຖບ​ສະ​ຖາ​ນະ" "ອະນຸຍາດໃຫ້ແອັບຯເປັນແຖບສະຖານະ." "ຫຍໍ້/ຂະຫຍາຍ ແຖບສະຖານະ" "ອະນຸຍາດໃຫ້ແອັບຯ ຂະຫຍາຍ ຫຼືຫຍໍ້ແຖບສະຖານະ." @@ -282,7 +282,7 @@ "ອະນຸຍາດໃຫ້ແອັບຯຮັບ ແລະປະມວນຜົນຂໍ້ຄວາມ WAP. ການອະນຸຍາດນີ້ຮວມເຖິງຄວາມສາມາດໃນການກວດເບິ່ງ ແລະລຶບຂໍ້ຄວາມທີ່ສົ່ງແລ້ວ ໂດຍບໍ່ຕ້ອງສະແດງໃຫ້ທ່ານເຫັນ." "ດຶງແອັບຯທີ່ເຮັດວຽກຢູ່ມາ" "ອະນຸຍາດໃຫ້ແອັບຯດຶງຂໍ້ມູນກ່ຽວກັບການເຮັດວຽກໃນປັດຈຸບັນ ແລະຫາກໍຜ່ານມາ. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດຄົ້ນພົບຂໍ້ມູນ ກ່ຽວກັບແອັບພລິເຄຊັນທີ່ໃຊ້ຢູ່ໃນອຸປະກອນໄດ້." - "ຈັດ​ການ​ເຈົ້າ​ຂອງ​ໂປ​ຣ​ໄຟ​ລ໌ ແລະ​ອຸ​ປະ​ກອນ" + "ຈັດ​ການ​ເຈົ້າ​ຂອງ​ໂປ​ຣ​ໄຟ​ລ໌ ແລະ​ ອຸ​ປະ​ກອນ" "ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ຕັ້ງ​ເຈົ້າ​ຂອງ​ໂປ​ຣ​ໄຟ​ລ໌ ແລະ​ເຈົ້າ​ຂອງ​ອຸ​ປະ​ກອນ." "ຮຽງລຳດັບແອັບຯທີ່ກຳລັງເຮັດວຽກຄືນໃໝ່" "ອະນຸຍາດໃຫ້ແອັບຯຍ້າຍການເຮັດວຽກໄປໃສ່ດ້ານໜ້າ ແລະພື້ນຫຼັງໄດ້. ແອັບຯອາດຈະດຳເນີນການໂດຍບໍ່ຕ້ອງໃຫ້ທ່ານບອກ." @@ -324,7 +324,7 @@ "ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂບັນທຶກການໂທຂອງແທັບເລັດ ຮວມທັງຂໍ້ມູນກ່ຽວກັບການໂທອອກ ແລະໂທເຂົ້ານຳ. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດໃຊ້ຄຸນສົມບັດນີ້ເພື່ອລຶບ ຫຼືແກ້ໄຂບັນທຶກການໂທຂອງທ່ານໄດ້." "ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂບັນທຶກການໂທຂອງໂທລະພາບຂອງ​ທ່ານ ລວມທັງຂໍ້ມູນກ່ຽວກັບການໂທອອກ ແລະໂທເຂົ້ານຳ. ແອັບທີ່ເປັນອັນຕະລາຍອາດໃຊ້ຄຸນສົມບັດນີ້ເພື່ອລຶບ ຫຼືແກ້ໄຂບັນທຶກການໂທຂອງທ່ານໄດ້." "ອະນຸຍາດໃຫ້ແອັບຯ ແກ້ໄຂລາຍການການໂທໃນໂທລະສັບຂອງທ່ານ, ຮວມທັງຂໍ້ມູນກ່ຽວກັບສາຍໂທເຂົ້າ ແລະການໂທອອກ. ແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດໃຊ້ຄວາມສາມາດນີ້ ເພື່ອລຶບ ຫຼືແກ້ໄຂລາຍການການໂທຂອງທ່ານໄດ້." - "ເຊັນ​ເຊີ​​ຮ່າງ​ກາຍ (ເຊັ່ນ: ​ຕິດ​ຕາມ​ອັດ​ຕາ​ການ​ເຕັ້ນ​ຂອງ​ຫົວ​ໃຈ)" + "ເຂົ້າ​ຫາເຊັນ​ເຊີ​​ກວດຮ່າງ​ກາຍ (ເຊັ່ນ: ​ຈໍຕິດ​ຕາມ​ອັດ​ຕາ​ການ​ເຕັ້ນ​ຂອງຫົວ​ໃຈ)" "​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ເຂົ້າ​ເຖິງ​ຂໍ້​ມູນ​ຈາກ​ເຊັນ​ເຊີ​ທີ່​ຕິດ​ຕາມ​ສະ​ພາບ​ຮ່າງ​ການ​ຂອງ​ທ່ານ, ເຊັ່ນ: ອັດ​ຕາ​ການ​ເຕັ້ນ​ຂອງ​ຫົວ​ໃຈຂອງ​ທ່ານ." "ອ່ານກຳນົດການໃນປະຕິທິນຮວມທັງຂໍ້ມູນຄວາມລັບ" "ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການນັດໝາຍທັງໝົດທີ່ມີບັນທຶກໃນແທັບເລັດຂອງທ່ານ, ຮວມທັງຂອງໝູ່ ຫຼືໝູ່ທີ່ເຮັດວຽກນຳກັນໄດ້ ເຊິ່ງອາດເຮັດໃຫ້ແອັບຯສາມາດສົ່ງຕໍ່ ຫຼືບັນທຶກຂໍ້ມູນປະຕິທິນຂອງທ່ານ ບໍ່ວ່າຈະເປັນເລື່ອງຄວາມລັບ ຫຼືເລື່ອງລະອຽດອ່ອນແບບໃດກໍຕາມ." @@ -336,15 +336,15 @@ "ອະນຸຍາດໃຫ້ແອັບຯ ເພີ່ມ, ລຶບ, ປ່ຽນແປງນັດໝາຍທີ່ທ່ານສາມາດແກ້ໄຂໄດ້ໃນໂທລະສັບຂອງທ່ານ, ຮວມທັງຂອງໝູ່ຄູ່ ຫຼືເພື່ອນຮ່ວມວຽກ. ນີ້ອາດເຮັດໃຫ້ແອັບຯສາມາດສົ່ງຂໍ້ຄວາມ ທີ່ເບິ່ງຄືວ່າມາຈາກເຈົ້າຂອງປະຕິທິນ ຫຼືແກ້ໄຂນັດໝາຍໂດຍທີ່ທ່ານບໍ່ໄດ້ຮັບຮູ້ໄດ້." "ເຂົ້າເຖິງຄຳສັ່ງຜູ່ໃຫ້ບໍລິການພິກັດສະຖານທີ່" "ອະນຸຍາດ​ໃຫ້​ແອັບຯ​ເຂົ້າເຖິງ​ຄຳສັ່ງ​ເພີ່ມເຕີມ​ຂອງ​ຜູ່​ໃຫ້​ບໍລິການ​ສະຖານທີ່. ນີ້​ອາດ​ຈະ​ເປັນ​ການ​ເຮັດ​ໃຫ້​ແອັບຯ ລົບກວນ​ການ​ເຮັດ​ວຽກ​ຂອງ GPS ຫຼື​ແຫລ່ງ​ຂໍ້ມູນ​ສະຖານທີ່​ອື່ນໆ​ໄດ້." - "ສະຖານທີ່ແນ່ນອນ (ອ້າງອີງຈາກ GPS ແລະເຄືອຂ່າຍ)" + "ເຂົ້າ​ຫາທີ່ຕັ້ງທີ່ແນ່ນອນ (ອີງໃສ່ GPS ແລະ ເຄືອຂ່າຍ)" "ອະນຸຍາດໃຫ້ແອັບຯ ຮັບຕຳແໜ່ງສະຖານທີ່ລະອຽດຂອງທ່ານໂດຍໃຊ້ GPS ຫຼືແຫລ່ງຂໍ້ມູນເຄືອຂ່າຍສະຖານທີ່ເຊັ່ນ: ເສົາສັນຍານມືຖື ແລະ Wi-Fi. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຕ້ອງຖືກເປີດນຳໃຊ້ ແລະແລະມີຂໍ້ມູນໃຫ້ກັບອຸປະກອນຂອງທ່ານ ເພື່ອໃຫ້ແອັບຯໃຊ້ໄດ້. ແອັບຯຕ່າງໆອາດໃຊ້ຂໍ້ມູນນີ້ເພື່ອລະບຸສະຖານທີ່ຢູ່ຂອງທ່ານ ແລະອາດນຳໃຊ້ແບັດເຕີຣີເພີ່ມເຕີມໄດ້." - "ສະຖານທີ່ໂດຍປະມານ (ອ້າງອີງຈາກເຄືອຂ່າຍ)" + "ເຂົ້າ​ຫາທີ່ຕັ້ງໂດຍປະມານ (ອີງໃສ່ເຄືອຂ່າຍ)" "ອະນຸຍາດໃຫ້ແອັບຯ ລະບຸສະຖານທີ່ໂດຍປະມານຂອງທ່ານ. ສະຖານທີ່ນີ້ໄດ້ຮັບມາຈາກບໍລິການສະຖານທີ່ ໂດຍອາໃສສະຖານທີ່ເຄືອຂ່າຍເຊັ່ນ: ເສົາສັນຍານ ແລະ Wi-Fi. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຕ້ອງຖືກເປີດໃຊ້ ແລະ ມີໃນອຸປະກອນຂອງທ່ານເພື່ອທີ່ແອັບຯຈະສາມາດໃຊ້ພວກມັນໄດ້. ແອັບຯອາດຈະໃຊ້ຄຸນສົມບັດນີ້ ເພື່ອກວດສອບສະຖານທີ່ໂດຍປະມານຂອງທ່ານ." "ປ່ຽນການຕັ້ງຄ່າສຽງຂອງທ່ານ" "ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂການຕັ້ງຄ່າສຽງສ່ວນກາງ ເຊັ່ນ: ລະດັບສຽງ ແລະລຳໂພງໃດທີ່ຖືກໃຊ້ສົ່ງສຽງອອກ." "ບັນທຶກສຽງ" "ອະນຸຍາດໃຫ້ແອັບຯບັນທຶກສຽງດ້ວຍໄມໂຄຣໂຟນໄດ້. ການອະນຸຍາດນີ້ຈະເຮັດໃຫ້ແອັບຯ ສາມາດບັນທຶກສຽງໄດ້ຕະຫລອດເວລາ ໂດຍບໍ່ຕ້ອງຖ້າການຢືນຢັນຈາກທ່ານ." - "ການສື່ສານຂອງ SIM" + "ສົ່ງ​ຄຳ​ສັ່ງ​ຫາ SIM" "ອະນຸຍາດໃຫ້ແອັບຯສົ່ງຄຳສັ່ງຫາ SIM. ສິ່ງນີ້ອັນຕະລາຍຫຼາຍ." "ຖ່າຍຮູບ ແລະວິດີໂອ" "ອະນຸຍາດໃຫ້ແອັບຯຖ່າຍຮູບ ແລະວິດີໂອດ້ວຍກ້ອງຖ່າຍຮູບ. ການອະນຸຍາດນີ້ຈະອານຸຍາດໃຫ້ແອັບຯ ສາມາດໃຊ້ກ້ອງຖ່າຍຮູບໄດ້ຕະຫລອດເວລາ ໂດຍບໍ່ຕ້ອງຖ້າການຢືນຢັນຈາກທ່ານ." @@ -382,7 +382,7 @@ "ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ດຶງຂໍ້ມູນລາຍຊື່ຂອງບັນຊີທີ່ໂທລະສັບມີ ເຊິ່ງອາດຮວມເຖິງບັນຊີທີ່ໃດໆທີ່ສ້າງຂຶ້ນ ໂດຍແອັບພລິເຄຊັນທີ່ທ່ານຕິດຕັ້ງໄວ້." "ເບິ່ງການເຊື່ອມຕໍ່ເຄືອຂ່າຍ" "ອະນຸຍາດໃຫ້ແອັບຯ ເບິ່ງຂໍ້ມູນກ່ຽວກັບການເຊື່ອມຕໍ່ເຄືອຂ່າຍ ເຊັ່ນວ່າມີເຄືອຂ່າຍໃດແດ່ ແລະໄດ້ເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍໃດ." - "ເຂົ້າເຖິງເຄືອຂ່າຍເຕັມຮູບແບບ" + "ມີ​ການເຂົ້າເຖິງເຄືອຂ່າຍເຕັມຮູບແບບ" "ອະນຸຍາດໃຫ້ແອັບຯສ້າງຊັອກເກັດເຄືອຂ່າຍ ແລະໂປຣໂຕຄອນເຄືອຂ່າຍແບບກຳນົດເອງ. ໂປຣແກຣມທ່ອງເວັບ ແລະແອັບພລິເຄຊັນອື່ນໆຈະສົ່ງຂໍ້ມູນສູ່ອິນເຕີເນັດຢູ່ແລ້ວ ດັ່ງນັ້ນການອະນຸຍາດນີ້ຈຶ່ງບໍ່ຈຳເປັນຕ້ອງໃຊ້ ເພື່ອສົ່ງຂໍ້ມູນສູ່ອິນເຕີເນັດ." "ປ່ຽນການເຊື່ອມຕໍ່ເຄືອຂ່າຍ" "ອະນຸຍາດໃຫ້ແອັບຯປ່ຽນສະຖານະການເຊື່ອມຕໍ່ຂອງເຄືອຂ່າຍໄດ້." @@ -402,7 +402,7 @@ "ອະນຸຍາດໃຫ້ແອັບຯຕັ້ງຄ່າ Bluetooth ໃນໂທລະສັບ ເພື່ອຊອກຫາ ແລະການເຊື່ອມຕໍ່ກັບອຸປະກອນໄຮ້ສາຍພາຍນອກ." "ເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ຈາກ WiMAX" "ອະນຸຍາດໃຫ້ແອັບຯກວດເບິ່ງວ່າ WiMAX ຖືກເປີດນຳໃຊ້ຢູ່ບໍ່ ແລະຂໍ້ມູນກ່ຽວກັບເຄືອຂ່າຍ WiMAX ອື່ນໆທີ່ກຳລັງເຊື່ອມຕໍ່ຢູ່." - "ປ່ຽນສະຖານະ WiMAX" + "ປ່ຽນສະຖານະ WiMAX" "ອະນຸຍາດໃຫ້ແອັບຯເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ແທັບເລັດຈາກເຄືອຂ່າຍ WiMAX." "ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ເຊື່ອມ​ຕໍ່​ໂທລະພາບກັບ ແລະ​ຕັດ​ເຊື່ອມ​ຕໍ່ໂທລະພາບຈາກ​ເຄືອ​ຂ່າຍ WiMAX." "ອະນຸຍາດໃຫ້ແອັບຯເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ຂອງໂທລະສັບຈາກເຄືອຂ່າຍ WiMax ໄດ້." @@ -485,7 +485,7 @@ "ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ແກ້​ໄຂ​ຄ່າ​ການວັດ​ແທ້​ໜ້າ​ຈ​ໍ​ສຳ​ຜັດ. ​ແອັບຯ​ທຳ​ມະ​ດາບໍ່​ຄວນ​ໃຊ້." "ເຂົ້າ​ເຖິງ​ໃບຮັບຮອງ DRM" "ອະນຸຍາດ​ໃຫ້​ແອັບພລິເຄຊັນ​ຈັດຫາ ແລະ​ນຳໃຊ້​ໃບຮັບຮອງ DRM. ແອັບຯ​ທຳມະດາ​ບໍ່​ຄວນ​ຕ້ອງ​ການ​ໃຊ້." - "ຮັບ​ສະ​ຖາ​ນະ​ການ​ໂອນ​ຂໍ້​ມູນ Android Beam" + "ຮັບ​ສະ​ຖາ​ນະ​ການ​ໂອນ​ຂໍ້​ມູນ Android Beam" "ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພລິ​ເຄ​ຊັນ​ນີ້​ຮັບ​ຂໍ້​ມູນ​ກ່ຽວ​ກັບ​ການ​ໂອນ​ຂໍ້​ມູນ Android Beam ໃນ​ປັດ​ຈຸ​ບັນ" "ລຶບ​ໃບ​ຮັບ​ຮອງ DRM" "ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພລິ​ເຄ​ຊັນ​ລຶບ​ໃບ​ຮັບ​ຮອງ DRM. ແອັບຯ​ທົ່ວ​ໄປ​ບໍ່​ຄວນ​ຈຳ​ເປັນ​ຕ້ອງ​ໃຊ້." @@ -1091,11 +1091,11 @@ "ກຳລັງຟໍແມັດ…" "ບໍ່ແຊກໃສ່" "ບໍ່ພົບກິດຈະກຳທີ່ກົງກັນ." - "ກຳນົດເສັ້ນທາງເອົ້າພຸດຂອງສື່" + "ກຳນົດຊ່ອງທາງອອກຂອງສື່" "ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ກຳນົດເສັ້ນທາງເອົ້າພຸດຂອງສື່ໄປຫາອຸປະກອນພາຍນອກອື່ນໆ." - "ອ່ານ​ເຊດ​ຊັນ​ການ​ຕິດ​ຕັ້ງ" + "ອ່ານ​ເຊສ​ຊັນ​ການ​ຕິດ​ຕັ້ງ" "​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພລິ​ເຄ​ຊັນ​ອ່ານ​ເຊດ​ຊັນ​ການ​ຕິດ​ຕັ້ງ​ໄດ້. ນີ້​ຈະ​ອະ​ນຸ​ຍາດ​ໃຫ້​ມັນ​ເບິ່ງ​ເຫັນ​ລາຍ​ລະ​ອຽດ​ກ່ຽວ​ກັບ​ການ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ​ທີ່​ເຮັດ​​ວຽກ​ຢູ່​ໄດ້." - "ຂໍ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ" + "ຂໍ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ" "ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ຂອງ​ການ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ." "ແຕະສອງເທື່ອສຳລັບການຄວບຄຸມການຊູມ" "ບໍ່ສາມາດເພີ່ມວິດເຈັດໄດ້." diff --git a/core/res/res/values-lt-watch/strings.xml b/core/res/res/values-lt-watch/strings.xml index ed8ccdb7b0d30..e7c66fd219b1f 100644 --- a/core/res/res/values-lt-watch/strings.xml +++ b/core/res/res/values-lt-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d programa iš %2$d." + "Jutikliai" diff --git a/core/res/res/values-lt/cm_strings.xml b/core/res/res/values-lt/cm_strings.xml new file mode 100644 index 0000000000000..d30676fe0a595 --- /dev/null +++ b/core/res/res/values-lt/cm_strings.xml @@ -0,0 +1,170 @@ + + + + + + Ekrano kopija + + gauti apsaugotus SMS + + Leidžia programai gauti įeinančius apsaugotus SMS. + + keisti apsaugotų SMS sąrašą + + Leidžia programai keisti apsaugotų SMS adresų sąrašą. + + Sauga + + Leidimai susiję su įrenginio saugumo informacija. + + skaityti telefono juodąjį sąrašą + + Leidžia programai skaityti informaciją apie telefono numerius kurie yra užblokuoti dėl įeinančių skambučių ar pranešimų. + + pakeisti telefono juodąjį sąrašą + + Leidžia programai keisti telefono numerius kurie yra užblokuoti dėl įeinančių skambučių ar pranešimų. + + nustatyti klaviatūros apsaugos foną + + Leidžia programai pakeisti ekrano užrakto foną. + + Paleisti iš naujo + + Dabartinis + + + Paleisti iš naujo + + Atkūrimo režimas + + Bootloader + + Atsisiuntimo režimas + + Paleisti iš naujo OS + + Paleisti iš naujo + + Jūsų planšetinis kompiuteris bus paleistas iš naujo. + Jūsų telefonas bus paleistas iš naujo. + + Paleidžiama iš naujo\u2026 + + Programa priverstinai uždaryta + + USB derinimas per tinklą įgalintas + + USB derinimas per USB ir tinklą įgalintas + + Palieskite, kad neleistumėte derinimo. + + ADB - %1$s + USB ir tinklas + USB + Tinklas + + perimti programos paleidimą + + %s neįdiegta + + Prioritetas + Joks + + Wi-Fi saitvietė išjungta dėl SIM prenumeratos kaitos + + Išjunkite „Wi-Fi“ + + įgalinti arba neleisti privatumo saugos + Leisti programai keisti, kai kita programa veikia su privatumo sauga. Kai programa veikia su privatumo sauga ji neturės prieigos prie asmeninių duomenų pvz., kontaktų, skambučių žurnalų ar pranešimų. + Privatumo sauga aktyvi + %1$s negalės prieiti prie asmeninių duomenų + Privatumo sauga + %1$s norėtu %2$s. + + Prisiminti mano pasirinkimą + + pasiekti fotoaparatą + pasiekti jūsų vietą + skaityti jūsų pranešimus + suaktyvinti VPN + paleisti įsijungiant + Ištrinti jūsų skambučių žurnalą + Ištrinti jūsų kontaktus + Ištrinti jūsų MMS pranešimus + Ištrinti jūsų SMS pranešimus + Piešti langus viršuje + gauti programos naudojimo statistiką + laikyti jūsų įrenginį pabudusį + skambinti + atnaujinti jūsų kalendorių + atnaujinti skambučių žurnalą + keisti iškarpinę + atnaujinti jūsų kontaktus + atnaujinti sistemos nustatymus + nutildyti / įjungti mikrofoną + leisti garso įrašą + rašyti pranešimą + medijos projektas + skaityti jūsų kalendorių + skaityti skambučių žurnalą + skaityti iškarpinę + skaityti jūsų kontaktus + skaityti jūsų MMS pranešimus + skaityti jūsų SMS pranešimus + gauti SMS pranešimą + įrašyti garso įrašą + siųsti MMS pranešimą + siųsti SMS pranešimą + paleisti įsijungiant + Rodyti informacinius pranešimus + įjungti „Bluetooth“ + Įjungti / išjungti NFC + valdyti signalo garsumą + valdyti garso sutelktį + valdyti „Bluetooth“ garsumą + valdyti pagrindinį garsumą + naudoti medijos mygtukus + valdyti medijos garsumą + valdyti pranešimo garsumą + valdyti skambėjimo garsumą + naudoti liečiamuosius atsiliepimus + valdyti balso skambučio garsumą + rašyti MMS pranešimą + rašyti SMS pranešimą + gauti „Root“ prieigą + + Kad atsegtumėte šį ekraną palieskite ir laikykite mygtuką atgal. + + Nėra prijungto įrenginio + %1$s prijungtas įrenginys + %1$s prijungti įrenginiai + + + + + + Nustatyti iš naujo akumuliatoriaus statistiką + + Leidžia programai nustatyti iš naujo dabartinio žemo lygio akumuliatoriaus naudojimo duomenis. + + diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 19f54ffde9f91..fa4acd9dd31b3 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -256,7 +256,7 @@ "Įtraukiami asmeniniai duomenys, pavyzdžiui, kredito kortelių numeriai ir slaptažodžiai." "išjungti ar keisti būsenos juostą" "Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas." - "būsenos juosta" + "būti būsenos juosta" "Leidžiama programai būti būsenos juosta." "išskleisti / sutraukti būsenos juostą" "Leidžiama programai išskleisti arba sutraukti būsenos juostą." @@ -284,7 +284,7 @@ "Leidžiama programai gauti ir apdoroti WAP pranešimus. Šis leidimas apima galimybę stebėti ar ištrinti jums siunčiamus pranešimus jums jų neparodžius." "nuskaityti vykdomas programas" "Leidžiama programai nuskaityti informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Taip programa gali atrasti informacijos, kokios programos naudojamos įrenginyje." - "Tvarkyti profilio ir įrenginio savininkus" + "tvarkyti profilio ir įrenginio savininkus" "Leisti programai nustatyti profilio savininkus ir įrenginio savininką." "pertvarkyti vykdomas programas" "Leidžiama programai perkelti užduotis į priekinį planą ir foną. Programa gali tai daryti be jūsų įsikišimo." @@ -326,7 +326,7 @@ "Programai leidžiama skaityti planšetinio kompiuterio skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Kenkėjiškos programos tai gali naudoti, kad ištrintų ar keistų jūsų skambučių žurnalą." "Programai leidžiama keisti TV skambučių žurnalą, įskaitant duomenis apie gaunamus ir siunčiamus skambučius. Taip kenkėjiškos programos gali ištrinti arba pakeisti skambučių žurnalą." "Programai leidžiama skaityti telefono skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Kenkėjiškos programos tai gali naudoti, kad ištrintų ar keistų jūsų skambučių žurnalą." - "kūno jut. (pvz., pulso d. t.)" + "pas. k. jut. (pvz., pul. dažn. st. įr.)" "Programai leidžiama pasiekti duomenis, gautus iš jutiklių, stebinčių fizinę būseną, pvz., širdies ritmą." "nuskaito kalendoriaus įvykius ir konfidencialią informaciją" "Leidžiama programai skaityti visus planšetiniame kompiuteryje išsaugotus kalendoriaus įvykius, įskaitant draugų ar bendradarbių įvykius. Dėl to programai gali būti leidžiama bendrinti ar saugoti kalendoriaus duomenis, neatsižvelgiant į konfidencialumą ar privatumą." @@ -338,15 +338,15 @@ "Leidžiama programai pridėti, pašalinti ir keisti įvykius, kuriuos galite keisti telefone, įskaitant draugų ir bendradarbių įvykius. Dėl to programa gali siųsti pranešimus, kurie atrodo lyg būtų siunčiami kalendorių savininkų, arba keisti įvykius be savininko žinios." "pasiekti papildomas vietos teikimo įrankio komandas" "Programai leidžiama pasiekti papildomas vietovės nustatymo paslaugų teikėjų komandas. Dėl to programa gali trukdyti veikti GPS ar kitiems vietovės nustatymo šaltiniams." - "tiksli vieta (pagrįsta pagal GPS ir tinklą)" + "pasiekti tikslią vietą (nustatytą atsižvelgiant į GPS ir tinklą)" "Leidžiama programai gauti jūsų tikslią vietą naudojant visuotinę vietos nustatymo sistemą (angl. „Global Positioning System“, GPS) arba tinklo vietos šaltinius, pvz., mobiliojo ryšio bokštus ir „Wi-Fi“. Šios vietos paslaugos turi būti įjungtos ir pasiekiamos įrenginyje, kad programa galėtų jas naudoti. Programos gali tai naudoti jūsų vietai nustatyti bei eikvoti papildomą akumuliatoriaus energiją." - "apytikslė vieta (pagrįsta pagal tinklą)" + "pasiekti apytikslę vietą (nustatytą atsižvelgiant į tinklą)" "Leidžiama programai gauti jūsų apytikslę vietą. Ši vieta gaunama vietos paslaugų naudojant tinklo vietos šaltinius, pvz., mobiliojo ryšio bokštus ir „Wi-Fi“. Šios vietos paslaugos turi būti įjungtos ir pasiekiamos įrenginyje, kad programa galėtų jas naudoti. Programos gali tai naudoti jūsų apytikslei vietai nustatyti." "keisti garso nustatymus" "Leidžiama programai keisti visuotinius garso nustatymus, pvz., garsumą ir tai, kuris garsiakalbis naudojamas išvesčiai." "įrašyti garsą" "Leidžiama programai įrašyti garsą naudojant mikrofoną. Šis leidimas suteikia galimybę programai įrašyti garsą bet kada be jūsų patvirtinimo." - "SIM kortelės ryšys" + "siųsti komandas į SIM kortelę" "Programai leidžiama siųsti komandas į SIM kortelę. Tai labai pavojinga." "fotografuoti ir filmuoti" "Leidžiama programai fotografuoti ir filmuoti kamera. Šis leidimas suteikia teisę programai naudoti kamerą bet kada be jūsų patvirtinimo." @@ -384,7 +384,7 @@ "Leidžiama programai gauti telefono žinomų paskyrų sąrašą. Gali būti įtrauktos visos paskyros, sukurtos įdiegtomis programomis." "žiūrėti tinklo ryšius" "Leidžiama programai peržiūrėti informaciją apie tinklo ryšius, pvz., kurie tinklai pasiekiami ir prijungti." - "visateisė tinklo prieiga" + "turėti visateisę tinklo prieigą" "Leidžiama programai kurti tinklo programines jungtis ir naudoti tinkintus tinklo protokolus. Naršyklė ir kitos programos teikia priemones siųsti duomenis į internetą, todėl norint siųsti duomenis į internetą šis leidimas nebūtinas." "keisti tinklo jungiamumą" "Leidžiama programai keisti tinklo jungiamumo būseną." @@ -404,7 +404,7 @@ "Leidžiama programai konfigūruoti vietinį „Bluetooth“ telefoną ir atrasti bei susieti su nuotoliniais įrenginiais." "prisijungti prie WiMAX ir atsijungti nuo jo" "Leidžiama programai nustatyti, ar įgalintas „WiMAX“, ir informaciją apie visus prijungtus tinklus." - "Keisti „WiMAX“ būseną" + "keisti „WiMAX“ būseną" "Leidžia programai prijungti planšetinį kompiuterį prie „WiMAX“ ryšio tinklų ir nuo jų atjungti." "Programai leidžiama prijungti TV prie „WiMAX“ tinklų ir atjungti nuo jų." "Leidžia programai prijungti telefoną prie „WiMAX“ ryšio tinklų ir nuo jų atjungti." @@ -487,7 +487,7 @@ "Leidžiama programai keisti jutiklinio ekrano kalibravimo parametrus. Neturėtų prireikti naudojant įprastas programas." "gali pasiekti DRM sertifikatus" "Programai leidžiama pasiekti ir naudoti DRM sertifikatus. Neturėtų prireikti naudojant įprastas programas." - "Gauti „Android“ perdavimo funkcijos perkėlimo būseną" + "gauti „Android“ perdavimo funkcijos perkėlimo būseną" "Programai leidžiama gauti informaciją apie dabartinius „Android“ perdavimo funkcijos perkėlimus" "pašalinti DRM sertifikatus" "Programai leidžiama pašalinti DRM sertifikatus. Neturėtų prireikti naudojant įprastas programas." @@ -1105,11 +1105,11 @@ "Formatuojama…" "Neįdėta" "Nerasta atitinkančios veiklos." - "Medijos išvesties nukreipimas" + "nukreipti medijos išvestį" "Leidžiama programai nukreipti medijos išvestį į kitus išorinius įrenginius." - "Skaityti diegimo seansus" + "skaityti diegimo sesijas" "Leidžiama programai skaityti diegimo seansus. Leidžiama peržiūrėti išsamią aktyvių paketų diegimo informaciją." - "Pateikti užklausą dėl paketų diegimo" + "pateikti užklausą dėl diegimo paketų" "Programai leidžiama pateikti užklausą dėl paketų diegimo." "Dukart palieskite, kad valdytumėte mastelio keitimą" "Nepavyko pridėti." diff --git a/core/res/res/values-lv-watch/strings.xml b/core/res/res/values-lv-watch/strings.xml index a0d051e4a2a52..eb3c9b0c89837 100644 --- a/core/res/res/values-lv-watch/strings.xml +++ b/core/res/res/values-lv-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d. lietotne no %2$d." + "Sensori" diff --git a/core/res/res/values-lv/cm_strings.xml b/core/res/res/values-lv/cm_strings.xml new file mode 100644 index 0000000000000..feda39b0b7f1b --- /dev/null +++ b/core/res/res/values-lv/cm_strings.xml @@ -0,0 +1,155 @@ + + + + + + Ekrānattēls + + saņemt aizsargātu īsziņu + + Ļauj lietotnēm saņemt aizsargātu ienākošo īsziņu. + + mainīt aizsargāto īsziņu sarakstu + + Ļauj lietotnei mainīt aizsargāto īsziņu adrešu sarakstu. + + Drošība + + Atļaujas saistītas ar iekārtas drošības informāciju. + + lasīt telefona melno sarakstu + + Ļauj lietotnei lasīt informāciju par bloķētajiem ienākošo zvanu un ziņu telefona numuriem. + + mainīt telefona melno sarakstu + + Ļauj lietotnei mainīt bloķēto saņemto zvanu vai īsziņu telefona numurus. + + iestatīt taustiņslēga tapeti + + Ļauj lietotnei manīt slēgekrāna tapeti. + + Pārsāknēt + + + + Pārsāknēt + + Atjaunošana + + Sāknētājs + + Lejuplādēt + + Programmātiskā pārsāknēšana + + Restartēt + + Jūsu planšete pārsāknēsies. + Jūsu telefons pārsāknēsies. + + Pārsāknē\u2026 + + Lietotne izbeigta + + ADB pa tīklu ieslēgts + + ADB pa USB & tīklu ieslēgts + + Pieskarieties, lai atslēgtu atkļūdošanu. + + + + + + + + Ieslēgt vai atslēgt Privātuma sargu + Ļauj lietotnei mainīties pat ja cita lietotne lieto Privātuma Sargu. Kad lietotne darbojas ar privātuma sargu, tai nebūs pieejas personīgajiem datiem, kā kontakti, zvanu saraksts, vai īsziņas. + Privātuma Sargs ir aktīvs + %1$s nevarēs piekļūt personīgajiem datiem + Privātuma sargs + %1$s vēlētos %2$s . + + Atcerēties manu izvēli + + piekļuve kamerai + piekļeve jūsu atrašanās vietai + lasīt jūsu ziņas + aktivizēt VPN + palaist pēc ieslēgšanas + izdzēst zvanu žurnālu + dzēst jūsu kontaktus + dzēst jūsu MMS ziņas + dzēst jūsu SMS īsziņas + radīt logus pa virsu + saņemt lietotnes lietošanas statistiku + turēt iekārtu nomodā + zvanīt pa telefonu + atjaunot kalendāru + atjaunot zvanu žurnālu + mainīt starpliktuvi + atjaunot kontaktus + atjaunot sistēmas iestatījumus + izslēgt/ieslēgt mikrofonu + atskaņot audio failus + sūtīt ziņas + medija projekts + lasīt jūsu kalendāru + lasīt zvanu žurnālu + lasīt starpliktuvi + lasīt jūsu kontaktus + lasīt jūsu multivides ziņas + lasīt jūsu īsziņas + saņemt īsziņas + ierakstīt audio + sūtīt multiziņu + sūtīt īsziņu + palaist pēc ieslēgšanas + ieslēgt Bluetooth + pārslēgt NFC + regulēt trauksmes skaļumu + regulēt audio fokusu + regulēt Bluetooth skaļumu + regulēt galveno skaļumu + lietot multivides pogas + regulēt multivides skaļumu + regulēt ziņojumu skaļumu + regulēt zvana skaļumu + lietot vibrāciju atgriezeniskai saitei + regulēt balss zvana skaļumu + rakstīt multivides ziņu + rakstīt īsziņu + saņemt root piekļuvi + + + Nav pievienota ierīce + %1$s pievienota ierīce + %1$s pievienotas ierīces + + + + + + + + diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 54a857501df36..f22358def62f1 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -255,7 +255,7 @@ "Ietver personas datus, piemēram, kredītkartes numurus un paroles." "atspējot vai pārveidot statusa joslu" "Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas." - "statusa josla" + "Būt par statusa joslu" "Ļauj lietotnei būt par statusa joslu." "izvērst/sakļaut statusa joslu" "Ļauj lietotnei izvērst vai sakļaut statusa joslu." @@ -283,7 +283,7 @@ "Ļauj lietotnei saņemt un apstrādāt WAP ziņojumus. Šī atļauja ietver iespēju pārraudzīt vai dzēst jums nosūtītos ziņojumus, neparādot tos jums." "izgūt izmantotās lietotnes" "Ļauj lietotnei izgūt informāciju par pašreiz un nesen darbinātajiem uzdevumiem. Tādējādi lietotne var atklāt informāciju par ierīcē izmantotajām lietojumprogrammām." - "Profilu un ierīces īpašnieku pārvaldība" + "Pārvaldīt profilus un ierīces īpašniekus" "Atļaut lietotnēm iestatīt profilu īpašniekus un ierīces īpašnieku." "pārkārtot izmantotās lietotnes" "Ļauj lietotnei pārvietot uzdevumus priekšplānā un fonā. Lietotne var to izdarīt bez jūsu apstiprinājuma." @@ -325,7 +325,7 @@ "Ļauj lietotnei pārveidot planšetdatora zvanu žurnālu, tostarp ienākošo un izejošo zvanu datus. Ļaunprātīgas lietotnes var to izmantot, lai dzēstu vai pārveidotu savu zvanu žurnālu." "Ļauj lietotnei pārveidot televizora zvanu žurnālu, tostarp ienākošo un izejošo zvanu datus. Ļaunprātīgas lietotnes var to izmantot, lai dzēstu vai pārveidotu zvanu žurnālu." "Ļauj lietotnei pārveidot tālruņa zvanu žurnālu, tostarp ienākošo un izejošo zvanu datus. Ļaunprātīgas lietotnes var to izmantot, lai dzēstu vai pārveidotu savu zvanu žurnālu." - "ķermeņa sensori (piemēram, sirdsdarbības monitori)" + "Piekļūt ķermeņa sensoriem (piemēram, sirdsdarbības monitoriem)" "Ļauj lietotnei piekļūt to sensoru datiem, kuri pārrauga jūsu fizisko stāvokli (piemēram, sirdsdarbības ātrumu)." "lasīt kalendāra pasākumus un konfidenciālu informāciju" "Ļauj lietotnei lasīt visus planšetdatorā saglabātos kalendāra notikumus, tostarp draugu vai kolēģu notikumus. Tas var ļaut lietotnei kopīgot vai saglabāt jūsu kalendāra datus, neraugoties uz to konfidencialitāti vai sensitivitāti." @@ -337,15 +337,15 @@ "Ļauj lietotnei pievienot, noņemt, mainīt notikumus, kurus varat pārveidot tālrunī, tostarp draugu vai kolēģu notikumus. Tas var ļaut lietotnei sūtīt ziņojumus, norādot, ka tos sūta kalendāru īpašnieki, vai pārveidot notikumus bez īpašnieka atļaujas." "piekļūt atrašanās vietas nodrošinātāja papildu komandām" "Ļauj lietotnei piekļūt papildu atrašanās vietas noteikšanas nodrošinātāju komandām. Tas var ļaut lietotnei traucēt GPS vai citu atrašanās vietas noteikšanas avotu darbību." - "precīza atrašanās vieta (GPS un tīklā)" + "Piekļūt precīzai atrašanās vietai (izmantojot GPS un tīklu)" "Ļauj lietotnei iegūt precīzu informāciju par jūsu atrašanās vietu, izmantojot globālo pozicionēšanas sistēmu (GPS) vai tīkla atrašanās vietas pakalpojumus, piemēram, mobilo sakaru torņus un Wi-Fi. Lai lietotne varētu izmantot šos atrašanās vietas pakalpojumus, ierīcē tiem ir jābūt ieslēgtiem un pieejamiem. Lietotnes var izmantot šo atļauju, lai noteiktu jūsu atrašanās vietu, un var patērēt papildu akumulatora enerģiju." - "aptuvena atrašanās vieta (tīklā)" + "Piekļūt aptuvenai atrašanās vietai (izmantojot tīklu)" "Ļauj lietotnei iegūt informāciju par aptuvenu jūsu atrašanās vietu. Tā tiek noteikta atrašanās vietas pakalpojumos, izmantojot tīkla atrašanās vietas avotus, kā arī mobilo sakaru torņus un Wi-Fi. Lai lietotne varētu izmantot šos atrašanās vietas pakalpojumus, ierīcē tiem ir jābūt ieslēgtiem un pieejamiem. Lietotnes var izmantot šo atļauju, lai noteiktu aptuvenu jūsu atrašanās vietu." "mainīt audio iestatījumus" "Ļauj lietotnei mainīt globālos audio iestatījumus, piemēram, skaļumu un izejai izmantoto skaļruni." "ierakstīt audio" "Ļauj lietotnei ierakstīt audio, izmantojot mikrofonu. Šī atļauja ļauj lietotnei ierakstīt audio jebkurā brīdī bez jūsu apstiprinājuma." - "SIM saziņa" + "Sūtīt komandas SIM kartei" "Ļauj lietotnei sūtīt komandas uz SIM karti. Tas ir ļoti bīstami!" "uzņemt attēlus un videoklipus" "Ļauj lietotnei uzņemt attēlus un videoklipus ar kameru. Ar šo atļauju lietotne var jebkurā brīdī izmantot kameru bez jūsu apstiprinājuma." @@ -383,7 +383,7 @@ "Ļauj lietotnei iegūt tālrunim zināmo kontu sarakstu. Tas var ietvert jebkādus kontus, ko izveidojušas instalētās lietojumprogrammas." "skatīt tīkla savienojumus" "Ļauj lietotnei skatīt informāciju par tīkla savienojumiem, piemēram, par to, kādi tīkli pastāv un ar kuriem tīkliem ir izveidots savienojums." - "pilnīga piekļuve tīklam" + "Iegūt pilnu piekļuvi tīklam" "Ļauj lietotnei izveidot tīkla ligzdas un izmantot pielāgotus tīkla protokolus. Pārlūkprogramma un citas lietojumprogrammas nodrošina līdzekļus, kas nepieciešami, lai sūtītu datus internetā, tāpēc šī atļauja nav nepieciešama, lai sūtītu datus internetā." "mainīt tīkla savienojamību" "Ļauj lietotnei mainīt tīkla savienojamības statusu." @@ -403,7 +403,7 @@ "Ļauj lietotnei konfigurēt vietējo Bluetooth tālruni, kā arī atklāt attālas ierīces un savienot tās pārī." "WiMAX savienojuma izveide un pārtraukšana" "Ļauj lietotnei noteikt, vai WiMAX ir iespējots, un sniedz informāciju par visiem WiMAX tīkliem, ar kuriem ir izveidots savienojums." - "WiMAX statusa mainīšana" + "WiMAX statusa mainīšana" "Ļauj lietotnei izveidot un pārtraukt planšetdatora savienojumu ar WiMAX tīkliem." "Ļauj lietotnei pievienot televizoru WiMAX tīkliem un atvienot no tiem." "Ļauj lietotnei izveidot un pārtraukt tālruņa savienojumu ar WiMAX tīkliem." @@ -486,7 +486,7 @@ "Ļauj lietotnei pārveidot skārienekrāna kalibrēšanas parametrus. Parastām lietotnēm šī atļauja nekad nav nepieciešama." "Piekļuve digitālā satura tiesību pārvaldības sertifikātiem" "Ļauj lietojumprogrammai nodrošināt un izmantot digitālā satura tiesību pārvaldības sertifikātus. Parastām lietotnēm šī atļauja nekad nav nepieciešama." - "Saņemt Android Beam pārsūtīšanas statusu" + "Saņemt Android Beam pārsūtīšanas statusu" "Ļauj šai lietojumprogrammai saņemt informāciju par pašreizēju Android Beam pārsūtīšanu" "noņemt DRM sertifikātus" "Ļauj lietojumprogrammai noņemt DRM sertifikātus. Parastās lietotnēs tas nebūs nepieciešams." @@ -1098,11 +1098,11 @@ "Notiek formatēšana…" "Nav ievietots" "Nav atrasta neviena atbilstoša darbība." - "Multivides datu izejas maršrutēšana" + "Maršrutēt multivides datu izeju" "Ļauj lietojumprogrammai maršrutēt multivides datu izeju uz citām ārējām ierīcēm." - "Instalēšanas sesiju lasīšana" + "Lasīt instalēšanas sesijas" "Ļauj lietojumprogrammai lasīt instalēšanas sesijas. Tādējādi lietojumprogrammai ir pieejama informācija par aktīvajām pakotņu instalācijām." - "Pieprasīt pakotņu instalēšanu" + "Pieprasīt pakotņu instalēšanu" "Ļauj lietojumprogrammai pieprasīt pakotņu instalēšanu." "Pieskarieties divreiz, lai kontrolētu tālummaiņu." "Nevarēja pievienot logrīku." diff --git a/core/res/res/values-mcc208-mnc01/config.xml b/core/res/res/values-mcc208-mnc01/config.xml index c56da24a92818..5930e3aa7a12c 100644 --- a/core/res/res/values-mcc208-mnc01/config.xml +++ b/core/res/res/values-mcc208-mnc01/config.xml @@ -28,9 +28,6 @@ note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" --> Orange Internet,orange.fr,,,orange,orange,,,,,208,01,1,DUN - [ApnSettingV3]Carrefour WAP,ofnew.fr,,,orange,orange,,,,,208,01,1,DUN,,,true,0,,,,,,,gid,33 - [ApnSettingV3]VM WAP,ofnew.fr,,,orange,orange,,,,,208,01,1,DUN,,,true,0,,,,,,,gid,52 - [ApnSettingV3]NRJWEB,ofnew.fr,,,orange,orange,,,,,208,01,1,DUN,,,true,0,,,,,,,gid,4E diff --git a/core/res/res/values-mcc208-mnc10/config.xml b/core/res/res/values-mcc208-mnc10/config.xml index a32f266214270..d3640e5c41537 100644 --- a/core/res/res/values-mcc208-mnc10/config.xml +++ b/core/res/res/values-mcc208-mnc10/config.xml @@ -29,11 +29,6 @@ SFR option modem,websfr,,,,,,,,,208,10,,DUN [ApnSettingV3]INTERNET NRJ,internetnrj,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,gid,4E - [ApnSettingV3]Auchan,wap65,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,spn,A MOBILE - [ApnSettingV3]LeclercMobile,wap66,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,spn,LeclercMobile - [ApnSettingV3]Coriolis,fnetcoriolis,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,gid,12 - [ApnSettingV3]WEB La Poste Mobile,wapdebitel,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,gid,4C - [ApnSettingV3]Darty Surf Mails,wap68,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,gid,44 diff --git a/core/res/res/values-mcc214-mnc07/config.xml b/core/res/res/values-mcc214-mnc07/config.xml index 91571a54df17b..21d9bf77337e0 100644 --- a/core/res/res/values-mcc214-mnc07/config.xml +++ b/core/res/res/values-mcc214-mnc07/config.xml @@ -28,7 +28,34 @@ note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" --> Conexión Compartida,movistar.es,,,MOVISTAR,MOVISTAR,,,,,214,07,1,DUN - [ApnSettingV3]Jazztel Internet,jazzinternet,,,,,,,,,214,07,,DUN,,,true,0,,,,,,,spn,JAZZTEL + + + + 2 + diff --git a/core/res/res/values-mcc222-mnc10/config.xml b/core/res/res/values-mcc222-mnc10/config.xml index 5a74462e5c551..cd6e8c6f46c2e 100644 --- a/core/res/res/values-mcc222-mnc10/config.xml +++ b/core/res/res/values-mcc222-mnc10/config.xml @@ -20,16 +20,6 @@ - - - - 1 - 4 - 7 - 9 - - - - - - 1 - 4 - 7 - 9 - - - [ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,54 + [ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,IP,IP,true,0,,,,,,,gid,54 [ApnSettingV3]Tethered Mobile Internet,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,50 [ApnSettingV3]Tethered Public Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,4D4F diff --git a/core/res/res/values-mcc310-mnc160-af/strings.xml b/core/res/res/values-mcc310-mnc160-af/strings.xml new file mode 100644 index 0000000000000..72ca2f25abed9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-af/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Om oproepe te maak en boodskappe oor Wi-Fi te stuur, vra jou diensverskaffer eers om hierdie diens op te stel. Skakel Wi-Fi-oproepe dan weer in Instellings aan." + + + "Registreer by jou diensverskaffer" + + "%s Wi-Fi-oproep" + diff --git a/core/res/res/values-mcc310-mnc160-am/strings.xml b/core/res/res/values-mcc310-mnc160-am/strings.xml new file mode 100644 index 0000000000000..86b06512b6b0d --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-am/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "በWi-Fi ላይ ጥሪዎችን ለማድረግ እና መልዕክቶችን ለመላክ መጀመሪያ የአገልግሎት አቅራቢዎ ይህን አገልግሎት እንዲያዘጋጅልዎ መጠየቅ አለብዎት። ከዚያ ከቅንብሮች ሆነው እንደገና የWi-Fi ጥሪን ያብሩ።" + + + "የአገልግሎት አቅራቢዎ ጋር ይመዝገቡ" + + "የ%s Wi-Fi ጥሪ" + diff --git a/core/res/res/values-mcc310-mnc160-ar/strings.xml b/core/res/res/values-mcc310-mnc160-ar/strings.xml new file mode 100644 index 0000000000000..c0e42293ecf4b --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ar/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "‏لإجراء مكالمات وإرسال رسائل عبر Wi-Fi، اطلب من مشغّل شبكة الجوّال أولاً إعداد هذا الجهاز، ثم شغّل الاتصال عبر Wi-Fi مرة أخرى من خلال الإعدادات." + + + "التسجيل لدى مشغّل شبكة الجوّال" + + "‏%s جارٍ الاتصال عبر Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc260-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc160-az-rAZ/strings.xml similarity index 82% rename from core/res/res/values-mcc310-mnc260-az-rAZ/strings.xml rename to core/res/res/values-mcc310-mnc160-az-rAZ/strings.xml index 32d21c56fca55..0c250cdb10e23 100644 --- a/core/res/res/values-mcc310-mnc260-az-rAZ/strings.xml +++ b/core/res/res/values-mcc310-mnc160-az-rAZ/strings.xml @@ -1,7 +1,7 @@ + + + + + + "За да извършвате обаждания и да изпращате съобщения през Wi-Fi, първо помолете оператора си да настрои тази услуга. След това включете отново функцията за обаждания през Wi-Fi от настройките." + + + "Регистриране с оператора ви" + + "%s – обаждания през Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-bn-rBD/strings.xml b/core/res/res/values-mcc310-mnc160-bn-rBD/strings.xml new file mode 100644 index 0000000000000..0c3e816c77a3b --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-bn-rBD/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi এর মাধ্যমে কল করতে ও বার্তা পাঠাতে, প্রথমে আপনার পরিষেবা প্রদানকারীকে এই পরিষেবার সেট আপ করার বিষয়ে জিজ্ঞাসা করুন। তারপরে আবার সেটিংস থেকে Wi-Fi কলিং চালু করুন।" + + + "আপনার পরিষেবা প্রদানকারীকে নথিভুক্ত করুন" + + "%s Wi-Fi কলিং" + diff --git a/core/res/res/values-mcc310-mnc160-ca/strings.xml b/core/res/res/values-mcc310-mnc160-ca/strings.xml new file mode 100644 index 0000000000000..5a989bfaee888 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ca/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Per fer trucades i enviar missatges per Wi-Fi, primer has de demanar a l\'operador de telefonia mòbil que configuri aquest servei. Després, torna a activar les trucades per Wi-Fi des de Configuració." + + + "Registra\'t amb el teu operador de telefonia mòbil" + + "Trucada de Wi-Fi de: %s" + diff --git a/core/res/res/values-mcc310-mnc160-cs/strings.xml b/core/res/res/values-mcc310-mnc160-cs/strings.xml new file mode 100644 index 0000000000000..3eb962ed2e5d7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-cs/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Chcete-li volat a odesílat textové zprávy přes síť Wi-Fi, nejprve požádejte operátora, aby vám tuto službu nastavil. Poté volání přes Wi-Fi opět zapněte v Nastavení." + + + "Registrace u operátora" + + "Volání přes Wi-Fi: %s" + diff --git a/core/res/res/values-mcc310-mnc160-da/strings.xml b/core/res/res/values-mcc310-mnc160-da/strings.xml new file mode 100644 index 0000000000000..8e401d8206eda --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-da/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Hvis du vil foretage opkald og sende beskeder via Wi-Fi, skal du først anmode dit mobilselskab om at konfigurere denne tjeneste. Derefter skal du slå Wi-Fi-opkald til igen fra Indstillinger." + + + "Registrer dig hos dit mobilselskab" + + "%s Wi-Fi-opkald" + diff --git a/core/res/res/values-mcc310-mnc160-de/strings.xml b/core/res/res/values-mcc310-mnc160-de/strings.xml new file mode 100644 index 0000000000000..7b172d836bb78 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-de/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Um über WLAN telefonieren und Nachrichten senden zu können, bitte zuerst deinen Mobilfunkanbieter, diesen Dienst einzurichten. Aktiviere die Option \"Anrufe über WLAN\" dann erneut über die Einstellungen." + + + "Registriere dich bei deinem Mobilfunkanbieter." + + "%s Anrufe über WLAN" + diff --git a/core/res/res/values-mcc310-mnc160-el/strings.xml b/core/res/res/values-mcc310-mnc160-el/strings.xml new file mode 100644 index 0000000000000..bfd09c0cde111 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-el/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Για να κάνετε κλήσεις και να στέλνετε μηνύματα μέσω Wi-Fi, ζητήστε πρώτα από την εταιρεία κινητής τηλεφωνίας να ρυθμίσει την υπηρεσία. Στη συνέχεια, ενεργοποιήστε ξανά τη λειτουργία κλήσεων μέσω Wi-Fi από τις Ρυθμίσεις." + + + "Εγγραφείτε μέσω της εταιρείας κινητής τηλεφωνίας" + + "%s Κλήση Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc160-en-rAU/strings.xml new file mode 100644 index 0000000000000..d4f59ed50ff1f --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-en-rAU/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings." + + + "Register with your operator" + + "%s Wi-Fi Calling" + diff --git a/core/res/res/values-mcc310-mnc160-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc160-en-rGB/strings.xml new file mode 100644 index 0000000000000..d4f59ed50ff1f --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-en-rGB/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings." + + + "Register with your operator" + + "%s Wi-Fi Calling" + diff --git a/core/res/res/values-mcc310-mnc160-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-en-rIN/strings.xml new file mode 100644 index 0000000000000..d4f59ed50ff1f --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-en-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings." + + + "Register with your operator" + + "%s Wi-Fi Calling" + diff --git a/core/res/res/values-mcc310-mnc160-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc160-es-rUS/strings.xml new file mode 100644 index 0000000000000..8930a3e0d0ba8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-es-rUS/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Para realizar llamadas o enviar mensajes por Wi-Fi, primero solicítale al proveedor que instale el servicio. Luego, vuelve a activar las llamadas por Wi-Fi desde Configuración." + + + "Regístrate con tu proveedor." + + "Llamada por Wi-Fi de %s" + diff --git a/core/res/res/values-mcc310-mnc160-es/strings.xml b/core/res/res/values-mcc310-mnc160-es/strings.xml new file mode 100644 index 0000000000000..1aac00b423ae3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-es/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Para hacer llamadas y enviar mensajes por Wi-Fi, debes pedir antes a tu operador que configure este servicio. Una vez hecho esto, vuelva a activar las llamadas Wi-Fi en Ajustes." + + + "Regístrate con tu operador" + + "Llamada Wi-Fi de %s" + diff --git a/core/res/res/values-mcc310-mnc160-et-rEE/strings.xml b/core/res/res/values-mcc310-mnc160-et-rEE/strings.xml new file mode 100644 index 0000000000000..f625e50ec9809 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-et-rEE/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Üle WiFi-võrgu helistamiseks ja sõnumite saatmiseks paluge operaatoril esmalt see teenus seadistada. Seejärel lülitage WiFi-kõned menüüs Seaded uuesti sisse." + + + "Registreeruge operaatori juures" + + "%s WiFi kaudu helistamine" + diff --git a/core/res/res/values-mcc310-mnc160-eu-rES/strings.xml b/core/res/res/values-mcc310-mnc160-eu-rES/strings.xml new file mode 100644 index 0000000000000..93c4026058097 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-eu-rES/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi bidez deiak egiteko eta mezuak bidaltzeko, eskatu operadoreari zerbitzu hori gaitzeko. Ondoren, aktibatu Wi-Fi bidezko deiak Ezarpenak atalean." + + + "Erregistratu operadorearekin" + + "%s Wi-Fi bidezko deiak" + diff --git a/core/res/res/values-mcc310-mnc160-fa/strings.xml b/core/res/res/values-mcc310-mnc160-fa/strings.xml new file mode 100644 index 0000000000000..247693a72a010 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-fa/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "‏برای برقراری تماس و ارسال پیام از طریق Wi-Fi، ابتدا از شرکت مخابراتی‌تان درخواست کنید این سرویس را راه‌اندازی کند. سپس دوباره از تنظیمات، تماس Wi-Fi را روشن کنید." + + + "ثبت نام با شرکت مخابراتی شما" + + "‏تماس ‪%s Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-fi/strings.xml b/core/res/res/values-mcc310-mnc160-fi/strings.xml new file mode 100644 index 0000000000000..aebdf71bf0683 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-fi/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Jos haluat soittaa puheluita ja lähettää viestejä Wi-Fin kautta, pyydä ensin operaattoriasi ottamaan tämä palvelu käyttöön. Ota sitten Wi-Fi-puhelut käyttöön asetuksissa." + + + "Rekisteröidy operaattorisi asiakkaaksi." + + "Wi-Fi-puhelut: %s" + diff --git a/core/res/res/values-mcc310-mnc160-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc160-fr-rCA/strings.xml new file mode 100644 index 0000000000000..b0d21c2ee8a25 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-fr-rCA/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Pour effectuer des appels et envoyer des messages par Wi-Fi, demandez tout d\'abord à votre fournisseur de services de configurer ce service. Réactivez ensuite les appels Wi-Fi dans les paramètres." + + + "Inscrivez-vous auprès de votre fournisseur de services" + + "Appels Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-fr/strings.xml b/core/res/res/values-mcc310-mnc160-fr/strings.xml new file mode 100644 index 0000000000000..9fe787c6acecc --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-fr/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Pour effectuer des appels et envoyer des messages via le Wi-Fi, demandez tout d\'abord à votre opérateur de configurer ce service. Réactivez ensuite les appels Wi-Fi dans les paramètres." + + + "Inscrivez-vous auprès de votre opérateur." + + "Appels Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-gl-rES/strings.xml b/core/res/res/values-mcc310-mnc160-gl-rES/strings.xml new file mode 100644 index 0000000000000..0d85bb879b581 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-gl-rES/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Para facer chamadas e enviar mensaxes a través da wifi, primeiro pídelle ao teu operador que configure este servizo. A continuación, activa de novo as chamadas wifi en Configuración." + + + "Rexístrate co teu operador" + + "Chamadas wifi de %s" + diff --git a/core/res/res/values-mcc310-mnc160-gu-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-gu-rIN/strings.xml new file mode 100644 index 0000000000000..e218ee6e0717a --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-gu-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi પર કૉલ્સ કરવા અને સંદેશા મોકલવા માટે, પહેલા તમારા કેરીઅરને આ સેવા સેટ કરવા માટે કહો. પછી સેટિંગ્સમાંથી Wi-Fi કૉલિંગ ચાલુ કરો." + + + "તમારા કેરીઅર સાથે નોંધણી કરો" + + "%s Wi-Fi કૉલિંગ" + diff --git a/core/res/res/values-mcc310-mnc160-hi/strings.xml b/core/res/res/values-mcc310-mnc160-hi/strings.xml new file mode 100644 index 0000000000000..23f4dc886aa14 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-hi/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें." + + + "अपने वाहक के साथ पंजीकृत करें" + + "%s वाई-फ़ाई कॉलिंग" + diff --git a/core/res/res/values-mcc310-mnc160-hr/strings.xml b/core/res/res/values-mcc310-mnc160-hr/strings.xml new file mode 100644 index 0000000000000..956093af1fdcb --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-hr/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Da biste telefonirali i slali pozive putem Wi-Fi-ja, morate tražiti od mobilnog operatera da vam postavi tu uslugu. Zatim ponovo uključite Wi-Fi pozive u Postavkama." + + + "Registrirajte se kod mobilnog operatera" + + "%s Wi-Fi pozivanje" + diff --git a/core/res/res/values-mcc310-mnc160-hu/strings.xml b/core/res/res/values-mcc310-mnc160-hu/strings.xml new file mode 100644 index 0000000000000..a42073f2f8216 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-hu/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Ha Wi-Fi-n szeretne telefonálni és üzenetet küldeni, kérje meg szolgáltatóját, hogy állítsa be ezt a szolgáltatást. Ezután a Beállítások menüben kapcsolhatja be újra a Wi-Fi-hívást." + + + "Regisztráljon a szolgáltatójánál" + + "%s Wi-Fi-hívás" + diff --git a/core/res/res/values-mcc310-mnc160-hy-rAM/strings.xml b/core/res/res/values-mcc310-mnc160-hy-rAM/strings.xml new file mode 100644 index 0000000000000..aadc5091b2df9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-hy-rAM/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi-ի միջոցով զանգեր կատարելու և հաղորդագրություններ ուղարկելու համար նախ դիմեք ձեր օպերատորին՝ ծառայությունը կարգավորելու համար: Ապա նորից միացրեք Wi-Fi զանգերը Կարգավորումներում:" + + + "Գրանցվեք օպերատորի մոտ" + + "%s Wi-Fi զանգեր" + diff --git a/core/res/res/values-mcc310-mnc160-in/strings.xml b/core/res/res/values-mcc310-mnc160-in/strings.xml new file mode 100644 index 0000000000000..364029160d57e --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-in/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan." + + + "Harap daftarkan ke operator" + + "%s Panggilan Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-is-rIS/strings.xml b/core/res/res/values-mcc310-mnc160-is-rIS/strings.xml new file mode 100644 index 0000000000000..fd10da5157897 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-is-rIS/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Til að hringja og senda skilaboð yfir Wi-Fi þarftu fyrst að biðja símafyrirtækið þitt um að setja þá þjónustu upp. Kveiktu síðan á Wi-Fi símtölum í stillingunum." + + + "Skráðu þig hjá símafyrirtækinu" + + "%s Wi-Fi símtöl" + diff --git a/core/res/res/values-mcc310-mnc160-it/strings.xml b/core/res/res/values-mcc310-mnc160-it/strings.xml new file mode 100644 index 0000000000000..7403ef7c6f2d8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-it/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Per effettuare chiamate e inviare messaggi tramite Wi-Fi, è necessario prima chiedere all\'operatore telefonico di attivare il servizio. Successivamente, riattiva le chiamate Wi-Fi dalle Impostazioni." + + + "Registrati con il tuo operatore" + + "Chiamata Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-iw/strings.xml b/core/res/res/values-mcc310-mnc160-iw/strings.xml new file mode 100644 index 0000000000000..2aa39370575e2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-iw/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "‏כדי להתקשר ולשלוח הודעות ברשת Wi-Fi, תחילה יש לבקש מהספק להגדיר את השירות. לאחר מכן, יש להפעיל שוב התקשרות Wi-Fi מ\'הגדרות\'." + + + "הירשם אצל הספק" + + "‏שיחות Wi-Fi של %s" + diff --git a/core/res/res/values-mcc310-mnc160-ja/strings.xml b/core/res/res/values-mcc310-mnc160-ja/strings.xml new file mode 100644 index 0000000000000..e5893346479dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ja/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi経由で音声通話の発信やメッセージの送信を行うには、携帯通信会社にWi-Fiサービスを申し込んだ上で、設定画面でWi-Fi発信を再度ONにしてください。" + + + "携帯通信会社に登録してください" + + "Wi-Fi通話(%s)" + diff --git a/core/res/res/values-mcc310-mnc160-ka-rGE/strings.xml b/core/res/res/values-mcc310-mnc160-ka-rGE/strings.xml new file mode 100644 index 0000000000000..2b8fd07aff6e2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ka-rGE/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi-ს მეშვეობით ზარების განხორციელების ან შეტყობინების გაგზავნისათვის, პირველ რიგში დაეკითხეთ თქვენს ოპერატორს აღნიშნულ მომსახურებაზე. შემდეგ ხელახლა ჩართეთ Wi-Fi ზარები პარამეტრებიდან." + + + "დაარეგისტრირეთ თქვენი ოპერატორი" + + "%s დარეკვა Wi-Fi-ს მეშვეობით" + diff --git a/core/res/res/values-mcc310-mnc160-kk-rKZ/strings.xml b/core/res/res/values-mcc310-mnc160-kk-rKZ/strings.xml new file mode 100644 index 0000000000000..b4f243364010c --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-kk-rKZ/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi арқылы қоңырау шалу және хабарларды жіберу үшін алдымен жабдықтаушыңыздан осы қызметті орнатуды сұраңыз. Содан кейін Параметрлерден Wi-Fi қоңырау шалуын іске қосыңыз." + + + "Жабдықтаушыңыз арқылы тіркелу" + + "%s Wi-Fi арқылы қоңырау шалу" + diff --git a/core/res/res/values-mcc310-mnc160-km-rKH/strings.xml b/core/res/res/values-mcc310-mnc160-km-rKH/strings.xml new file mode 100644 index 0000000000000..1806fbc5d0aa0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-km-rKH/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "ដើម្បីធ្វើការហៅ និងផ្ញើសារតាម Wi-Fi ដំបូងឡើយអ្នកត្រូវស្នើឲ្យក្រុមហ៊ុនរបស់អ្នកដំឡើងសេវាកម្មនេះសិន។ បន្ទាប់មកបើកការហៅតាម Wi-Fi ម្តងទៀតចេញពីការកំណត់។" + + + "ចុះឈ្មោះជាមួយក្រុមហ៊ុនរបស់អ្នក" + + "ការហៅតាមរយៈ Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-kn-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-kn-rIN/strings.xml new file mode 100644 index 0000000000000..43d942abae1db --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-kn-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi ಬಳಸಿಕೊಂಡು ಕರೆ ಮಾಡಲು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು, ಮೊದಲು ಈ ಸಾಧನವನ್ನು ಹೊಂದಿಸಲು ನಿಮ್ಮ ವಾಹಕವನ್ನು ಕೇಳಿ. ತದನಂತರ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಮತ್ತೆ Wi-Fi ಆನ್‌ ಮಾಡಿ." + + + "ನಿಮ್ಮ ವಾಹಕದಲ್ಲಿ ನೋಂದಾಯಿಸಿಕೊಳ್ಳಿ" + + "%s Wi-Fi ಕರೆ ಮಾಡುವಿಕೆ" + diff --git a/core/res/res/values-mcc310-mnc160-ko/strings.xml b/core/res/res/values-mcc310-mnc160-ko/strings.xml new file mode 100644 index 0000000000000..9e1322328c705 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ko/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi를 사용하여 전화를 걸고 메시지를 보내려면 먼저 이동통신사에 문의하여 이 기능을 설정해야 합니다. 그런 다음 설정에서 Wi-Fi 통화를 사용 설정하시기 바랍니다." + + + "이동통신사에 등록" + + "%s Wi-Fi 통화" + diff --git a/core/res/res/values-mcc310-mnc160-ky-rKG/strings.xml b/core/res/res/values-mcc310-mnc160-ky-rKG/strings.xml new file mode 100644 index 0000000000000..c1600125bbee7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ky-rKG/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi аркылуу чалууларды аткарып жана билдирүүлөрдү жөнөтүү үчүн адегенде операторуңуздан бул кызматты орнотушун сураныңыз. Андан соң, Жөндөөлөрдөн Wi-Fi чалууну кайра күйгүзүңүз." + + + "Операторуңузга катталыңыз" + + "%s Wi-Fi Чалуу" + diff --git a/core/res/res/values-mcc310-mnc160-lo-rLA/strings.xml b/core/res/res/values-mcc310-mnc160-lo-rLA/strings.xml new file mode 100644 index 0000000000000..a5347a9f25370 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-lo-rLA/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "ເພື່ອ​ໂທ ແລະ​ສົ່ງ​ຂໍ້​ຄວາມ​ຢູ່​ເທິງ Wi-Fi, ກ່ອນ​ອື່ນ​ໝົດ​ໃຫ້​ຖ້າມ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ ເພື່ອ​ຕັ້ງ​ການ​ບໍ​ລິ​ການ​ນີ້. ຈາກນັ້ນ​ເປີດການ​ໂທ Wi-Fi ອີກ​ຈາກ​ການ​ຕັ້ງ​ຄ່າ." + + + "ລົງ​ທະ​ບຽນ​ກັບ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ" + + "ການ​ໂທ %s Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-lt/strings.xml b/core/res/res/values-mcc310-mnc160-lt/strings.xml new file mode 100644 index 0000000000000..81b7488506381 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-lt/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Jei norite skambinti ir siųsti pranešimus „Wi-Fi“ ryšiu, pirmiausia paprašykite operatoriaus nustatyti šią paslaugą. Tada vėl įjunkite skambinimą „Wi-Fi“ ryšiu „Nustatymų“ skiltyje." + + + "Užregistruokite pas operatorių" + + "„%s“ „Wi-Fi“ skambinimas" + diff --git a/core/res/res/values-mcc310-mnc160-lv/strings.xml b/core/res/res/values-mcc310-mnc160-lv/strings.xml new file mode 100644 index 0000000000000..5d24c5f33ac8f --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-lv/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Lai veiktu zvanus un sūtītu īsziņas Wi-Fi tīklā, vispirms lūdziet mobilo sakaru operatoru iestatīt šo pakalpojumu. Pēc tam iestatījumos vēlreiz ieslēdziet Wi-Fi zvanus." + + + "Reģistrēt to pie sava mobilo sakaru operatora" + + "%s Wi-Fi zvani" + diff --git a/core/res/res/values-mcc310-mnc160-mk-rMK/strings.xml b/core/res/res/values-mcc310-mnc160-mk-rMK/strings.xml new file mode 100644 index 0000000000000..aea280e47c67c --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-mk-rMK/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "За повикување и испраќање пораки преку Wi-Fi, прво побарајте од операторот да ви ја постави оваа услуга. Потоа повторно вклучете повикување преку Wi-Fi во Поставки." + + + "Регистрирајте се со операторот" + + "%s Повикување преку Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-ml-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-ml-rIN/strings.xml new file mode 100644 index 0000000000000..9e244ebe3ebc1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ml-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "വൈഫൈ വഴി കോളുകൾ വിളിക്കാനും സന്ദേശങ്ങൾ അയയ്‌ക്കാനും ആദ്യം നിങ്ങളുടെ കാരിയറോട് ഈ സേവനം സജ്ജമാക്കാൻ ആവശ്യപ്പെടുക. ക്രമീകരണത്തിൽ നിന്ന് വീണ്ടും വൈഫൈ കോളിംഗ് ഓണാക്കുക." + + + "നിങ്ങളുടെ കാരിയറിൽ രജിസ്റ്റർ ചെയ്യുക" + + "%s വൈഫൈ കോളിംഗ്" + diff --git a/core/res/res/values-mcc310-mnc160-mn-rMN/strings.xml b/core/res/res/values-mcc310-mnc160-mn-rMN/strings.xml new file mode 100644 index 0000000000000..5b59d997dd801 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-mn-rMN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi-аар дуудлага хийх болон мессеж илгээхээр бол эхлээд оператороосоо энэ төхөөрөмжийг тохируулж өгөхийг хүсээрэй. Дараа нь Тохиргооноос Wi-Fi дуудлага хийх үйлдлийг асаагаарай." + + + "Операторт бүртгүүлэх" + + "%s Wi-Fi Дуудлага" + diff --git a/core/res/res/values-mcc310-mnc160-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-mr-rIN/strings.xml new file mode 100644 index 0000000000000..168c36ba55496 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-mr-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा." + + + "आपल्या वाहकासह नोंदणी करा" + + "%s वाय-फाय कॉलिंग" + diff --git a/core/res/res/values-mcc310-mnc160-ms-rMY/strings.xml b/core/res/res/values-mcc310-mnc160-ms-rMY/strings.xml new file mode 100644 index 0000000000000..1fe0157f3cfc7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ms-rMY/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Untuk membuat panggilan dan menghantar mesej melalui Wi-Fi, mula-mula minta pembawa anda untuk menyediakan perkhidmatan ini. Kemudian hidupkan panggilan Wi-Fi semula daripada Tetapan." + + + "Daftar dengan pembawa anda" + + "%s Panggilan Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-my-rMM/strings.xml b/core/res/res/values-mcc310-mnc160-my-rMM/strings.xml new file mode 100644 index 0000000000000..ae87ae7d74508 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-my-rMM/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "ဝိုင်ဖိုင်သုံး၍ ဖုန်းခေါ်ဆိုရန်နှင့် မက်စေ့ဂျ်များပို့ရန်၊ ဤဝန်ဆောင်မှုအား စတင်သုံးနိုင်ရန်အတွက် သင့် မိုဘိုင်းဝန်ဆောင်မှုအား ဦးစွာမေးမြန်းပါ။ ထို့နောက် ဆက်တင်မှတဆင့် ဝိုင်ဖိုင် ခေါ်ဆိုမှုအား ထပ်ဖွင့်ပါ။" + + + "သင့် မိုဘိုင်းဝန်ဆောင်မှုဖြင့် မှတ်ပုံတင်ရန်" + + "%s ဝိုင်ဖိုင် ခေါ်ဆိုမှု" + diff --git a/core/res/res/values-mcc310-mnc160-nb/strings.xml b/core/res/res/values-mcc310-mnc160-nb/strings.xml new file mode 100644 index 0000000000000..34357e1300b08 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-nb/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "For å ringe og sende meldinger over Wi-Fi må du først be operatøren om å konfigurere denne tjenesten. Deretter slår du på Wi-Fi-anrop igjen fra Innstillinger." + + + "Registrer deg hos operatøren din" + + "%s Wi-Fi-anrop" + diff --git a/core/res/res/values-mcc310-mnc160-ne-rNP/strings.xml b/core/res/res/values-mcc310-mnc160-ne-rNP/strings.xml new file mode 100644 index 0000000000000..f248fb73ebcc9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ne-rNP/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi बाट कल गर्न र सन्देशहरू पठाउन, सबभन्दा पहिला यो सेवा सेटअप गर्न तपाईँको वाहकलाई भन्नुहोस्। त्यसपछि फेरि सेटिङहरूबाट Wi-Fi कलिङ सक्रिय पार्नुहोस्।" + + + "तपाईँको वाहकसँग दर्ता गर्नुहोस्" + + "%s Wi-Fi कलिङ" + diff --git a/core/res/res/values-mcc310-mnc160-nl/strings.xml b/core/res/res/values-mcc310-mnc160-nl/strings.xml new file mode 100644 index 0000000000000..319f799ebfc91 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-nl/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via \'Instellingen\'." + + + "Registreren bij je provider" + + "Bellen via wifi van %s" + diff --git a/core/res/res/values-mcc310-mnc160-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-pa-rIN/strings.xml new file mode 100644 index 0000000000000..5641abebe79ab --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-pa-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈਟ ਅਪ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਵਿੱਚੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।" + + + "ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ" + + "%s Wi-Fi ਕਾਲਿੰਗ" + diff --git a/core/res/res/values-mcc310-mnc160-pl/strings.xml b/core/res/res/values-mcc310-mnc160-pl/strings.xml new file mode 100644 index 0000000000000..1d916cb006f41 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-pl/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Aby dzwonić i wysyłać wiadomości przez Wi-Fi, poproś swojego operatora o skonfigurowanie tej usługi. Potem ponownie włącz połączenia przez Wi-Fi w Ustawieniach." + + + "Zarejestruj u operatora" + + "Połączenia przez Wi-Fi (%s)" + diff --git a/core/res/res/values-mcc310-mnc260-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc160-pt-rBR/strings.xml similarity index 82% rename from core/res/res/values-mcc310-mnc260-pt-rBR/strings.xml rename to core/res/res/values-mcc310-mnc160-pt-rBR/strings.xml index bad49c3771f23..1c68cb14a3000 100644 --- a/core/res/res/values-mcc310-mnc260-pt-rBR/strings.xml +++ b/core/res/res/values-mcc310-mnc160-pt-rBR/strings.xml @@ -1,7 +1,7 @@ + + + + + + "Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as chamadas por Wi-Fi." + + + "Registar-se junto do seu operador" + + "Chamadas por Wi-Fi da %s" + diff --git a/core/res/res/values-mcc310-mnc160-pt/strings.xml b/core/res/res/values-mcc310-mnc160-pt/strings.xml new file mode 100644 index 0000000000000..1c68cb14a3000 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-pt/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Para fazer chamadas e enviar mensagens por Wi-Fi, primeiro peça à sua operadora para configurar esse serviço. Depois ative novamente as chamadas por Wi-Fi nas configurações." + + + "Faça registro na sua operadora" + + "%s chamada Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-ro/strings.xml b/core/res/res/values-mcc310-mnc160-ro/strings.xml new file mode 100644 index 0000000000000..f2490d8fbf7d6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ro/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Pentru a apela și a trimite mesaje prin Wi-Fi, mai întâi solicitați configurarea acestui serviciu la operator. Apoi, activați din nou apelarea prin Wi-Fi din Setări." + + + "Înregistrați-vă la operatorul dvs." + + "Apelare prin Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-ru/strings.xml b/core/res/res/values-mcc310-mnc160-ru/strings.xml new file mode 100644 index 0000000000000..9f2bc4357c8e8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ru/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Чтобы совершать звонки и отправлять сообщения по Wi-Fi, необходимо сначала обратиться к оператору связи и подключить эту услугу. После этого вы сможете снова выбрать этот параметр в настройках." + + + "Укажите оператора и зарегистрируйтесь" + + "Звонки по Wi-Fi (%s)" + diff --git a/core/res/res/values-mcc310-mnc160-si-rLK/strings.xml b/core/res/res/values-mcc310-mnc160-si-rLK/strings.xml new file mode 100644 index 0000000000000..0c133410892c3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-si-rLK/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi හරහා ඇමතුම් සිදු කිරීමට සහ පණිවිඩ යැවීමට, පළමුව මෙම සේවාව පිහිටුවන ලෙස ඔබේ වාහකයෙන් ඉල්ලන්න. අනතුරුව සැකසීම් වෙතින් Wi-Fi ඇමතුම නැවත ක්‍රියාත්මක කරන්න." + + + "ඔබගේ වාහකය සමඟ ලියාපදිංචි වන්න" + + "%s Wi-Fi අමතමින්" + diff --git a/core/res/res/values-mcc310-mnc160-sk/strings.xml b/core/res/res/values-mcc310-mnc160-sk/strings.xml new file mode 100644 index 0000000000000..3fe32f71edf82 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-sk/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Ak chcete volať a odosielať správy prostredníctvom siete Wi-Fi, kontaktujte najskôr svojho operátora v súvislosti s nastavením tejto služby. Potom opäť zapnite v Nastaveniach volanie cez Wi-Fi." + + + "Registrujte sa so svojím operátorom" + + "Volanie siete Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-sl/strings.xml b/core/res/res/values-mcc310-mnc160-sl/strings.xml new file mode 100644 index 0000000000000..3818309760551 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-sl/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Če želite klicati ali pošiljati sporočila prek omrežja Wi-Fi, se najprej obrnite na operaterja, da nastavi to storitev. Nato v nastavitvah znova vklopite klicanje prek omrežja Wi-Fi." + + + "Registracija pri operaterju" + + "Klicanje prek Wi-Fi-ja (%s)" + diff --git a/core/res/res/values-mcc310-mnc160-sq-rAL/strings.xml b/core/res/res/values-mcc310-mnc160-sq-rAL/strings.xml new file mode 100644 index 0000000000000..647cd03b5294a --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-sq-rAL/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Për të bërë telefonata dhe për të dërguar mesazhe me Wi-Fi, në fillim kërkoji operatorit celular ta konfigurojë këtë shërbim. Më pas aktivizo përsëri telefonatat me Wi-Fi, nga Cilësimet." + + + "Regjistrohu me operatorin tënd celular" + + "Telefonatat me Wi-Fi nga %s" + diff --git a/core/res/res/values-mcc310-mnc160-sr/strings.xml b/core/res/res/values-mcc310-mnc160-sr/strings.xml new file mode 100644 index 0000000000000..7f8381a7f7288 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-sr/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Да бисте упућивали позиве и слали поруке преко Wi-Fi-ја, прво затражите од мобилног оператера да вам омогући ову услугу. Затим у Подешавањима поново укључите Позивање преко Wi-Fi-ја." + + + "Региструјте се код мобилног оператера" + + "Wi-Fi позивање преко оператера %s" + diff --git a/core/res/res/values-mcc310-mnc160-sv/strings.xml b/core/res/res/values-mcc310-mnc160-sv/strings.xml new file mode 100644 index 0000000000000..e72b3b7c9c5dc --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-sv/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Om du vill ringa samtal och skicka meddelanden via Wi-Fi ber du först operatören att konfigurera tjänsten. Därefter kan du aktivera Wi-Fi-samtal på nytt från Inställningar." + + + "Registrera dig hos operatören" + + "%s Wi-Fi-samtal" + diff --git a/core/res/res/values-mcc310-mnc160-sw/strings.xml b/core/res/res/values-mcc310-mnc160-sw/strings.xml new file mode 100644 index 0000000000000..08ee75361c260 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-sw/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Ili upige simu na kutuma ujumbe kupitia Wi-Fi, mwambie mtoa huduma wako asanidi huduma hii kwanza. Kisha uwashe tena upigaji simu kwa Wi-Fi kutoka kwenye Mipangilio." + + + "Jisajili na mtoa huduma wako" + + "%s Upigaji Simu kwa Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160-ta-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-ta-rIN/strings.xml new file mode 100644 index 0000000000000..d6ea49cd593a9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ta-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "வைஃபை மூலம் அழைக்க மற்றும் செய்திகள் அனுப்ப, முதலில் மொபைல் நிறுவனத்திடம் இந்தச் சேவையை அமைக்குமாறு கேட்கவும். பிறகு அமைப்புகளில் மீண்டும் வைஃபை அழைப்பை இயக்கவும்." + + + "உங்கள் மொபைல் நிறுவனத்தில் பதிவுசெய்யவும்" + + "%s வைஃபை அழைப்பு" + diff --git a/core/res/res/values-mcc310-mnc160-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc160-te-rIN/strings.xml new file mode 100644 index 0000000000000..61f392900fcce --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-te-rIN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fiలో కాల్‌లు చేయడం మరియు సందేశాలు పంపడం కోసం ముందుగా ఈ సేవను సెటప్ చేయడానికి మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి మళ్లీ Wi-Fi కాలింగ్‌ను ఆన్ చేయండి." + + + "మీ క్యారియర్‌తో నమోదు చేయండి" + + "%s Wi-Fi కాలింగ్" + diff --git a/core/res/res/values-mcc310-mnc160-th/strings.xml b/core/res/res/values-mcc310-mnc160-th/strings.xml new file mode 100644 index 0000000000000..f1ff305e5abfc --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-th/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "หากต้องการโทรออกและส่งข้อความผ่าน Wi-Fi โปรดสอบถามผู้ให้บริการของคุณก่อนเพื่อตั้งค่าบริการนี้ แล้วเปิดการโทรผ่าน Wi-Fi อีกครั้งจากการตั้งค่า" + + + "ลงทะเบียนกับผู้ให้บริการ" + + "กำลังเรียก Wi-Fi ของ %s" + diff --git a/core/res/res/values-mcc310-mnc160-tl/strings.xml b/core/res/res/values-mcc310-mnc160-tl/strings.xml new file mode 100644 index 0000000000000..44dadd5aa1ee6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-tl/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Upang tumawag at magpadala ng mga mensahe sa pamamagitan ng Wi-Fi, hilingin muna sa iyong carrier na i-set up ang serbisyong ito. Pagkatapos ay muling i-on ang pagtawag sa Wi-Fi mula sa Mga Setting." + + + "Magparehistro sa iyong carrier" + + "Pagtawag sa Pamamagitan ng Wi-Fi ng %s" + diff --git a/core/res/res/values-mcc310-mnc160-tr/strings.xml b/core/res/res/values-mcc310-mnc160-tr/strings.xml new file mode 100644 index 0000000000000..2cb1dc91a8459 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-tr/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Kablosuz ağ üzerinden telefon etmek ve ileti göndermek için ilk önce operatörünüzden bu hizmeti ayarlamasını isteyin. Sonra tekrar Ayarlar\'dan Kablosuz çağrı özelliğini açın." + + + "Operatörünüze kaydolun" + + "%s Kablosuz Çağrı" + diff --git a/core/res/res/values-mcc310-mnc160-uk/strings.xml b/core/res/res/values-mcc310-mnc160-uk/strings.xml new file mode 100644 index 0000000000000..773930a6e0ffa --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-uk/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Щоб телефонувати або надсилати повідомлення через Wi-Fi, спочатку попросіть свого оператора налаштувати цю послугу. Після цього ввімкніть дзвінки через Wi-Fi у налаштуваннях." + + + "Зареєструйтеся в оператора" + + "Дзвінок через Wi-Fi від оператора %s" + diff --git a/core/res/res/values-mcc310-mnc160-ur-rPK/strings.xml b/core/res/res/values-mcc310-mnc160-ur-rPK/strings.xml new file mode 100644 index 0000000000000..e617582bdea9a --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-ur-rPK/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "‏Wi-Fi سے کالز کرنے اور پیغامات بھیجنے کیلئے، پہلے اپنے کیریئر سے اس سروس کو ترتیب دینے کیلئے کہیں۔ پھر ترتیبات سے دوبارہ Wi-Fi کالنگ آن کریں۔" + + + "اپنے کیریئر کے ساتھ رجسٹر کریں" + + "‏‎%s Wi-Fi کالنگ" + diff --git a/core/res/res/values-mcc310-mnc160-uz-rUZ/strings.xml b/core/res/res/values-mcc310-mnc160-uz-rUZ/strings.xml new file mode 100644 index 0000000000000..a951fc48ff536 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-uz-rUZ/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Wi-Fi orqali qo‘ng‘iroqlarni amalga oshirish va xabarlar bilan almashinish uchun uyali aloqa operatoringizdan ushbu xizmatni yoqib qo‘yishni so‘rashingiz lozim. Keyin sozlamalarda Wi-Fi qo‘ng‘irog‘i imkoniyatini yoqib olishingiz mumkin." + + + "Mobil operatoringiz yordamida ro‘yxatdan o‘ting" + + "%s Wi-Fi qo‘ng‘iroqlar" + diff --git a/core/res/res/values-mcc310-mnc160-vi/strings.xml b/core/res/res/values-mcc310-mnc160-vi/strings.xml new file mode 100644 index 0000000000000..253c93ead49ae --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-vi/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Để gọi điện và gửi tin nhắn qua Wi-Fi, trước tiên hãy yêu cầu nhà cung cấp dịch vụ của bạn thiết lập dịch vụ này. Sau đó, bật lại gọi qua Wi-Fi từ Cài đặt." + + + "Đăng ký với nhà cung cấp dịch vụ của bạn" + + "Gọi điện qua Wi-Fi %s" + diff --git a/core/res/res/values-mcc310-mnc160-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc160-zh-rCN/strings.xml new file mode 100644 index 0000000000000..3b10a631d2628 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-zh-rCN/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "要通过 WLAN 打电话和发信息,请先让您的运营商开通此服务,然后再到“设置”中重新开启 WLAN 通话功能。" + + + "向您的运营商注册" + + "%s WLAN 通话功能" + diff --git a/core/res/res/values-mcc310-mnc160-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc160-zh-rHK/strings.xml new file mode 100644 index 0000000000000..a39b37cd049dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-zh-rHK/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "如要透過 Wi-Fi 撥打電話及傳送訊息,請先向您的流動網絡供應商要求設定此服務。然後再次在「設定」中開啟 Wi-Fi 通話。" + + + "向您的流動網絡供應商註冊" + + "%s Wi-Fi 通話" + diff --git a/core/res/res/values-mcc310-mnc160-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc160-zh-rTW/strings.xml new file mode 100644 index 0000000000000..28690aa0ee6ff --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-zh-rTW/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "如要透過 Wi-FI 撥打電話及傳送訊息,請先要求您的行動通訊業者開通這項服務,然後再到「設定」啟用 Wi-Fi 通話功能。" + + + "向您的行動通訊業者註冊" + + "%s Wi-Fi 通話" + diff --git a/core/res/res/values-mcc310-mnc160-zu/strings.xml b/core/res/res/values-mcc310-mnc160-zu/strings.xml new file mode 100644 index 0000000000000..d08486d68e288 --- /dev/null +++ b/core/res/res/values-mcc310-mnc160-zu/strings.xml @@ -0,0 +1,32 @@ + + + + + + + + "Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo." + + + "Bhalisa ngenkampani yakho yenethiwekhi" + + "%s ukushaya kwe-Wi-Fi" + diff --git a/core/res/res/values-mcc310-mnc160/strings.xml b/core/res/res/values-mcc310-mnc160/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc160/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc200/strings.xml b/core/res/res/values-mcc310-mnc200/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc200/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc210/strings.xml b/core/res/res/values-mcc310-mnc210/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc210/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc220/strings.xml b/core/res/res/values-mcc310-mnc220/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc220/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc230/strings.xml b/core/res/res/values-mcc310-mnc230/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc230/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc240/strings.xml b/core/res/res/values-mcc310-mnc240/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc240/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc250/strings.xml b/core/res/res/values-mcc310-mnc250/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc250/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc260-de/strings.xml b/core/res/res/values-mcc310-mnc260-de/strings.xml index 3994bba0c3df0..f357bb65118af 100644 --- a/core/res/res/values-mcc310-mnc260-de/strings.xml +++ b/core/res/res/values-mcc310-mnc260-de/strings.xml @@ -23,10 +23,10 @@ - "Um über WLAN telefonieren und Nachrichten senden zu können, bitten Sie zuerst Ihren Mobilfunkanbieter, diesen Dienst einzurichten. Aktivieren Sie die Option \"Anrufe über WLAN\" dann erneut über die Einstellungen." + "Um über WLAN Anrufe durchführen und Nachrichten senden zu können, bitten Sie zuerst Ihren Mobilfunkanbieter, diesen Dienst einzurichten. Aktivieren Sie WLAN-Anrufe dann erneut über die Einstellungen." "Registrieren Sie sich bei Ihrem Mobilfunkanbieter." - "%s Anrufe über WLAN" + "%s WLAN-Anrufe" diff --git a/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml index 0a9d58dfc26e8..f24bed092a1db 100644 --- a/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml +++ b/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml @@ -23,10 +23,10 @@ - "Wi-Fi ಬಳಸಿಕೊಂಡು ಕರೆ ಮಾಡಲು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು, ಮೊದಲು ಈ ಸಾಧನವನ್ನು ಹೊಂದಿಸಲು ನಿಮ್ಮ ವಾಹಕವನ್ನು ಕೇಳಿ. ತದನಂತರ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಮತ್ತೆ Wi-Fi ಆನ್‌ ಮಾಡಿ." + "ವೈ-ಫೈ ಬಳಸಿಕೊಂಡು ಕರೆ ಮಾಡಲು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು, ಮೊದಲು ಈ ಸಾಧನವನ್ನು ಹೊಂದಿಸಲು ನಿಮ್ಮ ವಾಹಕವನ್ನು ಕೇಳಿ. ತದನಂತರ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಮತ್ತೆ ವೈ-ಫೈ ಆನ್‌ ಮಾಡಿ." "ನಿಮ್ಮ ವಾಹಕದಲ್ಲಿ ನೋಂದಾಯಿಸಿಕೊಳ್ಳಿ" - "%s Wi-Fi ಕರೆ ಮಾಡುವಿಕೆ" + "%s ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ" diff --git a/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml index a94680d128b42..764b792348101 100644 --- a/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml +++ b/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml @@ -23,10 +23,10 @@ - "വൈഫൈ വഴി കോളുകൾ വിളിക്കാനും സന്ദേശങ്ങൾ അയയ്‌ക്കാനും ആദ്യം നിങ്ങളുടെ കാരിയറോട് ഈ സേവനം സജ്ജമാക്കാൻ ആവശ്യപ്പെടുക. ക്രമീകരണത്തിൽ നിന്ന് വീണ്ടും വൈഫൈ കോളിംഗ് ഓണാക്കുക." + "Wi-Fi വഴി കോളുകൾ വിളിക്കാനും സന്ദേശങ്ങൾ അയയ്‌ക്കാനും ആദ്യം നിങ്ങളുടെ കാരിയറോട് ഈ സേവനം സജ്ജമാക്കാൻ ആവശ്യപ്പെടുക. ക്രമീകരണത്തിൽ നിന്ന് വീണ്ടും Wi-Fi കോളിംഗ് ഓണാക്കുക." "നിങ്ങളുടെ കാരിയറിൽ രജിസ്റ്റർ ചെയ്യുക" - "%s വൈഫൈ കോളിംഗ്" + "%s Wi-Fi കോളിംഗ്" diff --git a/core/res/res/values-mcc310-mnc260-nl/strings.xml b/core/res/res/values-mcc310-mnc260-nl/strings.xml index ac4961cf96b0a..1c6b892450c21 100644 --- a/core/res/res/values-mcc310-mnc260-nl/strings.xml +++ b/core/res/res/values-mcc310-mnc260-nl/strings.xml @@ -23,10 +23,10 @@ - "Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via \'Instellingen\'." + "Als u wilt bellen en berichten wilt verzenden via wifi, moet u eerst uw provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via \'Instellingen\'." - "Registreren bij je provider" + "Registreren bij uw provider" "Bellen via wifi van %s" diff --git a/core/res/res/values-mcc310-mnc270/strings.xml b/core/res/res/values-mcc310-mnc270/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc270/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc310/strings.xml b/core/res/res/values-mcc310-mnc310/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc310/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc490/strings.xml b/core/res/res/values-mcc310-mnc490/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc490/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc660/strings.xml b/core/res/res/values-mcc310-mnc660/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc660/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mcc310-mnc800/strings.xml b/core/res/res/values-mcc310-mnc800/strings.xml new file mode 100644 index 0000000000000..526d08b45c7ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc800/strings.xml @@ -0,0 +1,38 @@ + + + + + + + + + REG09 + + + + To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. + + + + Register with your carrier + + + %s Wi-Fi Calling + diff --git a/core/res/res/values-mk-rMK-watch/strings.xml b/core/res/res/values-mk-rMK-watch/strings.xml index b4eb51a42dd0d..e04a1953cb149 100644 --- a/core/res/res/values-mk-rMK-watch/strings.xml +++ b/core/res/res/values-mk-rMK-watch/strings.xml @@ -21,4 +21,5 @@ "Апликац. %1$d од %2$d." + "Сензори" diff --git a/core/res/res/values-mk-rMK/cm_strings.xml b/core/res/res/values-mk-rMK/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-mk-rMK/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml index 8dfdf1d318280..5ca10af3ab11c 100644 --- a/core/res/res/values-mk-rMK/strings.xml +++ b/core/res/res/values-mk-rMK/strings.xml @@ -254,7 +254,7 @@ "Опфаќа лични податоци како што се броеви на кредитни картички и лозинки." "оневозможи или измени статусна лента" "Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони." - "статусна лента" + "да стане статусна лента" "Дозволува апликацијата да биде статусната лента." "прошири/собери статусна лента" "Дозволува апликацијата да ја прошири или собере статусната лента." @@ -282,7 +282,7 @@ "Овозможува апликацијата да прима и да обработува WAP пораки. Оваа дозвола ја опфаќа способноста за следење или за бришење пораки испратени до вашиот уред без да ви ги прикаже вам." "обнови активни апликации" "Овозможува апликацијата да поврати информации за тековно и до неодамна активни задачи. Ова може да овозможи апликацијата да открие информации за тоа кои апликации се користат на уредот." - "Управувај сопственици на профил и уред" + "управување со сопствениците на профилите и уредите" "Дозволува апликациите до постават сопственици на профили и сопственик на уредот." "преуреди активни апликации" "Овозможува апликацијата да преместува задачи во преден план и во заднина. Апликацијата може да го прави тоа без вашиот придонес." @@ -324,7 +324,7 @@ "Овозможува апликацијата да го менува дневникот на повици на вашиот таблет, вклучувајќи податоци за дојдовни и појдовни повици. Злонамерните апликации може да го искористат ова да го избришат или да го менуваат вашиот дневник на повици." "Дозволува апликацијата да го менува дневникот на повици на вашиот телевизор, вклучувајќи и податоци за дојдовните или појдовните повици. Злонамерните апликации може да го искористат ова за да го избришат или да го менуваат вашиот дневник на повици." "Овозможува апликацијата да го менува дневникот на повици на вашиот телефон, вклучувајќи податоци за дојдовни и појдовни повици. Злонамерните апликации може да го искористат ова да го избришат или да го менуваат вашиот дневник на повици." - "телесни сензори (како монитори за срцев пулс)" + "пристап до телесните сензори (како мониторите за пулс)" "Дозволува апликацијата да пристапува до податоци од сензори кои ја следат вашата физичка состојба, како на пр. отчукувањата на срцето." "прочитај настани во календар и доверливи информации" "Овозможува апликацијата да ги чита сите календарски настани што се зачувани на вашиот таблет, вклучувајќи ги и оние на пријатели или соработници. Ова може да овозможи апликацијата да ги споделува или да го зачува вашите податоци од календарот, без оглед на нивната доверливост или чувствителност." @@ -336,15 +336,15 @@ "Овозможува апликацијата да додава, отстранува, менува настани кои може да ги менувате на вашиот телефон, вклучувајќи ги и оние на пријатели или соработници. Ова може да овозможи апликацијата да праќа пораки за кои се чини дека доаѓаат од сопственици на календар или да менува настани без знаење на сопствениците." "пристапи кон наредби на давателот на дополнителна локација" "Овозможува апликацијата да пристапи кон дополнителни наредби на давател на локација. Ова може да овозможи апликацијата да го попечи функционирањето на ГПС или други извори на локација." - "прецизна локација (ГПС и базирана на мрежа)" + "пристап до прецизната локација (GPS и врз база на мрежа)" "Овозможува апликацијата да ја добие вашата точна локација со користење „Глобален систем за позиционирање (ГПС)“ или извори на локација, како што се мобилни кули и Wi-Fi. Овие услуги за локација мора да се вклучени и достапни за вашиот уред за апликацијата да ги користи. Апликациите може да го користат ова за да утврдат приближно каде се наоѓате и може дополнително да потрошат батерија." - "приближна локација (базирана на мрежа)" + "пристап до приближната локација (врз база на мрежа)" "Овозможува апликацијата да ја добие вашата приближна локација. Оваа локација е изведена од услугите за локација со користење мрежа на извори на локација, како што се мобилни кули и Wi-Fi. Овие услуги за локација мора да се вклучени и достапни за вашиот уред за апликацијата да ги користи. Апликациите може да го користат ова за да утврдат приближно каде се наоѓате." "промени аудио подесувања" "Овозможува апликацијата да ги менува глобалните аудио подесувања, како што се јачината на звукот и кој звучник се користи за излез." "снимај аудио" "Овозможува апликацијата да снима аудио со микрофонот. Оваа дозвола овозможува апликацијата да снима аудио во кое било време без ваша потврда." - "комуникација со СИМ картичка" + "испраќање наредби до СИМ-картичката" "Овозможува апликацијата да испраќа наредби до СИМ картичката. Ова е многу опасно." "снимај слики и видеа" "Овозможува апликацијата да прави фотографии и да снима видеа со камерата. Оваа дозвола овозможува апликацијата да ја користи камерата во кое било време без ваша потврда." @@ -382,7 +382,7 @@ "Овозможува апликацијата да го добие списокот со сметки познати на телефонот. Ова може да опфати кои било сметки што ги создале апликациите што сте ги инсталирале." "прикажи мрежни врски" "Овозможува апликацијата да ги види информациите за мрежните конекции, како на пр., кои мрежи постојат и се поврзани." - "целосен пристап на мрежа" + "добивање целосен пристап до мрежата" "Овозможува апликацијата да создаде мрежни приклучоци и да користи приспособени мрежни протоколи. Прелистувачот и другите апликации обезбедуваат средства за да се испратат податоци на интернет, па оваа дозвола не е потребна за да се испратат податоци на интернет." "промени мрежно поврзување" "Дозволува апликацијата да ја промени состојбата на мрежната поврзливост." @@ -402,7 +402,7 @@ "Дозволува апликацијата да го конфигурира телефонот со локалниот Bluetooth и да открива и да се спарува со уреди на далечина." "поврзи се и исклучи се од WiMAX" "Овозможува апликацијата да утврди дали WiMAX е овозможен и информации за кои било поврзани WiMAX мрежи." - "Промени состојба на WiMAX" + "промена на состојбата на WiMAX" "Овозможува апликацијата да го вклучи таблетот на и да го исклучи таблетот од WiMAX мрежи." "Дозволува апликацијата да го поврзе или да го исклучи телевизорот од WiMAX мрежи." "Овозможува апликацијата да го вклучи телефонот на и да го исклучи телефонот од WiMAX мрежи." @@ -485,7 +485,7 @@ "Дозволува апликацијата да ги изменува калибрирачките параметри на екранот на допир. Не треба да се користи за стандардни апликации." "пристап до ДРМ-сертификати" "Дозволува апликацијата да обезбедува и користи ДРМ-сертификати. Не треба да се користи за стандардни апликации." - "Примајте статус на трансфер на Android Beam" + "добивање статус на пренос на Android Beam" "Ѝ дозволува на оваа апликација да добива информации за моменталните трансфери на Android Beam" "отстранување ДРМ-сетификати" "Дозволува апликација да отстранува ДРМ-сертификати. Не треба да се користи за стандардни апликации." @@ -1091,11 +1091,11 @@ "Се форматира..." "Не е внесено" "Не се пронајдени соодветни активности." - "Насочи излез за медиуми" + "насочување излез за медиуми" "Овозможува апликацијата да насочува излез за медиуми кон други надворешни уреди." - "Читај сесии на инсталирање" + "читање сесии на инсталирање" "Дозволува апликација да чита сесии на инсталирање. Тоа овозможува апликацијата да гледа детали за активни инсталации на пакет." - "Барај инсталирање пакети" + "барање пакети за инсталирање" "Дозволува апликацијата да бара инсталација на пакети." "Допрете двапати за регулирање на зумирањето" "Не можеше да се додаде виџет." diff --git a/core/res/res/values-ml-rIN-watch/strings.xml b/core/res/res/values-ml-rIN-watch/strings.xml index 079c42f4af882..9f93404f8670c 100644 --- a/core/res/res/values-ml-rIN-watch/strings.xml +++ b/core/res/res/values-ml-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d / %2$d അപ്ലിക്കേഷൻ." + "സെൻസറുകൾ" diff --git a/core/res/res/values-ml-rIN/cm_strings.xml b/core/res/res/values-ml-rIN/cm_strings.xml new file mode 100644 index 0000000000000..3262d4c7b1145 --- /dev/null +++ b/core/res/res/values-ml-rIN/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + സ്ക്രീൻഷോട്ട് + + പരിരക്ഷിത SMS സ്വീകരിക്കുക + + ഇൻകമിംഗ് പരിരക്ഷിത SMS സ്വീകരിക്കുവാന്‍ ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. + + പരിരക്ഷിത SMS ലിസ്റ്റ് പരിഷ്ക്കരിക്കുക + + പരിരക്ഷിത SMS വിലാസങ്ങളുടെ ലിസ്റ്റ് പരിഷ്ക്കരിക്കാൻ ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. + + സുരക്ഷ + + ഉപകരണ സുരക്ഷാ വിവരങ്ങളുമായി ബന്ധപ്പെട്ട അനുമതികൾ. + + ഫോൺ ബ്ലാക്ക്‌ലിസ്റ്റ് റീഡ് ചെയ്യുക + + ഇന്‍കമിംഗ് കോളുകള്‍ അല്ലെങ്കില്‍ സന്ദേശങ്ങള്‍ക്ക് വേണ്ടി തടയപ്പെട്ട ഫോണ്‍ നമ്പറുകളെക്കുറിച്ചുള്ള വിവരങ്ങള്‍ റീഡ് ചെയ്യാന്‍ ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. + + ഫോൺ ബ്ലാക്ക്‌ലിസ്റ്റ് മാറ്റുക + + ഇന്‍കമിംഗ് കോളുകള്‍ അല്ലെങ്കില്‍ സന്ദേശങ്ങള്‍ക്ക് വേണ്ടി തടയപ്പെട്ട ഫോണ്‍ നമ്പറുകള്‍ മാറ്റാന്‍ ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. + + കീഗാര്‍ഡ് വാൾപേപ്പർ സജ്ജമാക്കി + + ലോക്ക് സ്ക്രീൻ വാൾപേപ്പർ മാറ്റാന്‍ ഒരു ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. + + റീബൂട്ട് ചെയ്യുക + + നിലവിൽ + + + റീബൂട്ട് ചെയ്യുക + + റിക്കവറി + + ബൂട്ട്ലോഡര്‍ + + ഡൗൺലോഡുചെയ്യുക + + മൃദു റീബൂട്ട് + + റീബൂട്ട് ചെയ്യുക + + നിങ്ങളുടെ ടാബ്ലറ്റ് റീബൂട്ട് ചെയ്യുന്നതാണ്. + നിങ്ങളുടെ ഫോൺ റീബൂട്ട് ചെയ്യുന്നതാണ്. + + റീബൂട്ട് ചെയ്യുന്നു..... + + ആപ്ലിക്കേഷനെ നശിപ്പിച്ചു + + നെറ്റ്‌വർക്കിലൂടെയുള്ള ADB പ്രാപ്തമാക്കി + + USB & നെറ്റ്‌വർക്കിലൂടെയുള്ള ADB പ്രാപ്തമാക്കി + + ഡീബഗ്ഗിംഗ് അപ്രാപ്തമാക്കാൻ സ്‌പർശിക്കുക. + + ADB %1$s + USB & നെറ്റ്‌വർക്ക് + USB + നെറ്റ്‌വർക്ക് + + ആപ്ലിക്കേഷൻ ആരംഭിക്കുന്നത് തടസപ്പെടുത്തുക + + %s ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ല + + മുന്‍‌ഗണന + ആരിൽ നിന്നും വേണ്ട + + SIM സബ്സ്ക്രിപ്ഷൻ മാറ്റം കാരണം Wi-Fi ഹോട്ട്സ്പോട്ട് അപ്രാപ്തമാക്കി + + Wi-Fi ഓഫ് ചെയ്യുക + + പ്രൈവസി ഗാർഡ് അപ്രാപ്തമാക്കുക അല്ലെങ്കില്‍ അപ്രാപ്തമാക്കുക + മറ്റൊരു ആപ്ലിക്കേഷന്‍ സ്വകാര്യത ഗാർഡില്‍ പ്രവര്‍ത്തിക്കുന്നെങ്കില്‍ മാറ്റുന്നതിന് ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഒരു ആപ്ലിക്കേഷൻ സ്വകാര്യത ഗാർഡ് ഉപയോഗിച്ച് പ്രവർത്തിക്കുമ്പോൾ, കോണ്‍ടാക്റ്റുകള്‍, കോൾ ലോഗുകള്‍, അല്ലെങ്കിൽ സന്ദേശങ്ങൾ പോലുള്ള സ്വകാര്യ ഡാറ്റയില്‍ പ്രവേശനം ഉണ്ടായിരിക്കില്ല. + സ്വകാര്യത ഗാർഡ് സജീവമാണ് + സ്വകാര്യത ഡാറ്റ പ്രവേശനം ചെയ്യാന്‍ %1$s ന് കഴിയില്ല + സ്വകാര്യത ഗാർഡ് + %1$s, %1$s ആഗ്രഹിക്കുന്നു. + + എന്റെ ചോയ്‌സ് ഓർമ്മിക്കുക + + ക്യാമറ ആക്സസ് ചെയ്യുക + നിങ്ങളുടെ സ്ഥാനം ആക്സസ് ചെയ്യുക + നിങ്ങളുടെ അറിയിപ്പുകൾ വായിക്കുക + ഒരു VPN സജീവമാക്കുക + പവര്‍ ലഭിക്കുമ്പോള്‍ ആരംഭിക്കുക + നിങ്ങളുടെ കോൾ ലോഗ് ഇല്ലാതാക്കുക + നിങ്ങളുടെ കോണ്‍ടാക്റ്റുകള്‍ ഇല്ലാതാക്കുക + നിങ്ങളുടെ MMS സന്ദേശങ്ങൾ ഇല്ലാതാക്കുക + നിങ്ങളുടെ SMS സന്ദേശങ്ങൾ ഇല്ലാതാക്കുക + വിന്‍ഡോകള്‍ മുകളിൽ വരയ്ക്കുക + ആപ്ലിക്കേഷൻ ഉപയോഗ സ്ഥിതിവിവരക്കണക്കുകൾ നേടുക + നിങ്ങളുടെ ഉപകരണം സജീവമായി നിലനിര്‍ത്തുക + ഒരു ഫോൺ കോൾ ചെയ്യുക + നിങ്ങളുടെ കലണ്ടർ കാലികമാക്കുക + കോൾ ലോഗ് കാലികമാക്കുക + ക്ലിപ്ബോർഡ് പരിഷ്ക്കരിക്കുക + നിങ്ങളുടെ സമ്പര്‍‌ക്കങ്ങള്‍‌ കാലികമാക്കുക + സിസ്റ്റം ക്രമീകരണങ്ങൾ കാലികമാക്കുക + മൈക്രോഫോൺ നിശ്ശബ്ദമാക്കുക / ശബ്ദമുള്ളതാക്കുക + ഓഡിയോ പ്ലേ ചെയ്യുക + ഒരു അറിയിപ്പ് പോസ്റ്റ് ചെയ്യുക + പ്രോജക്റ്റ് മീഡിയ + നിങ്ങളുടെ കലണ്ടർ റീഡ് ചെയ്യുക + കോൾ ലോഗ് റീഡുചെയ്യുക + ക്ലിപ്ബോര്‍ഡ് റീഡ് ചെയ്യുക + നിങ്ങളുടെ കോൺടാക്റ്റുകൾ റീഡുചെയ്യുക + നിങ്ങളുടെ MMS സന്ദേശങ്ങൾ വായിക്കുക + നിങ്ങളുടെ SMS സന്ദേശങ്ങൾ വായിക്കുക + ഒരു SMS സന്ദേശം സ്വീകരിക്കുക + ഓഡിയോ റെക്കോർഡ് ചെയ്യുക + ഒരു MMS സന്ദേശം അയയ്ക്കുക + ഒരു SMS സന്ദേശം അയയ്ക്കുക + പവര്‍ ലഭിക്കുമ്പോള്‍ ആരംഭിക്കുക + ടോസ്റ്റ് സന്ദേശങ്ങൾ ഡിസ്പ്ലേ ചെയ്യുക + ടോഗിള്‍ Bluetooth + സെല്ലുലാർ ഡാറ്റ ഓൺ ചെയ്യുക + NFC ടോഗിൾ + Wi-Fi ഓണ്‍ ആക്കുക + അലാറം വോളിയം നിയന്ത്രിക്കുക + ഓഡിയോ ഫോക്കസ് നിയന്ത്രിക്കുക + Bluetooth വോളിയം നിയന്ത്രിക്കുക + മാസ്റ്റര്‍ വോളിയം നിയന്ത്രിക്കുക + മീഡിയ ബട്ടണുകൾ ഉപയോഗിക്കുക + മീഡിയ വോളിയം നിയന്ത്രിക്കുക + അറിയിപ്പ് വോളിയം നിയന്ത്രിക്കുക + റിംഗ്ടോൺ വോളിയം നിയന്ത്രിക്കുക + സ്പര്‍ശന പ്രതികരണം ഉപയോഗിക്കുക + വോയ്സ് കോൾ വോളിയം നിയന്ത്രിക്കുക + MMS സന്ദേശം റൈറ്റ് ചെയ്യുക + ഒരു SMS സന്ദേശം റൈറ്റ് ചെയ്യുക + വിരലടയാളം ഉപയോഗിക്കുക + ഒരു വോയ്സ്മെയിൽ ചേർക്കുക + ഫോണിന്‍റെ സ്ഥിതി ഉപയോഗിക്കുക + സ്കാൻ Wi-Fi നെറ്റ്വർക്കുകൾ + വാൾപേപ്പർ മാറ്റാൻ + use assist structure + ഒരു സ്ക്രീൻഷോട്ട് എടുക്കുക + ശരീരം സെൻസറുകൾ ഉപയോഗിക്കാൻ + ഫോണ്‍ പ്രക്ഷേപണങ്ങള്‍ വായിക്കുക + നിങ്ങളുടെ സ്ഥാനം വ്യാജമാക്കുക + ബാഹ്യ സംഭരണം വായിക്കാൻ + ബാഹ്യ സംഭരണം എഴുതാൻ + സ്ക്രീന്‍ ഓണാക്കുക + get device accounts + വൈഫിയുടെ സ്ഥിതി മാറ്റുക + റൂട്ട് പ്രവേശനം നേടുക + + ഈ സ്ക്രീൻ വേര്‍തിരിക്കുക ചെയ്യുന്നതിന്, പിന്നിലേക്ക് ബട്ടൺ അമര്‍ത്തിപ്പിടിക്കുക. + + ബന്ധിപ്പിച്ച ഉപകരണം ഇല്ല + %1$s ബന്ധിപ്പിച്ച ഉപകരണം + %1$s ബന്ധിപ്പിച്ച ഉപകരണങ്ങൾ + + + + പ്രോഗ്രാം തുറക്കുന്നത് തടഞ്ഞിരിക്കുന്നു + %1$s തുറക്കുന്നത് തടഞ്ഞിരിക്കുന്നു. സാധുവാക്കി തുറക്കുവാൻ സ്പർശിക്കുക. + + ബാറ്ററി പൂർണ്ണമായും ചാർജ് ചെയ്തു + ബാറ്ററി ആയുർദൈർഘ്യം മെച്ചപ്പെടുത്താൻ ചാർജർ നിന്നും നിങ്ങളുടെ ഉപകരണം വിച്ഛേദിക്കുക. + + ബാറ്ററി സ്ഥിതിവിവരക്കണക്ക് പുനക്രമീകരിക്കുക + + നിലവിലെ ലോ-ലെവല്‍ ബാറ്ററി ഉപയോഗ ഡാറ്റ പുനഃക്രമീകരിക്കാൻ ഒരു ആപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. + + diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml index 330c1e9a0b47a..537eeae52b1e0 100644 --- a/core/res/res/values-ml-rIN/strings.xml +++ b/core/res/res/values-ml-rIN/strings.xml @@ -254,7 +254,7 @@ "ക്രെഡിറ്റ് കാർഡ് നമ്പറുകളും പാസ്‌വേഡുകളും പോലുള്ള വ്യക്തിഗത ഡാറ്റ ഉൾപ്പെടുന്നു." "സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക" "നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." - "സ്റ്റാറ്റസ് ബാർ" + "സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക" "അപ്ലിക്കേഷനെ നില ബാർ ആകാൻ അനുവദിക്കുന്നു." "സ്റ്റാറ്റസ് വിപുലീകരിക്കുക/ചുരുക്കുക" "നില ബാർ വിപുലീകരിക്കുന്നതിനോ ചുരുക്കുന്നതിനോ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." @@ -282,7 +282,7 @@ "WAP സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങൾക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ ഉള്ള കഴിവ് ഈ അനുമതികളിൽ ഉൾപ്പെടുന്നു." "പ്രവർത്തിക്കുന്ന അപ്ലിക്കേഷനുകൾ വീണ്ടെടുക്കുക" "നിലവിലും സമീപകാലത്തും പ്രവർത്തിക്കുന്ന ടാസ്‌ക്കുകളെക്കുറിച്ചുള്ള വവിവരങ്ങൾ വീണ്ടെടുക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് ഉപകരണത്തിൽ ഉപയോഗിച്ച അപ്ലിക്കേഷനുകളെക്കുറിച്ചുള്ള വിവരം കണ്ടെത്താൻ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്." - "പ്രൊഫൈൽ, ഉപകരണ ഉടമകളെ നിയന്ത്രിക്കുക" + "പ്രൊഫൈൽ, ഉപകരണ ഉടമകളെ മാനേജുചെയ്യുക" "പ്രൊഫൈൽ ഉടമകളെയും ഉപകരണ ഉടമയെയും സജ്ജമാക്കാൻ അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു." "പ്രവർത്തിക്കുന്ന അപ്ലിക്കേഷനുകൾ പുനഃക്രമീകരിക്കുക" "ടാസ്‌ക്കുകളെ മുന്നിലേക്കോ പശ്ചാത്തലത്തിലേക്കോ നീക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് അപ്ലിക്കേഷൻ നിങ്ങളുടെ ഇടപെടലില്ലാതെ ചെയ്യാനിടയുണ്ട്." @@ -324,7 +324,7 @@ "ഇൻകമിംഗ്, ഔട്ട്ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള ഡാറ്റയുൾപ്പെടുന്ന, നിങ്ങളുടെ ടാബ്‌ലെറ്റിന്റെ കോൾ ലോഗ് പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ കോൾ ലോഗ് മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ഇത് ഉപയോഗിച്ചേക്കാം." "ഇൻകമിംഗ്, ഔട്ട്ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള വിവരമുൾപ്പെടുന്ന, നിങ്ങളുടെ ടിവിയുടെ കോൾ ലോഗ് പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ദോഷകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ കോൾ ലോഗ് മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ഇത് ഉപയോഗിച്ചേക്കാം." "ഇൻകമിംഗ്, ഔട്ട്ഗോയിംഗ് കോളുകളെക്കുറിച്ചുള്ള ഡാറ്റയുൾപ്പെടുന്ന, നിങ്ങളുടെ ഫോണിന്റെ കോൾ ലോഗ് പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ കോൾ ലോഗ് മായ്‌ക്കാനോ പരിഷ്‌ക്കരിക്കാനോ ഇത് ഉപയോഗിച്ചേക്കാം." - "ശാരീര സെൻസറുകൾ (ഹൃദയമിടിപ്പ് നിരക്ക് മോണിറ്ററുകൾ പോലെ)" + "ശരീര സെൻസറുകൾ (ഹൃദയമിടിപ്പ് നിരക്ക് മോണിറ്ററുകൾ പോലെ) ആക്സസ് ചെയ്യുക" "നിങ്ങളുടെ ഹൃദയമിടിപ്പ് പോലുള്ള ശാരീരികാവസ്ഥ നിരീക്ഷിക്കാൻ സെൻസറുകളിൽ നിന്ന് വിവരം ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "കലണ്ടർ ഇവന്റുകളും രഹസ്യാത്മക വിവരവും വായിക്കുക" "നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ സംഭരിച്ചിരിക്കുന്ന സുഹൃത്തുക്കളുടെയോ സഹപ്രവർത്തകരുടെയോ ഉൾപ്പെടെ, എല്ലാ കലണ്ടർ ഇവന്റുകളും റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് രഹസ്യാത്മകമാണെന്നോ തന്ത്രപ്രധാനമാണെന്നോ പരിഗണിക്കാതെ നിങ്ങളുടെ കലണ്ടർ ഡാറ്റ പങ്കിടാനോ സംരക്ഷിക്കാനോ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്." @@ -336,15 +336,15 @@ "സുഹൃത്തുക്കളുടെയും സഹപ്രവർത്തകരുടെയും ഉൾപ്പെടെ, നിങ്ങളുടെ ഫോണിൽ പരിഷ്‌ക്കരിക്കാനാകുന്ന ഇവന്റുകൾ ചേർക്കാനും നീക്കംചെയ്യാനും മാറ്റാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. കലണ്ടർ ഉടമകളിൽ നിന്നുള്ളതായി തോന്നുന്ന സന്ദേശങ്ങൾ അയയ്‌ക്കാനോ ഉടമയുടെ അറിവില്ലാതെ ഇവന്റുകൾ പരിഷ്‌ക്കരിക്കാനോ ഇത് അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്." "ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യുക" "ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് GPS-ന്റെയോ മറ്റ് ലൊക്കേഷൻ ഉറവിടങ്ങളുടെയോ പ്രവർത്തനത്തിൽ ഇടപെടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്." - "കൃത്യമായ ലൊക്കേഷൻ (GPS-ഉം നെറ്റ്‌വർക്കും അടിസ്ഥാനമാക്കിയുള്ളത്)" + "കൃത്യമായ ലൊക്കേഷൻ (GPS - നെറ്റ്‌വർക്ക് അധിഷ്ഠിതം) ആക്സസ് ചെയ്യുക" "ഗ്ലോബൽ പൊസിഷനിംഗ് സിസ്റ്റമോ (GPS) സെൽ ടവറുകളും Wi-Fi-യും പോലുള്ള നെറ്റ്‌വർക്ക് ലൊക്കേഷൻ ഉറവിടങ്ങളോ ഉപയോഗിച്ച് നിങ്ങളുടെ കൃത്യമായ ലൊക്കേഷൻ നേടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അപ്ലിക്കേഷനുകൾ അവ ഉപയോഗിക്കാൻ നിങ്ങളുടെ ഉപകരണത്തിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്‌ത് ലഭ്യമാക്കേണ്ടതുണ്ട്. നിങ്ങൾ എവിടെയാണെന്ന് ഏകദേശം നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനുകൾ ഇത് ഉപയോഗിക്കാം, അവ കൂടുതൽ ബാറ്ററി പവർ ഉപയോഗിക്കാനിടയുണ്ട്." - "ഏകദേശ ലൊക്കേഷൻ (നെറ്റ്‌വർക്ക് അടിസ്ഥാനമാക്കിയുള്ളത്)" + "ഏകദേശ ലൊക്കേഷൻ (നെറ്റ്‌വർക്ക് അധിഷ്ഠിതം) ആക്സസ് ചെയ്യുക" "നിങ്ങളുടെ ഏകദേശ ലൊക്കേഷൻ നേടാൻ അപ്ലിക്കേഷനുകളെ അനുവദിക്കുക. ഈ ലൊക്കേഷനെ സെൽ ടവറുകളും Wi-Fi-യും പോലുള്ള നെറ്റ്‌വർക്ക് ലൊക്കേഷൻ ഉറവിടങ്ങൾ ഉപയോഗിച്ച് ലൊക്കേഷൻ സേവനങ്ങൾ അനുമാനിക്കുന്നു. അപ്ലിക്കേഷനുകൾ അവ ഉപയോഗിക്കാൻ നിങ്ങളുടെ ഉപകരണത്തിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്‌ത് ലഭ്യമാക്കേണ്ടതുണ്ട്. നിങ്ങൾ എവിടെയാണെന്ന് ഏകദേശം നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനുകൾ ഇത് ഉപയോഗിക്കാം." "നിങ്ങളുടെ ഓഡിയോ ക്രമീകരണങ്ങൾ മാറ്റുക" "വോളിയവും ഔട്ട്പുട്ടിനായി ഉപയോഗിച്ച സ്‌പീക്കറും പോലുള്ള ആഗോള ഓഡിയോ ക്രമീകരണങ്ങൾ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "ഓഡിയോ റെക്കോർഡ് ചെയ്യുക" "മൈക്രോഫോൺ ഉപയോഗിച്ച് ഓഡിയോ റെക്കോർഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഈ അനുമതി നിങ്ങളുടെ സ്ഥിരീകരണമില്ലാതെ ഏതുസമയത്തും ഓഡിയോ റെക്കോർഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്ന്ഉ." - "സിം ആശയവിനിമയം" + "SIM-ലേക്ക് കമാൻഡുകൾ അയയ്ക്കുക" "സിമ്മിലേക്ക് കമാൻഡുകൾ അയയ്‌ക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് വളരെ അപകടകരമാണ്." "ചിത്രങ്ങളും വീഡിയോകളും എടുക്കുക" "ക്യാമറ ഉപയോഗിച്ച് ചിത്രങ്ങളും വീഡിയോകളും എടുക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ സ്ഥിരീകരണമില്ലാതെ ഏതുസമയത്തും ക്യാമറ ഉപയോഗിക്കാൻ ഈ അനുമതി അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." @@ -382,7 +382,7 @@ "ഫോൺ തിരിച്ചറിയുന്ന അക്കൗണ്ടുകളുടെ ലിസ്റ്റ് നേടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇതിൽ നിങ്ങൾ ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുകൾ സൃഷ്‌ടിച്ച എല്ലാ അക്കൗണ്ടുകളും ഉൾപ്പെടാം." "നെറ്റ്‌വർക്ക് കണക്ഷനുകൾ കാണുക" "ഏതെല്ലാം നെറ്റ്‌വർക്കുകൾ നിലവിലുണ്ടെന്നതും കണക്റ്റുചെയ്‌തിട്ടുണ്ടെന്നതും പോലുള്ള നെറ്റ്‌വർക്ക് കണക്ഷനുകളെക്കുറിച്ചുള്ള വിവരം കാണാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." - "പൂർണ്ണ നെറ്റ്‌വർക്ക് ആക്‌സസ്സ്" + "പൂർണ്ണ നെറ്റ്‌വർക്ക് ആക്സസ് നൽകുക" "നെറ്റ്‌വർക്ക് സോക്കറ്റുകൾ സൃഷ്‌ടിക്കാനും ഇഷ്‌ടാനുസൃത നെറ്റ്‌വർക്ക് പ്രോട്ടോക്കോളുകൾ ഉപയോഗിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇന്റർനെറ്റിലേക്ക് ഡാറ്റ അയയ്‌ക്കുന്നതിനായി ബ്രൗസറും മറ്റ് അപ്ലിക്കേഷനുകളും ഉള്ളതിനാൽ, ഇന്റർനെറ്റിലേക്ക് ഡാറ്റ അയയ്‌ക്കാൻ ഈ അനുമതി ആവശ്യമില്ല." "നെറ്റ്‌വർക്ക് കണക്‌റ്റിവിറ്റി മാറ്റുക" "നെറ്റ്‌വർക്ക് കണക്‌റ്റി‌വിറ്റിയുടെ നില മാറ്റുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." @@ -402,7 +402,7 @@ "ഒരു പ്രാദേശിക ബ്ലൂടൂത്ത് ഫോണിനെ കോൺഫിഗർചെയ്യുന്നതിനും വിദൂര ഉപകരണങ്ങളെ കണ്ടെത്തി ജോടിയാക്കുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "WiMAX കണക്റ്റുചെയ്യുക, അതിൽ നിന്നും വിച്ഛേദിക്കുക" "WiMAX പ്രവർത്തനക്ഷമമാണോയെന്നതും കണക്റ്റുചെയ്‌തിരിക്കുന്ന ഏതെങ്കിലും WiMAX നെറ്റ്‌വർക്കുകളെക്കുറിച്ചുള്ള വിവരങ്ങളും നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." - "WiMAX നില മാറ്റുക" + "WiMAX നില മാറ്റുക" "WiMAX നെറ്റ്‌വർക്കുകളിലേക്ക് ടാബ്‌ലെറ്റ് കണക്റ്റുചെയ്യാനും അതിൽ നിന്ന് വിച്ഛേദിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "WiMAX നെറ്റ്‌വർക്കുകളിൽ നിന്ന് ടിവി കണക്‌റ്റുചെയ്യുന്നതിനും വിച്‌ഛേദിക്കുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "WiMAX നെറ്റ്‌വർക്കുകളിലേക്ക് ഫോൺ കണക്റ്റുചെയ്യാനും അതിൽ നിന്ന് വിച്ഛേദിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." @@ -485,7 +485,7 @@ "ടച്ച് സ്‌ക്രീനിന്റെ കാലിബ്രേഷൻ പാരാമീറ്ററുകൾ പരിഷ്‌ക്കരിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല." "DRM സർട്ടിഫിക്കറ്റുകൾക്കുള്ള ആക്‌സസ്സ്" "പ്രൊവിഷൻ ചെയ്യുന്നതിനും DRM സർട്ടിഫിക്കറ്റുകൾ ഉപയോഗിക്കുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല." - "Android ബീം കൈമാറൽ നില നേടുക" + "Android ബീം കൈമാറൽ നില സ്വീകരിക്കുക" "നിലവിലെ Android ബീം കൈമാറ്റങ്ങളെക്കുറിച്ച് വിവരങ്ങൾ നേടാൻ ഈ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു" "DRM സർട്ടിഫിക്കറ്റുകൾ നീക്കം ചെയ്യുക" "DRM സർട്ടിഫിക്കറ്റുകൾ നീക്കംചെയ്യുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല." @@ -1091,11 +1091,11 @@ "ഫോർമാറ്റുചെയ്യുന്നു…" "ഇട്ടിട്ടില്ല" "പൊരുത്തമുള്ള പ്രവർത്തനങ്ങളൊന്നും കണ്ടെത്തിയില്ല." - "മീഡിയ ഔട്ട്പുട്ട് റൂട്ടുചെയ്യുക" + "മീഡിയ ഔട്ട്പുട്ട് റൂട്ടുചെയ്യുക" "മീഡിയ ഔട്ട്‌പുട്ടിനെ മറ്റ് ബാഹ്യ ഉപകരണങ്ങളിലേക്ക് റൂട്ടുചെയ്യാൻ ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." - "ഇൻസ്‌റ്റാൾ സെഷനുകൾ റീഡുചെയ്യുക" + "ഇൻസ്‌റ്റാൾ സെഷനുകൾ റീഡുചെയ്യുക" "ഇൻസ്റ്റാൾ ചെയ്‌ത സെഷനുകൾ റീഡുചെയ്യുന്നതിന് ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സജീവ പാക്കേജ് ഇൻസ്റ്റാളേഷനുകളെക്കുറിച്ചുള്ള വിശദാംശങ്ങൾ കാണുന്നതിന് ഇത് അനുവദിക്കുന്നു." - "പാക്കേജുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ അഭ്യർത്ഥിക്കുക" + "പാക്കേജുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ അഭ്യർത്ഥിക്കുക" "പാക്കേജുകളുടെ ഇൻസ്റ്റാളേഷൻ അഭ്യർത്ഥിക്കാൻ ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "സൂം ചെയ്യൽ നിയന്ത്രണങ്ങൾക്ക് രണ്ട് തവണ സ്‌പർശിക്കുക" "വിജറ്റ് ചേർക്കാനായില്ല." diff --git a/core/res/res/values-mn-rMN-watch/strings.xml b/core/res/res/values-mn-rMN-watch/strings.xml index 49f829b9b150e..ceea490990da8 100644 --- a/core/res/res/values-mn-rMN-watch/strings.xml +++ b/core/res/res/values-mn-rMN-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d-ны %2$d апп." + "Мэдрэгч" diff --git a/core/res/res/values-mn-rMN/cm_strings.xml b/core/res/res/values-mn-rMN/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-mn-rMN/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 2e6eb85f6fb9f..465be3bc90826 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -254,7 +254,7 @@ "Кредит картын дугаар болон нууц үг зэрэг хувийн датаг агуулж байна." "статус самбарыг идэвхгүй болгох болон өөрчлөх" "Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой." - "статус самбар" + "статусын хэсэг болох" "Апп нь статус самбар болох боломжтой." "статус самбарыг нээх/хаах" "Апп нь статус самбарыг дэлгэх болон хаах боломжтой." @@ -282,7 +282,7 @@ "Апп нь WAP мессежийг хүлээн авах болон биелүүлэх боломжтой. Энэ зөвшөөрөл нь танд илгээсэн мессежийг танд харуулалгүйгээр хянах эсвэл устгах боломжийг агуулна." "ажиллаж байгаа апп-г дуудах" "Апп нь одоо ажиллаж байгаа болон сүүлд ажилласан даалгаврын талаарх мэдээллийг авах боломжтой. Ингэснээр апп нь төхөөмж дээрх ямар аппликешнүүд ашиглагдсан талаарх мэдээлийг олох боломжтой." - "Профайл болон төхөөрөмжийн эзэмшигчийг удирдах" + "Профайл, төхөөрөмж эзэмшигчийг удирдах" "Аппликейшнд профайл болон төхөөрөмж эзэмшигчийг сонгохыг зөвшөөрөх" "ажиллаж байгаа апп-уудыг дахин эрэмбэлэх" "Апп нь даалгавруудыг нүүрлүү болон арлуу зөөх боломжтой. Апп нь энийг таны оролцоогүйгээр хийж болзошгүй" @@ -324,7 +324,7 @@ "Апп нь таны таблетын ирсэн гарсан дуудлага зэргийг агуулсан дуудлагын логыг унших боломжтой. Хортой апп нь энийг ашиглан таны дуудлагын логыг өөрчлөх болон арилгах боломжтой." "Апп-д орж ирсэн болон гадагш хийсэн телевизийн дуудлагын бүртгэлийг өөрчлөхийг зөвшөөрдөг. Хорлонтой апликейшнүүд үүнийг ашиглан таны дуудлагын бүртгэлийг устгах эсвэл өөрчилж болох юм." "Апп нь таны утасны ирсэн гарсан дуудлага зэргийг агуулсан дуудлагын логыг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан таны дуудлагын логыг өөрчлөх болон арилгах боломжтой." - "биеийн сенсор (зүрхний цохилт хянагч гэх мэт)" + "биеийн мэдрэгчид хандах (зүрхний хэмнэл шалгагч г.м)" "Апп-т таны зүрхний цохилт гэх мэт биеийн байдлыг хянадаг мэдрэгчдийн датанд хандалт хийх боломж олгоно." "календарийн хуваарийн нууц мэдээллийг унших" "Апп нь таны таблет дээр хадгалагдсан найзууд болон хамтран ажиллагсдын календарийн бүх хуваарийг унших боломжтой. Энэ нь апп-д таны календарийн датаг нууц эсвэл эмзэг эсэхээс нь үл хамааран хуваалцах эсвэл хадгалах боломжийг олгоно." @@ -336,15 +336,15 @@ "Апп нь утсан дээр та болон таны найзууд, хамтран ажиллагсдын өөрчилж чадах үйл явдлуудыг нэмэх, хасах болон солих боломжтой. Энэ нь апп-д, календарь эзэмшигчээс ирсэн мэт харагдах мессежийг илгээх эсвэл эзэмшигчид нь мэдэгдэлгүйгээр үйл явдлуудыг өөрчлөх боломжийг олгоно." "байршил нийлүүлэгчийн нэмэлт тушаалд хандах" "Апп нь байршил нийлүүлэгчийн нэмэлт тушаалд хандах боломжтой. Энэ нь апп-д GPS эсвэл бусад байршлын үйлчилгээний ажиллагаанд нөлөөлөх боломжийг олгоно." - "Тодорхой байршил(GPS болон сүлжээнд суурилсан)" + "тодорхой байршилд хандах (GPS, сүлжээнд суурилсан)" "Апп нь GPS эсвэл үүрэн цамхаг болон Wi-Fi зэрэг сүлжээний байршлын эх үүсвэрийг ашиглан таны тодорхой байршлыг авах боломжтой. Эдгээр байршлын үйлчилгээнүүд нь асаалттай байх шаардлагатай ба таны төхөөрөмж дээрх апп-ууд ашиглах боломжтой байх шаардлагатай. Апп-ууд энийг ашиглан таныг хаана байгааг тогтоох боломжтой ба батерей зарцуулалт нэмэгдэнэ." - "ойролцоох байршил(сүлжээнд суурилсан)" + "ойролцоох байршилд хандах (сүлжээнд суурилсан)" "Апп нь таны ойролцоох байршлыг оло боломжтой. Энэ байршил нь үүрэн цамхаг болон Wi-Fi зэрэг сүлжээний байршлын эх сурвалжийг ашигладаг байршлын үйлчилгээнээс олдоно. Эдгээр байршлын үйлчилгээнүүд нь таны төхөөрөмж дээр асаалттай байх шаардлагатай ба апп-д тэдгээрийг ашиглах боломжтой байх шаардлагатай. Апп-д тэдгээрийг ашиглан таны байршлыг ойролцоогоор олох боломжтой." "Аудио тохиргоо солих" "Апп нь дууны хэмжээ, спикерын гаралтад ашиглагдах глобал аудио тохиргоог өөрчлөх боломжтой." "аудио бичих" "Апп нь микрофоноор аудио бичих боломжтой. Энэ зөвшөөрөл нь апп-д ямар ч үед таны зөвшөөрөлгүйгээр аудио бичих боломжийг олгоно." - "сим холбоо" + "SIM картад тушаал илгээх" "Апп-д SIM рүү комманд илгээхийг зөвшөөрнө. Энэ маш аюултай." "зураг авах болон видео бичих" "Апп нь камераар зураг авах болон видео бичих боломжтой. Энэ зөвшөөрөл нь апп-д ямар ч үед таны зөвшөөрөлгүйгээр камер ашиглах боломжийг олгоно." @@ -382,7 +382,7 @@ "Апп нь утсанд мэдэгдэж байгаа акаунтын жагсаалтыг авах боломжтой. Энд таны суулгасан аппликешнүүдийн үүсгэсэн бүх акаунтууд хамрагдана." "сүлжээний холболтыг үзэх" "Апп нь сүлжээ байгаа болон холбогдсон эсэх зэрэг сүлжээний холболтын талаарх мэдээллийг харах боломжтой." - "сүлжээнд бүрэн хандах" + "сүлжээнд бүрэн нэвтрэх" "Апп нь сүлжээний сокетыг үүсгэх болон тусгай сүлжээний протокол ашиглах боломжтой. Хөтөч болон бусад аппликешнүүд Интернетээр дата илгээх боломжтой тул энэ зөвшөөрөл нь Интернетээр дата илгээхэд шаардлагагүй." "сүлжээний холболтыг солих" "Апп нь сүлжээний холболтын статусыг солих боломжтой." @@ -402,7 +402,7 @@ "Апп нь утасны дотоод блютүүтыг тохируулах боломжтой ба гадаад төхөөрөмжийг олох болон хос үүсгэх боломжтой." "WiMAX-д холбогдох болон салах" "Апп нь WiMAX идэвхтэй эсэх болон холбогдсон WiMAX сүлжээний талаар мэдээллийг тодорхойлох боломжтой." - "WiMAX статусыг өөрчлөх" + "WiMAX статусыг солих" "Апп нь WiMAX сүлжээнд таблетыг холбох болон салгах боломжтой." "Телевизийг WiMAX сүлжээнд холбох, салгахыг апп-д зөвшөөрдөг." "Апп нь WiMAX сүлжээнд утсыг холбох болон салгах боломжтой." @@ -485,7 +485,7 @@ "Мэдрэгчтэй дэлгэцний калибрешн параметрийг өөрчлөхийг апп-д зөвшөөрнө. Энгийн апп-д шаардлагагүй." "хандалтын DRM сертификат" "Аппликешнд DRM сертификатыг ашиглах болон нийлүүлэхийг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй." - "Андройд Бийм дамжуулалтын статусыг хүлээн авах" + "Android Beam дамжуулалтын төлөвийг авах" "Одоогийн Андройд Бийм дамжуулалтын мэдээллийг хүлээн авахыг аппликешнд зөвшөөрөх" "DRM сертификатыг устгах" "Аппликешнд DRM сертификатыг устгахыг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй." @@ -1091,11 +1091,11 @@ "Хэлбэршүүлж байна..." "Оруулаагүй байна" "Таарах активити олдсонгүй." - "Медиа гаралтыг чиглүүлэх" + "медиа гаралтын маршрут" "Аппликешн нь медиа гаралтыг бусад гадаад төхөөрөмжрүү чиглүүлэх боломжтой." - "Суулгах сешн унших" + "Суулгах харилцан үйлдлийг унших" "Аппликешн-д суулгах сешн уншихыг зөвшөөрнө. Энэ нь идэвхтэй багцуудыг суулгалтын талаар дэлгэрэнгүй мэдээллийг үзэх боломж олгоно." - "Багц суулгахыг хүсэх" + "багц суулгахыг хүсэх" "Аппликейшн нь багц суулгахыг хүсэх боломжтой." "Өсгөх контрол дээр хоёр удаа товшино уу" "Виджет нэмж чадсангүй." diff --git a/core/res/res/values-mr-rIN-watch/strings.xml b/core/res/res/values-mr-rIN-watch/strings.xml index 49fa7d9e466c9..223f8faf1b889 100644 --- a/core/res/res/values-mr-rIN-watch/strings.xml +++ b/core/res/res/values-mr-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d पैकी %1$d अॅप" + "सेन्सर" diff --git a/core/res/res/values-mr-rIN/cm_strings.xml b/core/res/res/values-mr-rIN/cm_strings.xml new file mode 100644 index 0000000000000..86845d9e44574 --- /dev/null +++ b/core/res/res/values-mr-rIN/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + स्क्रीनशॉट + + संरक्षित SMS प्राप्त झाला + + अॅप ला एक इनकमिंग संरक्षित SMS प्राप्त करण्याची परवानगी देते. + + संरक्षित SMS यादी सुधारित करा + + अॅप संरक्षित SMS पत्ता यादी सुधारित करण्याची परवानगी देते. + + सुरक्षितता + + डिव्हाइस सुरक्षा माहितीशी संबंधित परवानग्या. + + फोन काळी यादी वाचा + + इनकमिंग कॉल्स किंवा संदेशांसाठी अवरोधित केलेल्या फोन नंबर्सविषयी माहिती अॅप वाचू देते. + + फोन काळी यादी बदला + + इनकमिंग कॉल्स किंवा संदेशांसाठी अवरोधित केलेले फोन नंबर्स अनुप्रयोगाला बदलण्याची परवानगी देते. + + कीगार्ड वॉलपेपर सेट करा + + अनुप्रयोगाला लॉक स्क्रीन वॉलपेपर बदलण्याची परवानगी देते. + + रीबूट करा + + वर्तमान + + + रीबूट करा + + पुर्नप्राप्ती + + बूटलोडर + + डाउनलोड करा + + सॉफ्ट रीबूट + + रीबूट करा + + तुमचा टॅब्लेट रीबूट होईल. + तुमचा फोन रीबूट होईल. + + रीबूट करत आहे\u2026 + + अॅप बंद केला + + नेटवर्कवर ADB सक्षम केले + + नेटवर्कवर आणि USB वर ADB सक्षम केले + + डिबगिंग अक्षम करण्यासाठ स्पर्श करा. + + ADB - %1$s + USB आणि नेटवर्क + USB + नेटवर्क + + अनुप्रयोग सुरू कराला अटकाव करा + + %s स्थापित केलेले नाही + + प्राधान्य + काहीही नाही + + सिम सदस्यत्व बदलामुळे अक्षम केलेला Wi-Fi हॉटस्पॉट + + Wi-Fi बंद करा + + गुप्तता रक्षक सक्षम किंवा अक्षम करा + गुप्तता रक्षकासह दुसरा अनुप्रयोग चालतो का ते अॅप बदलण्याची परवानगी देते. जेव्हा गुप्तता रक्षकासह एखादा अनुप्रयोग चालू असेल तेव्हा, त्याला वैयक्तिक डेटामध्ये ऍक्सेस नसेल, जसे की संपर्क, कॉल लॉग्ज किंवा संदेश. + गुप्तता रक्षक सक्रिय + %1$s ला वैयक्तिक डेटामध्ये ऍक्सेस करता येणार नाही + गुप्तता रक्षक + %1$s ला %2$sचे आहे. + + माझी आवड लक्षात ठेवा + + कॅमेरा ऍक्सेस करा + तुमचे स्थान ऍक्सेस करा + तुमच्या सूचना वाचा + एक VPN सक्रिय करा + पॉवर अपला सुरू करा + तुमचे कॉल लॉग हटवा + तुमचे संपर्क हटवा + तुमचे MMS संदेश हटवा + तुमचे SMS संदेश हटवा + शीर्षावर विंडोज रेखाटा + अॅप वापर आकडेवारी मिळवा + तुमचे डिव्हाइस सक्रिय ठेवा + फोन कॉल करा + तुमची दिनदर्शिका अपडेट करा + कॉल लॉग अपडेट करा + क्लिपबोर्ड सुधारित करा + तुमचे संपर्क अपडेट करा + सिस्टिम सेटिंग्ज अपडेट करा + मायक्रोफोन निःशब्द/सशब्द करा + ऑडिओ प्ले करा + सूचना पोस्ट करा + प्रोजेक्‍ट मीडिया + तुमची दिनदर्शिका वाचा + कॉल लॉग वाचा + क्लिपबोर्ड वाचा + आपले संपर्क वाचा + तुमचे MMS संदेश वाचा + तुमचे SMS संदेश वाचा + SMS संदेश प्राप्त करा + ऑडिओ रेकॉर्ड करा + MMS संदेश पाठवा + SMS संदेश पाठवा + पॉवर अपला सुरू करा + टोस्ट संदेश प्रदर्शित करा + Bluetooth टॉगल करा + मोबाईल डेटा टॉगल करा + NFC टॉगल करा + Wi-Fi टॉगल करा + अलार्म ध्वनी नियंत्रित करा + ऑडिओ फोकस नियंत्रित करा + Bluetooth ध्वनी नियंत्रित करा + प्रमुख ध्वनी नियंत्रित करा + मिडिया बटणे वापरा + मिडिया ध्वनी नियंत्रित करा + सूचना ध्वनी नियंत्रित करा + रींग टोन ध्वनी नियंत्रित करा + हॅप्टिक फीडबॅक वापरा + व्हॉइस कॉल ध्वनी नियंत्रित करा + MMS संदेश लिहा + SMS संदेश लिहा + बोटाचा ठसा वापरा + व्हॉइसमेल जोडा + फोन आकडेवारी ऍक्सेस करा + Wi-Fi नेटवर्क्स स्कॅन करा + वॉलपेपर बदला + सहाय्यक रचना वापरा + स्क्रीनशॉट घ्या + शरीर सेन्सर्स वापरा + सेल ब्रॉडकास्ट्स वाचा + तुमचे स्थान खोटे करा + बाह्य संग्रह वाचा + अंतर्गत संग्रह लिहा + स्क्रीन चालू करा + डिव्हाइस खाती मिळवा + Wi-Fi आकडेवारी बदला + रूट ऍक्सेस मिळवा + + हा स्क्रीन अनपिन करण्यासाठी, मागे बटण दाबून धरा. + + कनेक्टेड डिव्हाइस नाही + %1$s कनेक्टेड डिव्हाइस + %1$s कनेक्टेड डिव्हाइसेस + + + + कार्यकलाप सुरू करा अवरोधित केले + %1$s सुरू होण्यापासून संरक्षित आहे. प्रमाणित करण्यासाठी टॅप करा आणि अॅप सुरू करा. + + बॅटरी पूर्णपणे चार्ज + बॅटरी फार काळ टिकवण्यासाठी चार्जर मधून आपले डिव्हाइस डिस्कनेक्ट करा. + + बॅटरी आकडेवारी रीसेट करा + + अॅपला चालू कमी-पातळी बॅटरी वापर डेटा रीसेट करण्याची परवानगी देते. + + सिम कार्डे बदलली + सिम कार्ड मुलभूत प्राधान्ये सेट करण्यासाठी टॅप + diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml index 74f36b9a61ba0..baef50bbafaed 100644 --- a/core/res/res/values-mr-rIN/strings.xml +++ b/core/res/res/values-mr-rIN/strings.xml @@ -254,7 +254,7 @@ "क्रेडिट कार्ड नंबर आणि संकेतशब्‍द यासारखा वैयक्तिक डेटा समाविष्‍ट करते." "स्टेटस बार अक्षम करा किंवा सुधारित करा" "स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टीम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते." - "स्टेटस बार" + "स्टेटस बार होऊ द्या" "स्टेटस बार होण्यासाठी अॅप ला अनुमती देते." "स्‍टेटस बार विस्तृत करा/संकुचित करा" "स्टेटस बार विस्तृत करण्यासाठी किंवा संक्षिप्त करण्यासाठी अॅप ला अनुमती देते." @@ -282,7 +282,7 @@ "WAP संदेश प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्याला पाठविलेले संदेश आपल्याला न दर्शविता त्यांचे परीक्षण करण्याची आणि ते हटविण्याची क्षमता समाविष्ट करते." "चालणारे अॅप्स पुनर्प्राप्त करा" "सध्या आणि अलीकडे चालणार्‍या कार्यांविषयी माहिती पुनर्प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे डिव्हाइसवर कोणते अनुप्रयोग वापरले जात आहेत त्याविषयी माहिती शोधण्यासाठी अॅप ला अनुमती देऊ शकतात." - "प्रोफाईल आणि डिव्हाइस मालक व्यवस्थापित करा" + "प्रोफाईल आणि डिव्हाइस मालक व्यवस्थापित करा" "प्रोफाईल मालक आणि डिव्हाइस मालक सेट करण्याची अॅप्सना अनुमती द्या." "चालणारे अॅप्स पुनर्क्रमित करा" "समोर आणि पार्श्वभूमीवर कार्ये हलविण्यासाठी अॅप ला अनुमती देते. अॅप हे आपल्या इनपुटशिवाय करू शकतो." @@ -324,7 +324,7 @@ "येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टॅब्लेटचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात." "येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टीव्हीचा कॉल लॉग सुधारित करण्यासाठी अॅपला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात." "येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या फोनचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात." - "(हृदय गती मॉनिटरसारखे) शरीर सेन्सर" + "शरीर सेन्सरमध्ये (हृदय गती मॉनिटरसारखे) प्रवेश करा" "हृदय गती सारख्या, आपल्या शारीरिक स्थितीचे नियंत्रण करणार्‍या सेन्सरवरून डेटामध्ये प्रवेश करण्यासाठी अॅपला अनुमती देते." "कॅलेंडर इव्हेंट तसेच गोपनीय माहिती वाचा" "मित्र किंवा सहकर्मींसह, आपल्या टॅब्लेटवर संचयित केलेले सर्व कॅलेंडर इव्हेंट वाचण्यासाठी अॅप ला अनुमती देते. यामुळे गोपनीयता किंवा संवेदनशीलता याकडे दुर्लक्ष करून, आपला कॅलेंडर डेटा सामायिक किंवा जतन करण्यासाठी अॅप ला अनुमती देऊ शकते." @@ -336,15 +336,15 @@ "मित्र किंवा सहकर्मी यांच्यासह, आपण आपल्या फोनवर सुधारित करू शकता असे इव्हेंट जोडण्यासाठी, काढण्यासाठी, बदलण्यासाठी अॅप ला अनुमती देते. हे कॅलेंडर मालकांकडून येत असल्याचे दिसणारे संदेश पाठविण्यासाठी किंवा मालकांच्या माहितीशिवाय इव्हेंट सुधारित करण्यासाठी अॅप ला अनुमती देऊ शकते." "अतिरिक्त स्थान प्रदाता आदेशांवर प्रवेश करा" "अ‍ॅपला अतिरिक्त स्‍थान प्रदाता आदेशावर प्रवेश करण्‍याची अनुमती देते. हे कदाचित अ‍ॅपला GPS किंवा इतर स्‍थान स्त्रोत च्या ऑपरेशनमध्‍ये हस्तक्षेप करण्‍याची अनुमती देऊ शकते." - "अचूक स्थान (GPS आणि नेटवर्क-आधारित)" + "अचूक स्थानामध्ये (GPS आणि नेटवर्क-आधारित) प्रवेश करा" "सेल टॉवर आणि वाय-फाय सारखी समग्र स्थिती निर्धारण प्रणाली (GPS) किंवा नेटवर्क स्थान स्त्रोत वापरून आपले अचूक स्थान मिळवण्यासाठी अॅप ला अनुमती देते. अॅपला त्या वापरण्यासाठी या स्थान सेवा चालू असणे आणि आपल्या डिव्हाइसवर उपलब्ध असणे आवश्यक आहे. आपण कुठे आहात हे निर्धारित करण्यासाठी अॅप्स याचा वापर करू शकतात आणि अतिरिक्त बॅटरी उर्जा वापरली जाऊ शकते." - "अंदाजे स्थान (नेटवर्क-आधारित)" + "अंदाजे स्‍थानामध्ये (नेटवर्क-आधारित) प्रवेश करा" "आपले अंदाजे स्थान देण्याची अॅप ला अनुमती देते. हे स्थान सेल टॉवर आणि वाय-फाय सारखे नेटवर्क स्थान स्त्रोत वापरून स्थान सेवांद्वारे मिळवले आहे. अॅपला त्या वापरण्यासाठी या स्थान सेवा चालू असणे आणि आपल्या डिव्हाइसवर उपलब्ध असणे आवश्यक आहे. अॅप्स हे आपण कुठे आहात याचा अंदाज लावण्यासाठी वापरू शकतात." "आपल्या ऑडिओ सेटिंग्ज बदला" "व्हॉल्यूम आणि आउटपुटसाठी कोणता स्पीकर वापरला आहे यासारख्या समग्र ऑडिओ सेटिंग्ज सुधारित करण्यासाठी अॅप ला अनुमती देते." "ऑडिओ रेकॉर्ड करा" "मायक्रोफोनसह ऑडिओ रेकॉर्ड करण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्या पुष्टिकरणाशिवाय कोणत्याही वेळी ऑडिओ रेकॉर्ड करण्यासाठी अॅप ला अनुमती देते." - "सिम संप्रेषण" + "सिम वर आदेश पाठवा" "अ‍ॅप ला सिम वर आदेश पाठविण्‍याची अनुमती देते. हे खूप धोकादायक असते." "चित्रे आणि व्हिडिओ घ्या" "कॅमेर्‍यासह चित्रे आणि व्हिडिओ घेण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्या पुष्टीकरणाशिवाय कोणत्याही वेळी कॅमेरा वापरण्यासाठी अॅप ला परवानगी देते." @@ -382,7 +382,7 @@ "फोनद्वारे ज्ञात खात्यांची सूची मिळवण्यासाठी अॅप ला अनुमती देते. यात आपण स्थापित केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट करू शकतात." "नेटवर्क कनेक्शन पहा" "कोणती नेटवर्क अस्तित्वात आहेत आणि कनेक्ट केलेली आहेत यासारख्या नेटवर्क कनेक्शनविषयीची माहिती पाहण्यासाठी अॅप ला अनुमती देते." - "पूर्ण नेटवर्क प्रवेश" + "पूर्ण नेटवर्क प्रवेश आहे" "नेटवर्क सॉकेट तयार करण्यासाठी आणि सानुकूल नेटवर्क प्रोटोकॉल वापरण्यासाठी अॅप ला अनुमती देते. ब्राउझर आणि अन्य अनुप्रयोग म्हणजे इंटरनेटवर डेटा पाठवण्याचा मार्ग, म्हणजे इंटरनेटवर डेटा पाठविण्यासाठी परवानगीची आवश्यकता नसते." "नेटवर्क कनेक्टिव्हिटी बदला" "नेटवर्क कनेक्टिव्हिटीची स्थिती बदलण्यासाठी अॅप ला अनुमती देते." @@ -402,7 +402,7 @@ "स्थानिक ब्लूटुथ फोन कॉन्फिगर करण्याकरिता आणि दूरस्थ डिव्हाइसेस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते." "WiMAX कनेक्ट करा आणि त्यावरून डिस्कनेक्ट करा" "WiMAX सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या कोणत्याही WiMAX नेटवर्क विषयीची माहिती निर्धारित करण्यासाठी अॅप ला अनुमती देते." - "WiMAX स्थिती बदला" + "WiMAX स्थिती बदला" "WiMAX नेटवर्कवर टॅब्लेट कनेक्ट करण्यास आणि त्यावरून टॅब्लेट डिस्कनेक्ट करण्यास अॅप ला अनुमती देते." "WiMAX नेटवर्कवरून टीव्ही कनेक्ट करण्यासाठी आणि त्यावरून टीव्ही डिस्कनेक्ट करण्यासाठी अॅपला अनुमती देते." "WiMAX नेटवर्कवर फोन कनेक्ट करण्यास आणि त्यावरून फोन डिस्कनेक्ट करण्यास अॅप ला अनुमती देते." @@ -485,7 +485,7 @@ "स्पर्श स्क्रीनची मापन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते." "DRM प्रमाणपत्रांवर प्रवेश करा" "DRM प्रमाणपत्रांची तरतूद करण्यासाठी आणि वापरण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यकता नसते." - "Android बीम स्थानांतरण स्थिती प्राप्त करा" + "Android बीम स्थानांतरण स्थिती प्राप्त करा" "वर्तमान Android बीम स्थानांतरणांविषयी माहिती प्राप्त करण्यासाठी या अनुप्रयोगास अनुमती देते" "DRM प्रमाणपत्रे काढा" "DRM प्रमाणपत्रे काढण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यकता नसते." @@ -1091,11 +1091,11 @@ "फॉर्मेट करीत आहे..." "घातले नाही" "कोणतेही जुळणारे क्रियाकलाप आढळले नाहीत." - "मीडिया आउटपुट मार्गस्थ करा" + "मीडिया आउटपुट मार्गस्थ करा" "अन्य बाह्य डिव्हाइसेसवरील रूट मीडिया आउटपुट वर अनुप्रयोगास अनुमती देते." - "स्‍थापना सत्र वाचा" + "स्‍थापना सत्र वाचा" "अनुप्रयोगास स्‍थापना सत्र वाचण्‍याची अनुमती देते. हे सक्रिय पॅकेज स्‍थापनांविषयी तपशील पाहाण्‍याची यास अनुमती देते." - "पॅकेज स्थापित करण्यासाठी विनंती करा" + "पॅकेज स्थापित करण्यासाठी विनंती करा" "पॅकेजच्या स्थापना करण्यासाठी अनुप्रयोगास अनुमती देते." "झूम नियंत्रणासाठी दोनदा स्पर्श करा" "विजेट जोडू शकलो नाही." diff --git a/core/res/res/values-ms-rMY-watch/strings.xml b/core/res/res/values-ms-rMY-watch/strings.xml index 148f518bcdbb8..eeb290c2e77c0 100644 --- a/core/res/res/values-ms-rMY-watch/strings.xml +++ b/core/res/res/values-ms-rMY-watch/strings.xml @@ -21,4 +21,5 @@ "Apl %1$d daripada %2$d." + "Penderia" diff --git a/core/res/res/values-ms-rMY/cm_strings.xml b/core/res/res/values-ms-rMY/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-ms-rMY/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 5d666a7f5f507..ec726ed18ce97 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -254,7 +254,7 @@ "Termasuk data peribadi seperti nombor kad kredit dan kata laluan." "lumpuhkan atau ubah suai bar status" "Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem." - "bar status" + "jadi bar status" "Membenarkan apl menjadi bar status." "kembangkan/runtuhkan bar status" "Membenarkan apl mengembangkan atau meruntuhkan bar status." @@ -282,7 +282,7 @@ "Membenarkan apl menerima dan memproses mesej WAP. Kebenaran ini termasuk keupayaan untuk memantau atau memadam mesej yang dihantar kepada anda tanpa menunjukkannya kepada anda." "dapatkan semula apl yang sedang dijalankan" "Membenarkan apl mengambil maklumat tentang tugasan yang sedang dan baru berjalan. Ini boleh membenarkan apl untuk menemui maklumat tentang apl mana yang digunakan pada peranti." - "Urus pemilik profil dan peranti" + "urus pemilik profil dan peranti" "Membenarkan apl menetapkan pemilik profil dan pemilik peranti." "susun semula tertib apl yang dijalankan" "Membenarkan apl memindahkan tugasan ke latar depan dan latar belakang. Apl boleh melakukan ini tanpa input anda." @@ -324,7 +324,7 @@ "Membenarkan apl untuk mengubah suai panggilan tablet anda, termasuk data tentang panggilan masuk dan keluar. Apl hasad boleh menggunakannya untuk memadam atau mengubah suai log panggilan anda." "Membenarkan apl untuk mengubah suai log panggilan TV anda, termasuk data mengenai panggilan masuk atau keluar. Apl hasad mungkin menggunakan ini untuk memadam atau mengubah suai log panggilan anda." "Membenarkan apl untuk mengubah suai panggilan telefon anda, termasuk data tentang panggilan masuk dan keluar. Apl hasad boleh menggunakannya untuk memadam atau mengubah suai log panggilan anda." - "penderia (spt. denyut jantung)" + "akss pndia bdn (spt pmntau kdr dnyt jntg)" "Membenarkan apl mengakses data dari penderia yang memantau keadaan fizikal anda, seperti kadar denyutan jantung anda." "baca acara kalendar serta maklumat sulit" "Membenarkan apl membaca semua acara kalendar yang tersimpan pada tablet anda, termasuk milik rakan atau rakan sekerja. Ini boleh membenarkan apl untuk berkongsi atau menyimpan data kalendar anda, tanpa mengira kerahsiaan atau sensitiviti." @@ -336,15 +336,15 @@ "Membenarkan apl menambah, mengalih keluar, mengubah acara yang anda boleh ubah suai pada telefon anda, termasuk milik rakan atau rakan sekerja. Ini boleh membenarkan apl menghantar mesej yang kelihatan seperti datang dari pemilik kalendar atau mengubah suai acara tanpa pengetahuan pemilik." "akses perintah tambahan pembekal lokasi" "Membenarkan apl mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain." - "lokasi tepat (GPS dan berasaskan rangkaian)" + "akses lokasi tepat (GPS dan berasaskan rangkaian)" "Membenarkan apl mendapatkan lokasi tepat anda menggunakan Sistem Kedudukan Global (GPS) atau sumber lokasi rangkaian seperti menara sel dan Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada peranti anda untuk kegunaan apl. Apl boleh menggunakan ini untuk menentukan tempat anda berada dan mungkin menggunakan kuasa bateri tambahan." - "lokasi anggaran (berasaskan rangkaian)" + "akses lokasi anggaran (berasaskan rangkaian)" "Membenarkan apl mendapatkan lokasi anggaran anda. Lokasi ini diperolehi oleh perkhidmatan lokasi menggunakan sumber lokasi rangkaian seperti menara sel dan Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada peranti anda untuk kegunaan apl. Apl boleh menggunakan ini untuk menentukan secara anggaran tempat anda berada." "tukar tetapan audio anda" "Membenarkan apl untuk mengubah suai tetapan audio global seperti kelantangan dan pembesar suara mana digunakan untuk output." "rakam audio" "Membenarkan apl untuk merakam audio menggunakan mikrofon. Kebenaran ini membenarkan apl untuk merakam audio pada bila-bila masa tanpa pengesahan anda." - "komunikasi sim" + "hantar perintah ke SIM" "Membenarkan apl menghantar arahan kepada SIM. Ini amat berbahaya." "ambil gambar dan video" "Membenarkan apl mengambil gambar dan video menggunakan kamera. Kebenaran ini membenarkan apl untuk menggunakan kamera pada bila-bila masa tanpa pengesahan anda." @@ -382,7 +382,7 @@ "Membenarkan apl mendapatkan senarai akaun yang dikenali oleh telefon. Ini mungkin termasuk sebarang akaun yang dibuat oleh aplikasi yang telah anda pasang." "lihat sambungan rangkaian" "Membenarkan apl melihat maklumat tentang sambungan rangkaian seperti rangkaian mana yang wujud dan bersambung." - "akses rangkaian penuh" + "mempunyai akses rangkaian penuh" "Membenarkan apl membuat soket rangkaian dan menggunakan protokol rangkaian tersuai. Penyemak imbas dan aplikasi lain menyediakan cara untuk menghantar data ke internet, jadi kebenaran ini tidak diperlukan untuk menghantar data ke internet." "tukar kesambungan rangkaian" "Membenarkan apl untuk mengubah keadaan kesambungan rangkaian." @@ -402,7 +402,7 @@ "Membenarkan apl mengkonfigurasikan telefon Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh." "sambung dan putuskan sambungan WiMAX" "Membenarkan apl menentukan sama ada WiMaX didayakan dan maklumat tentang sebarang rangkaian WiMaX yang disambungkan." - "Tukar keadaan WiMAX" + "tukar keadaan WiMAX" "Membenarkan apl untuk menyambungkan tablet ke dan menyahsambungkan tablet dari rangkaian WiMaX." "Membenarkan apl menyambungkan TV ke dan memutuskan sambungan TV daripada rangkaian WiMAX." "Membenarkan apl untuk menyambungkan telefon ke dan menyahsambung telefon dari rangkaian WiMaX." @@ -485,7 +485,7 @@ "Membenarkan apl mengubah suai parameter penentukuran skrin sentuh. Ini tidak sekali-kali diperlukan untuk apl biasa." "akses sijil DRM" "Membenarkan aplikasi memperuntuk dan menggunakan sijil DRM. Tidak sekali-kali diperlukan untuk apl biasa." - "Terima status pemindahan Pancaran Android" + "terima status pemindahan Pancaran Android" "Membenarkan aplikasi ini menerima maklumat mengenai pemindahan Pancaran Android semasa" "alih keluar sijil DRM" "Membenarkan aplikasi mengalih keluar sijil DRM. Tidak sekali-kali diperlukan untuk apl biasa." @@ -1091,11 +1091,11 @@ "Memformat…" "Tidak dimasukkan" "Tiada aktiviti yang sepadan ditemui." - "Buat laluan output media" + "halakan output media" "Membenarkan apl untuk membuat laluan output media ke peranti luaran lain." - "Baca sesi pemasangan" + "baca sesi pemasangan" "Membenarkan aplikasi membaca sesi pemasangan Ini membenarkan apl melihat butiran mengenai pemasangan pakej yang aktif." - "Minta pemasangan pakej" + "minta pakej pemasangan" "Membenarkan aplikasi meminta pemasangan pakej." "Sentuh dua kali untuk mendapatkan kawalan zum" "Tidak dapat menambahkan widget." diff --git a/core/res/res/values-my-rMM-watch/strings.xml b/core/res/res/values-my-rMM-watch/strings.xml index ec89e536dc2a9..813c7dafd6ae1 100644 --- a/core/res/res/values-my-rMM-watch/strings.xml +++ b/core/res/res/values-my-rMM-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d%1$d ‌အသေးစားဆော့ဝဲ" + "အာရုံခံကိရိယာများ" diff --git a/core/res/res/values-my-rMM/cm_strings.xml b/core/res/res/values-my-rMM/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-my-rMM/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml index e65be4d84223d..d0d06bdf5b609 100644 --- a/core/res/res/values-my-rMM/strings.xml +++ b/core/res/res/values-my-rMM/strings.xml @@ -254,7 +254,7 @@ "အရေးကြီးသော ကိုယ်ရေးအချက်အလက်များဖြစ်တဲ့ ခရက်ဒစ်ကဒ်နံပါတ်များနှင့် စကားဝှက်များ ပါဝင်ပါတယ်." "အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်" "appအား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။" - "အခြေအနေပြနေရာ" + "အခြေအနေပြ ဘားဖြစ်ပါစေ" "appအား အခြေအနေပြ ဘားဖြစ်ခွင့် ပြုသည်။" "အခြေအနေပြဘားအား ချဲ့/ပြန့်ခြင်း" "appအား အခြေအနေပြ ဘားကို ချဲ့ခွင့် သို့မဟုတ် ခေါက်သိမ်းခွင့် ပြုသည်။" @@ -282,7 +282,7 @@ "အပလီကေးရှင်းအား WAP စာများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။" "အလုပ်လုပ်နေကြသည့် appများကို ရယူခြင်း" "အပလီကေးရှင်းအား လက်ရှိနဲ့ လတ်တလော လုပ်ဆောင်ခဲ့သော သတင်းအချက်အလက် အသေးစိတ်အား ထုတ်ယူခွင့်ပြုရန်။ အပလီကေးရှင်းမှ သင် ဘယ် အပလီကေးရှင်းများသုံးရှိကြောင့် တွေ့ရှိနိုင်ပါသည်" - "ကိုယ်ရေးအချက်အလက်နှင့် စက်ပစ္စည်းပိုင်ရှင်များကို စီမံပါ" + "ကိုယ်ရေးအချက်အလက်နှင့် စက်ပစ္စည်း ပိုင်ရှင်များကို စီမံပါ" "ကိုယ်ရေးအချက်လက်ပိုင်ရှင်များနှင့်စက်ပစ္စည်းပိုင်ရှင်အား သတ်မှတ်ရန် App အားခွင့်ပြုပါ။" "အလုပ်လုပ်နေကြသည့် appများကို ပြန်လည်စီစဉ်ခြင်း" "အပလီကေးရှင်းအား နောက်ကွယ် နှင့် ရှေ့မှောက်တွင် လက်ရှိ လုပ်ဆောင်နေမှုများအား ဖယ်ခွင့် ပြုပါ။ သင့် ခွင့်ပြုချက်မပါပဲ လုပ်ဆောင်နိုင်ပါလိမ့်မည်" @@ -324,7 +324,7 @@ "အပလီကေးရှင်းအား သင့်တက်ဘလက်၏ ဖုန်းခေါ်ဆိုမှု မှတ်တမ်း (အဝင်အထွက်ခေါ်ဆိုမှု အချက်အလက်များ) ကို ပြင်ဆင်ခွင့် ပေးခြင်း။ အန္တရာယ်ရှိ အပလီကေးရှင်းများမှ ဤအချက်ကို အသုံးပြု၍ သင့် ဖုန်းခေါ်ဆိုမှု မှတ်တမ်းကို ဖျက်ပစ်ခြင်း၊ ပြင်ဆင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်" "အဝင်အထွက်ခေါ်ဆိုမှု အချက်အလက်များ အပါအဝင်၊ သင့်တီဗွီ၏ ဖုန်းခေါ်ဆိုမှု မှတ်တမ်းကို အပလီကေးရှင်းအား ပြင်ဆင်ခွင့်ပေးခြင်း။ အန္တရာယ်ရှိ အပလီကေးရှင်းများမှ ဤအချက်ကို အသုံးပြု၍ သင့် ဖုန်းခေါ်ဆိုမှု မှတ်တမ်းကို ဖျက်ပစ်ခြင်း၊ ပြင်ဆင်ခြင်းများ ပြုလုပ်နိုင်၏။" "အပလီကေးရှင်းအား သင့်ဖုန်း၏ ဖုန်းခေါ်ဆိုမှု မှတ်တမ်း (အဝင်အထွက်ခေါ်ဆိုမှု အချက်အလက်များ) ကို ပြင်ဆင်ခွင့် ပေးခြင်း။ အန္တရာယ်ရှိ အပလီကေးရှင်းများမှ ဤအချက်ကို အသုံးပြု၍ သင့် ဖုန်းခေါ်ဆိုမှု မှတ်တမ်းကို ဖျက်ပစ်ခြင်း၊ ပြင်ဆင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်" - "ခန္ဓာကိုယ် အာရံခံကိရိယာများ (နှလုံးခုန်နှုန်း စောင့်ကြည့်စက် လို)" + "ခန္ဓာကိုယ် အာရုံကိရိယာများကို (နှလုံးခုန်နှုန်း မော်နီတာလို)ကို ရယူသုံးရန်" "သင်၏ နှလုံးခုန်နှုန်းလို ရုပ်ပိုင်း အခြေအနေကို စောင့်ကြပ်သည့် အာရုံခံစက်များထံမှ ဒေတာများကို appအား ရယူသုံးခွင့် ပြုပါ။" "ပြက္ခဒိန်အဖြစ်အပျက်များနှင့် လှို့ဝှက်အချက်အလက်များအား ဖတ်ခြင်း" "အပလီကေးရှင်းအား တက်ဘလက်ထဲတွင် သိမ်းထားသော သူငယ်ချင်းနှင့် လုပ်ဖော်ကိုင်ဘက်များ၏ ပြက္ခဒိန် အဖြစ်အပျက်များအပါအဝင် အားလုံးကို ဖတ်ရှုခွင့်ပြုပါ။ ဒီခွင့်ပြုချက်ကြောင့် အပလီကေးရှင်းမှ ပြက္ခဒိန် အဖြစ်အပျက်များအား လျှို့ဝှက်မှု သို့ ဂရုပြုမှု ကို ထည့်သွင်းမစဉ်းစားပဲ သိမ်းဆည်းခြင်း၊ မျှဝေခြင်း ပြုလုပ်စေနိုင်ပါသည်" @@ -336,15 +336,15 @@ "အပလီကေးရှင်းအား သင်၏ ဖုန်းတွင် သူငယ်ချင်း အလုပ်ဖော်များ အပါအဝင် သင်၏ ပြောင်းလဲအဖြစ်အပျက်များအား ထည့်ခြင်း၊ ထုတ်ခြင်းအား ခွင့်ပြုရန်။ ဤခွင့်ပြုချက်သည် အပလီကေးရှင်းအား သတင်းများပို့ခြင်းကို ပြက္ခဒိန်ပိုင်ရှင်ဆီမှ လာသလို အနေဖြင့် ပေးပို့ခြင်း သို့မဟုတ် အဖြစ်အပျက်များကို ပိုင်ရှင်မသိပဲ ပြင်ဆင်နိုင်ပါသည်။" "တည်နေရာပံ့ပိုးမှုညွှန်ကြားချက်အပိုအား ဝင်ရောက်ကြည့်ခြင်း" "appအား တည်နေရာ စီမံပေးရေး ညွှန်ကြားချက် အပိုများကို ရယူခွင့်ပြုသည်။ သို့ဖြစ်၍ appသည် GPS သို့မဟုတ် အခြား တည်နေရာ ရင်းမြစ်ကို သုံးကြသူတို့၏ လုပ်ငန်းများကို ဝင်စွက်ခွင့် ပြုနိုင်သည်။" - "တည်နေရာ အတိအကျ (ဂျီပီအက်စ် နှင့် ကွန်ရက်အခြေခံ)" + "တိကျတဲ့ တည်နေရာ (GPS နှင့် ကွန်ရက် အခြေခံ)ကို ရယူသုံးရန်" "အပလီကေးရှင်းမှ သင့်ရဲ့ တိကျသောနေရာကို ဂျီပီအက်စ် သို့ ဆယ်လူလာတာဝါတိုင်၊ ဝိုင်ဖိုင် အချက်အလက်များ သုံးပြီး ရှာခြင်း ခွင့်ယူပါ။ နေရာပြ ဆားဗစ်များ စက်ပေါ်မှာ ရှိရမှာ ဖြစ်သလို ဖွင့်ထားရမှာလည်း ဖြစ်ပါသည်။ အပလီကေးရှင်းမှ ဒီဆားဗစ်များကို သုံး၍ ရှာဖွေသောကြောင့် ဘက်ထရီ ပိုကုန်နိုင်ပါသည်။" - "အကြမ်းဖျင်းနေရာ (ကွန်ရက်အခြေခံ)" + "အနီးစပ်ဆုံး တည်နေရာ (ကွန်ရက် အခြေခံ)ကို ရယူသုံးရန်" "သင့်ရဲ့ ပျမ်းမျတည်နေရာကို အပလီကေးရှင်း အား သိခွင့် ပြုရန်။ ဒီ တည်နေရာကို တည်နေရာရှာဖွေရေး ဆားဗစ်မှ မိုဘိုင်း တာဝါတိုင်၊ ဝိုင်ဖိုင် စသည်တို့မှ တဆင့် ရယူပါသည်။ အပလီကေးရှင်း အနေဖြင့် ဒီ ဆားဗစ်များ ရှိနေရန် လိုအပ်ပါသည်။ ဒီအရာများကို အသုံးပြု၍ သင့်နေရာကို သိနိုင်ပါသည်။" "သင့်အသံအပြင်အဆင်အားပြောင်းခြင်း" "အပလီကေးရှင်းအား အသံအတိုးအကျယ်နှင့် အထွက်ကို မည်သည့်စပီကာကို သုံးရန်စသည်ဖြင့် စက်တစ်ခုလုံးနှင့်ဆိုင်သော အသံဆိုင်ရာ ဆက်တင်များ ပြင်ဆင်ခွင့် ပြုရန်" "အသံဖမ်းခြင်း" "အပလီကေးရှင်းအား မိုက်ခရိုဖုန်းဖြင့် အသံသွင်းခွင့် ပြုပါ။ အပလီကေးရှင်းအနေဖြင့် သင့် ခွင့်ပြုချက် မပါပဲ အချိန်မရွေး အသံဖမ်းနိုင်ပါမည်" - "ဆင်းမ်ကဒ် ဆက်သွယ်ရေး" + "SIM ထံသို့ ညွှန်ကြားချက်များကို ပို့ပါ" "အပလီကေးရှင်းအား ဆင်းမ်ကဒ်ဆီသို့ အမိန့်များ ပေးပို့ခွင့် ပြုခြင်း။ ဒီ ခွင့်ပြုမှုဟာ အန်တရယ် အလွန် ရှိပါသည်။." "ဓါတ်ပုံနှင့်ဗွီဒီယိုရိုက်ခြင်း" "အပလီကေးရှင်းအား အလိုအလျောက် ဓာတ်ပုံရိုက်ခွင့်၊ ဗီဒီယို ရိုက်ကူးခွင့် ပြုပါ။ ဒီခွင့်ပြုချက်က အပလီကေးရှင်းကို အချိန်မရွေး ကင်မရာအား ခွင့်ပြုချက် မလိုအပ်ပဲ သုံးခွင့်ပြုပါသည်။" @@ -382,7 +382,7 @@ "အပလီကေးရှင်းအား ဖုန်းမှ သိရှိထားသော အကောင့်စာရင်းများအား ရယူခွင့်ပေးပါ။ ဒီထဲတွင် သင် ထည့်သွင်းထားသော အပလီကေးရှင်းများမှတဆင့် ပြုလုပ်ထားသော အကောင့်များပါ ပါဝင်နိုင်ပါသည်။" "ကွန်ရက် ချိတ်ဆက်မှုများအား ကြည့်ရန်" "အပလီကေးရှင်းအား မည်သည့်ကွန်ရက်နက်ဝဘ်ရှိသလဲ၊ မည်သည့်ကွန်ရက်နှင့် ချိတ်ဆက်ထားလဲ စသည်ဖြင့် ကွန်ရက်ချိတ်ဆက်မှုများ၏ သတင်းအချက်အလက်များကို ကြည့်ခွင့်ပေးရန်" - "အပြည့်အ၀ ကွန်ရက်သုံးခွင့်ရရန်" + "ကွန်ရက်ကို အပြည့်အဝ ရယူသုံးနိုင်" "အပလီကေးရှင်းအား ကွန်ရက်ဆော့ကတ်များ တည်ဆောက်ခွင့်၊ တသီးတသန့် ကွန်ရက် ပရိုတိုကောလ်များ သုံးခွင့် ပြုပါ။ အင်တာနက်မှ အချက်အလက်များ ပေးပို့ခြင်းကို ဘရောက်ဇာနှင့် တခြား အပလီကေးရှင်းများက လုပ်ဆောင်ပေးသောကြောင့် ဒီခွင့်ပြုချက်က အင်တာနက်မှ အချက်အလက် ပေးပို့ခြင်း မလိုအပ်ပါ" "ကွန်ယက်ဆက်သွယ်မှုအားပြောင်းခြင်း" "appအား ကွန်ရက် ချိတ်ဆက်နိုင်စွမ်း အခြေအနေကို ပြောင်းလဲခွင့် ပြုသည်။" @@ -402,7 +402,7 @@ "appအား ဒေသန္တရ ဘလူးတုသ် ဖုန်းကို စီစဉ်ဖွဲ့စည်းခွင့်ကို၎င်း၊ အဝေးထိန်း ကိရိယာများကို ရှာကြံလျက် ချိတ်တွဲခွင့်ကို၎င်း ပေးထားသည်။" "ဝိုင်မက်စ် နှင့် ချိတ်ဆက်ရန်နှင့် ဆက်သွယ်မှု ဖြတ်တောက်ရန်" "အပလီကေးရှင်းအား ဝိုင်မက်စ် အခြေအနေ ကြည့်ခွင့်ပေးရန် ဥပမာ ဝိုင်မက်စ် ဖွင့်ထား မထား၊ ဝိုင်မက်စ် ချိတ်ဆက်ထားသော ကွန်ရက်အခြေအနေ" - "ဝိုက်မက်စ် အခြေအနေအား ပြင်ရန်" + "WiMAX အခြေအနေကို ပြောင်းရန် ပြင်ရန်" "အပလီကေးရှင်းအား တက်ဘလက်ကို ဝိုင်မက်စ် ကွန်ရက်များနဲ့ ဆက်သွယ်ခြင်း၊ ဆက်သွယ်မှု ရပ်ဆိုင်းခြင်းများ လုပ်ခွင့်ပြုပါ" "တီဗွီနှင့် ချိတ်ဆက်ရန် app အား ခွင့်ပြုပြီး တီဗွီနှင့် WiMAX ကွန်ယက်များ ချိတ်ဆက်ထားမှုအား ဖြတ်တောက်ပါ။" "အပလီကေးရှင်းအား ဖုန်းကို ဝိုင်မက်စ် ကွန်ရက်များနဲ့ ဆက်သွယ်ခြင်း၊ ဆက်သွယ်မှု ရပ်ဆိုင်းခြင်းများ လုပ်ခွင့်ပြုပါ" @@ -485,7 +485,7 @@ "appအား တို့ထိရေး မျက်နှာပြင် တိုင်းထွာစံညှိမှုကို မွမ်းမံခွင့် ပြုသည်။ သာမန် appများ ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။" "DRM လက်မှတ်များကို ရယူသုံးခြင်း" "အပလီကေးရှင်း တစ်ခုအား စီမံလုပ်ကိုင်ခွင့် DRM လက်မှတ်များ သုံးခွင့် ပြုသည်။ သာမန် appများ အတွက် ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။" - "အန်ဒရွိုက်၏ အလင်းတန်းထိုး လွှဲပြောင်းမှု အခြေအနေကို ရယူရန်" + "Android ရဲ့ အလင်းတန်းထိုး လွှဲပြောင်းမှု အခြေအနေကို ရယူရန်" "ဒီအပလီကေးရှင်းအား အန်ဒရွိုက်၏ လက်ရှိ အလင်းတန်းထိုး လွှဲပြောင်းမှု အကြောင်း အချက်အလက်ကို ရယူခွင့် ပြုသည်" "DRM လက်မှတ်များ ဖယ်ရှားရန်" "အပလီကေးရှင်းအား DRM လက်မှတ်များကို ဖယ်ရှားခွင့် ပြုသည်။ သာမန် appများ အတွက် ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။" @@ -1091,11 +1091,11 @@ "ပုံစံပြင်နေစဉ်…" "ဖြည့်စွက်ထားခြင်း မရှိပါ" "တိုက်ဆိုင်သော ပြုလုပ်ချက် ရှာမတွေ့ပါ" - "မီဒီယာထွက်ပေါက်အား လမ်းလွှဲပြောင်းခြင်း" + "မီဒီယာ ထွက်ပေါက်ကို လမ်းဖေါ်ပြပေးပါ" "အပလီကေးရှင်းအား မီဒီယာ ထုတ်လွှတ်မှုကို အခြားပြင်ပ စက်ပစ္စည်းများသို့ လွှဲပြောင်းခွင့်ပြုပါ" - "တပ်ဆင်ရေး ချိတ်ဆက်မှုများကို ဖတ်ရန်" + "တပ်ဆင်ရေး လုပ်ကိုင်မှုကို ဖတ်ရန်" "အပလီကေးရှင်းအား တပ်ဆင်ရေး ချိတ်ဆက်မှုများကို ဖတ်ခွင့်ပြုသည်။ ၎င်းသည် ဖွင့်သုံးနေသည့် အထုပ်အား တပ်ဆင်မှုဆိုင်ရာ အသေးိစတ်များကို ကြည့်ရှုခွင့် ပြုသည်။" - "ပက်ကေ့များ သွင်းယူရန် တောင်းဆိုပါ" + "တပ်ဆင်ရေး အထုပ်များကို တောင်းဆိုပါ" "ပက်ကေ့များ သွင်းယူခြင်းအတွက် တောင်းဆိုရန် အပ္ပလီကေးရှင်းအား ခွင့်ပြုပါ" "ချုံ့ချဲ့မှုကို ထိန်းချုပ်ရန် အတွက် နှစ်ကြိမ် ထိပါ" "ဝဒ်ဂျက်ထည့်လို့ မရပါ" diff --git a/core/res/res/values-nb-watch/strings.xml b/core/res/res/values-nb-watch/strings.xml index 3bd7fa50f60de..e6da48ac3368f 100644 --- a/core/res/res/values-nb-watch/strings.xml +++ b/core/res/res/values-nb-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d av %2$d." + "Sensorer" diff --git a/core/res/res/values-nb/cm_strings.xml b/core/res/res/values-nb/cm_strings.xml new file mode 100644 index 0000000000000..d1cfdaf8b625c --- /dev/null +++ b/core/res/res/values-nb/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Skjermbilde + + motta beskyttet SMS + + Lar programmet motta innkommende beskyttede SMS. + + endre beskyttede SMS-listen + + Lar programmet endre adresselisten for beskyttede SMS. + + Sikkerhet + + Tillatelser knyttet til enhetens sikkerhetsinformasjon. + + les telefonens svarteliste + + Tillater en app å lese informasjon om telefonnummer som er blokkert for innkommende samtaler eller meldinger. + + endre telefonens svarteliste + + Tillater en app å endre telefonnummer som er blokkert for innkommende samtaler eller meldinger. + + Angi tastaturbakgrunn + + Tillat en app å endre låseskjermsbakgrunn. + + Start på nytt + + Nåværende + + + Start på nytt + + Gjenoppretting + + Bootloader + + Download + + Myk omstart + + Omstart + + Nettbrettet startes på nytt. + Telefonen startes på nytt. + + Starter på nytt\u2026 + + App stoppet + + ADB over nettverk aktivert + + ADB over USB & nettverk aktivert + + Trykk for å deaktivere feilsøking. + + ADB – %1$s + USB og nettverk + USB + Nettverk + + avbryt app start + + %s er ikke installert + + Prioritet + Ingen + + Deaktivert Wi-Fi hotspot på grunn av endring i SIM-abbonement + + Deaktiver Wi-Fi + + aktivere eller deaktivere personvernvakt + Lar appen endre om en annen app kjører med personlighetsvern. Når en app kjører med personlighetsvern vil den ikke ha tilgang til personlig data som kontakter, samtalelogg eller meldinger. + Personvernvakt aktiv + %1$s vil ikke få tilgang til personlige data + Personvernvakt + %1$s vil gjerne %2$s. + + Husk mitt valg + + tilgang til kameraet + tilgang til din plassering + lese dine varsler + aktiver en VPN + start under oppstart + Slett samtaleloggen + Slett kontaktene dine + slett dine MMS-meldinger + slett dine SMS-meldinger + tegn vinduer på topp + få brukstatistikk over app + holde enheten våken + utføre en samtale + oppdatere kalenderen + oppdatere samtaleloggen + endre utklippstavlen + Oppdater kontaktene + oppdatere systeminnstillinger + Demp/fjern demping av mikrofonen + spille av lyd + legge inn en melding + Prosjekt media + lese kalenderen + lese i samtaleloggen + lese utklippstavlen + lese kontaktene + lese MMS meldinger + lese SMS-meldinger + motta en SMS-melding + spille inn lyd + sende en MMS-melding + sende en tekstmelding + starte under oppstart + vis toast meldinger + slå av/på Bluetooth + slå av/på mobildata + slå av/på NFC + slå av/på Wi-Fi + styre alarmvolum + styre lydfokus + styre bluetooth volum + styre hovedvolum + bruke mediaknappene + styre mediavolum + styre varslingsvolum + styre ringevolum + Bruk haptisk tilbakemelding + styre stemmesamtalevolum + skrive en MMS-melding + skrive en tekstmelding + bruk fingeravtrykk + legge til en telefonsvarer + hente telefontilstand + skann trådløse nettverk + endre bakgrunnsbilde + bruke hjelpestruktur + ta et skjermbilde + bruke enhetssensorer + lese cellekringkastinger + simulere posisjon + lese fra ekstern lagring + skrive til ekstern lagring + slå skjermen på + hente enhetskontoer + endre Wi-Fi-tilstand + få root-tilgang + + For å unpin denne skjermen, trykk og hold tilbake-knappen. + + Ingen tilkoblede enheter + %1$s tilkoblet enhet + %1$s tilkoblede enheter + + + + Aktivitets oppstart blokkert + %1$s er beskyttet mot oppstart. Trykk for å godkjenne og starte programmet. + + Batteriet er fullt oppladet + Koble enheten fra laderen for å forbedre batteri levetid. + + tilbakestill batteristatistikk + + Tillater at et program kan tilbakestille nåværende bruksdata om lavt batteri. + + SIM-kort er endret + Tappe for å angi standardinnstillinger for SIM-kortet + diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index b538fd30418c1..2c3d881983a69 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -229,7 +229,7 @@ "Kontakter" "se kontaktene dine" "Posisjon" - "tilgang til enhetens plassering" + "få tilgang til enhetens plassering" "Kalender" "åpne kalenderen din" "SMS" @@ -254,7 +254,7 @@ "Dette omfatter personlige data, som kredittkortnumre og passord." "deaktivere eller endre statusfeltet" "Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner." - "statusrad" + "vise appen i statusfeltet" "Gir appen tillatelse til å vises i statusfeltet." "utvide/slå sammen statusfeltet" "Lar appen utvide eller skjule statuslinjen." @@ -282,7 +282,7 @@ "Lar appen motta og behandle WAP-meldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til deg uten at du har sett dem." "hente apper som kjører" "Lar appen hente informasjon om oppgaver som kjører og som nylig har kjørt. Dette kan tillate appen å oppdage informasjon om hvilke apper som brukes på enheten." - "Administrer profiler og enhetseiere" + "administrere profiler og enhetseiere" "Lar apper angi profileierne og enhetseieren." "Endre rekkefølge på apper som kjører" "Lar appen flytte oppgaver til forgrunnen eller bakgrunnen. Appen kan gjøre dette uten instruksjoner fra deg." @@ -324,7 +324,7 @@ "Lar appen endre nettbrettets samtalelogg, inkludert data om innkommende og utgående anrop. Skadelige apper kan utnytte denne tillatelsen til å slette eller endre samtaleloggen din." "Gjør at appen kan endre TV-ens samtalelogg, herunder data om innkommende eller utgående samtaler. Skadelige apper kan bruke dette til å slette eller endre samtaleloggen." "Lar appen endre telefonens samtalelogg, inkludert data om innkommende og utgående anrop. Skadelige apper kan utnytte denne tillatelsen til å slette eller endre samtaleloggen din." - "kroppssensorer (som pulsmålere)" + "få tilgang til kroppssensorer (f.eks. pulsmålere)" "Gir appen tilgang til data fra sensorer som overvåker den fysiske tilstanden din, for eksempel hjertefrekvensen din." "lese kalenderhendelser og konfidensiell informasjon" "Lar appen lese alle kalenderaktivitetene lagret på nettbrettet ditt, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen deler eller lagrer kalenderinformasjonen din uavhengig av konfidensialitet og sensitivitet." @@ -336,15 +336,15 @@ "Lar appen legge til, fjerne og endre aktiviteter du kan redigere på telefonen din, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen sender meldinger som ser ut som om de kommer fra kalendereiere eller endre aktiviteter uten at eierne vet om det." "bruke ekstra posisjonskommandoer" "Appen gis tillatelse til å bruke ekstra kommandoer fra posisjonsleverandører. Dette kan gi appen tillatelse til å påvirke bruken av GPS eller andre posisjonskilder." - "presis posisjon (GPS- og nettverksbasert)" + "få tilgang til nøyaktig posisjon (GPS- og nettverksbasert)" "Lar appen se den nøyaktige posisjonen din ved hjelp av GPS (Global Positioning System) eller posisjonstjenester for nettverk, som for eksempel basestasjoner og Wi-Fi. Disse posisjonstjenestene må være slått på og tilgjengelig for enheten din, for at appen skal kunne bruke dem. Apper kan bruke dette til å fastslå hvor du er, og funksjonen kan medføre økt batteribruk." - "omtrentlig posisjon (nettverksbasert)" + "få tilgang til omtrentlig posisjon (nettverksbasert)" "Lar appen se den omtrentlige posisjonen din. Denne posisjonen hentes fra posisjonstjenester som benytter posisjonskilder som for eksempel basestasjoner og Wi-Fi. Disse posisjonstjenestene må være slått på og tilgjengelig for enheten din, for at appen skal kunne bruke dem. Apper kan bruke dette til å finne ut omtrent hvor du er." "endre lydinnstillinger" "Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydavspilling." "ta opp lyd" "Appen tillates å ta opp lyd med mikrofonen. Det betyr at appen kan ta opp lyd når som helst uten at du har bedt om det." - "sim-kommunikasjon" + "sende kommandoer til SIM-kortet" "Lar appen sende kommandoer til SIM-kortet. Dette er veldig farlig." "ta bilder og videoer" "Appen tillates å ta bilder og filme med kameraet. Det betyr at appen kan bruke kameraet når som helst uten bekreftelse fra deg." @@ -382,7 +382,7 @@ "Appen kan hente listen over kontoene telefonen kjenner. Dette kan inkludere kontoer som er opprettet av apper du har installert." "se nettverkstilkoblinger" "Appen kan se informasjon om nettverkstilkoblinger, slik som hvilke nettverk som finnes og er tilkoblet." - "full nettverkstilgang" + "få full nettverkstilgang" "Appen kan opprette nettverkskontakter og bruke tilpassede nettverksprotokoller. Nettleseren og andre apper gjør det mulig å sende data til Internett, så denne tillatelsen er ikke nødvendig for å kunne sende data til Internett." "endre nettverkskonnektivitet" "Lar appen endre innstillingene for nettverkstilknytning." @@ -402,7 +402,7 @@ "Lar appen konfigurere den lokale Bluetooth-telefonen, samt oppdage og koble sammen med eksterne enheter." "koble til eller fra WiMAX" "Lar appen avgjøre hvorvidt WiMAX er aktivert og finne informasjon om eventuelle tilkoblede WiMAX-nettverk." - "Endre WiMAX-status" + "endre WiMAX-status" "Lar appen koble nettbrettet til og fra WiMAX-nettverk." "Gjør at appen kobler TV-en til og fra WiMAX-nettverk." "Lar appen koble telefonen til og fra WiMAX-nettverk." @@ -485,7 +485,7 @@ "Lar appen endre kalibrasjonsparametrene for berøringsskjermen. Denne tillatelsen bør aldri være nødvendig for vanlige apper." "tilgang til DRM-sertifikater" "Tillater at en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper." - "Motta overføringsstatus for Android Beam" + "motta overføringsstatus for Android Beam" "Lar appen motta informasjon om aktuelle Android Beam-overføringer" "fjern sertifikater for digital rettighetsadministrasjon" "Gir en app tillatelse til å fjerne sertifikater for digital rettighetsadministrasjon. Skal ikke være nødvendig for vanlige apper." @@ -1091,11 +1091,11 @@ "Formatering …" "Ikke satt inn" "Finner ingen samsvarende aktiviteter." - "Videresending av medieutdata" + "videresende medieutdata" "Lar en app videresende medieutdata til andre eksterne enheter." - "lese installeringsøkter" + "lese installeringsøkter" "Tillater en app å lese installeringsøkter. Dette gjør det mulig for den å se detaljer om aktive pakkeinstallasjoner." - "Be om installasjon av pakker" + "be om installasjon av pakker" "Lar apper be om installasjon av pakker." "Trykk to ganger for zoomkontroll" "Kunne ikke legge til modulen." diff --git a/core/res/res/values-ne-rNP-watch/strings.xml b/core/res/res/values-ne-rNP-watch/strings.xml index e2453c89eac6f..759612d430ad3 100644 --- a/core/res/res/values-ne-rNP-watch/strings.xml +++ b/core/res/res/values-ne-rNP-watch/strings.xml @@ -21,4 +21,5 @@ "%2$d को %1$d अनुप्रयोग।" + "सेन्सरहरू" diff --git a/core/res/res/values-ne-rNP/cm_strings.xml b/core/res/res/values-ne-rNP/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-ne-rNP/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml index 0d5460291b838..71f62ae8bf735 100644 --- a/core/res/res/values-ne-rNP/strings.xml +++ b/core/res/res/values-ne-rNP/strings.xml @@ -254,7 +254,7 @@ "व्यक्तिगत डेटा जस्तै क्रेडिट कार्ड नम्बरहरू र पासवर्डहरू समावेश गर्दछ।" "स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्" "स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।" - "स्थिति पट्टि" + "वस्तुस्थिति पट्टी हुन दिनुहोस्" "अनुप्रयोगलाई स्थिति पट्टि हुन अनुमति दिन्छ।" "स्थिति पट्टिलाई विस्तृत/सङ्कुचित गर्नुहोस्" "अनुप्रयोगलाई स्थिति पट्टि विस्तार वा संकुचन गर्न अनुमति दिन्छ।" @@ -282,7 +282,7 @@ "WAP सन्देशहरू प्राप्त गर्न र प्रशोधन गर्न अनुप्रयोगलाई अनुमति दिन्छ। यो अनुमतिमा मोनिटर गर्ने वा तपाईँलाई पठाइएका सन्देशहरू तपाईँलाई नदेखाई मेट्ने क्षमता समावेश हुन्छ।" "चलिरहेका अनुप्रयोगहरू पुनःबहाली गर्नुहोस्" "वर्तमानमा र भरखरै चलिरहेका कार्यहरू बारेको सूचना पुनःबहाली गर्न अनुप्रयोगलाई अनुमित दिन्छ। यसले उपकरणमा प्रयोग भएका अनुप्रयोगहरूको बारेमा सूचना पत्ता लगाउन अनुप्रयोगलाई अनुमति दिन सक्छ।" - "प्रोफाइल र यन्त्र मालिकहरू व्यवस्थापन गर्नुहोस्" + "प्रोफाइल र यन्त्र मालिकहरूको व्यवस्थापन गराउनुहोस्" "अनुप्रयोगहरूलाई प्रोफाइल र यन्त्र मालिकहरू सेट गर्न अनुमति दिनुहोस्।" "चलिरहेका अनुप्रयोगहरूलाई पुनःक्रम गराउनुहोस्" "कामहरूलाई अग्रभाग र पृष्ठभूमिमा सार्न अनुप्रयोगलाई अनुमति दिन्छ। अनुप्रयोगले यो तपाईँको इनपुट बिना नै गर्न सक्छ।" @@ -324,7 +324,7 @@ "आगमन तथा बहर्गमन डेटासहित तपाईँको ट्याब्लेटको कल लगको परिमार्जन गर्न अनुप्रयोगलाई अनुमति दिन्छ। खराब अनुप्रयोगहरूले यसलाई तपाईँको कल लग परिमार्जन गर्न वा मेटाउन प्रयोग गर्न सक्छन्।" "अनुप्रयोगहरूलाई अनुमति दिन्छ तपाईँको TV को कल लग, आगमन र बहिर्गमन कलका डेटा लगायत, परिमार्जन गर्न। दुस्प्रभावी अनुप्रयोगहरूले यसलाई तपाईँको कल लग मेट्न वा परिमार्जन गर्न सक्छ।" "अनुप्रयोगलाई तपाईंको फोनको आउने र बाहिर जाने कलहरूको बारेको डेटा सहित कल लग परिमार्जन गर्न अनुमति दिन्छ। खराब अनुप्रयोगहरूले यसलाई तपाईंको कल लग मेटाउन वा परिमार्जन गर्न प्रयोग गर्न सक्दछ।" - "शरीर सेन्सर (हृदयदर मोनिटर जस्तै)" + "शरीरका सेन्सरहरूमा पहुँच गराउनुहोस् (जस्तै हृदय धड्कन निगरानीहरू)" "तपाईँको हृदय गति जस्तो सेंसर बाट डेटा पहुँचको लागि अनुप्रयोग अनुमति दिन्छ जसले तपाईँको भौतिक अवस्था अनुगमन गर्छ।" "गोप्य जानकारी र पात्रो घटनाहरू पढ्नुहोस्" "अनुप्रयोगलाई तपाईंको ट्याब्लेटमा भण्डारण गरिएका ती साथीहरू वा सहयोगीहरू सहितको पात्राका कार्यक्रमहरू पढ्न अनुमति दिन्छ। यसले गोपनीयता वा संवेदनशीलता बिना पनि अनुप्रयोगलाई तपाईंको पात्राका डेटा साझेदारी गर्न वा बचत गर्न अनुमति दिन्छ।" @@ -336,15 +336,15 @@ "ती साथीहरू वा सहकर्मीहरूसहित तपाईँको फोनका घटनाहरू जसलाई थप्न, हटाउन र परिवर्तन गर्न अनुप्रयोगलाई अनुमति दिन्छ। पात्रो मालिकबाट देखा परेका वा मालिकको ज्ञान बिना परिवर्तन भएका घटनाहरू सन्देश पठाउन यसले अनुप्रयोगलाई अनुमति दिन सक्छ।" "अधिक स्थान प्रदायक आदेशहरू पहुँच गर्नुहोस्" "अनुप्रयोगलाई अतिरिक्त स्थान प्रदायक आदेशहरू पहुँच गर्न अनुमति दिन्छ। यो अनुप्रयोगलाई GPS वा अन्य स्थान स्रोतहरूको संचालन साथै हस्तक्षेप गर्न अनुमति दिन सक्छ।" - "सटिक स्थान (GPS र नेटवर्क आधारित)" + "सटीक स्थान पहुँच गराउनुहोस् (GPS तथा नेटवर्कमा आधारित)" "अनुप्रयोगले विश्वव्यापी स्थान प्रणाली (GPS) वा सेल टावरहरू र वाइफाइ जस्ता नेटवर्क स्थान स्रोतहरूको प्रयोग गरेर तपाईँको सही स्थान प्राप्त गर्न अनुमति दिन्छ। यी स्थान सेवाहरू खोल्नु पर्छ र अनुप्रयोगहरूका लागि प्रयोग गर्न तपाईँको उपकरणमा उपलब्ध हुनु पर्छ। अनुप्रयोगहरूले तपाईँ कहाँ हुनु हुन्छ भन्ने निर्धारण गर्न यसलाई प्रयोग गर्न सक्छ र यसले अतिरिक्त ब्याट्रि उर्जा खतप गर्न सक्छ।" - "अनुमानित स्थान (नेटवर्क-आधारित)" + "अनुमानित स्थान पहुँच गराउनुहोस् (नेटवर्कमा आधारित)" "अनुप्रयोगलाई तपाईँको अनुमानित स्थान प्राप्त गर्न अनुमति दिन्छ। यो स्थान सेल टावर र वाइ-फाइजस्ता नेटवर्क स्थान स्रोतहरूको प्रोग गरी स्थान सेवाहरूबाट उत्पन्न गरिएको हो। अनुप्रयोगले यी स्थान सेवाहरूको उपयोग गर्नको लागि यी सेवाहरू तपाईँको उपकरणमा चालु र उपलब्ध हुनु आवश्यक छ। अनुप्रयोगहरूले अनुमानित रूपमा तपाईँ कहाँ हुनुहुन्छ भन्ने निर्धारण गर्न यसको प्रयोग गर्न सक्छन्।" "तपाईँका अडियो सेटिङहरू परिवर्तन गर्नुहोस्" "अनुप्रयोगलाई ग्लोबल अडियो सेटिङ्हरू परिमार्जन गर्न अनुमति दिन्छ, जस्तै आवाजको मात्रा र आउटपुटको लागि कुन स्पिकर प्रयोग गर्ने।" "अडियो रेकर्ड गर्नुहोस्" "अनुप्रयोगलाई माइक्रोफोनको साथ अडियो रेकर्ड गर्न अनुमति दिन्छ। यस अनुमतिले तपाईंको पुष्टिकरण बिना कुनै पनि समयमा अडियो रेकर्ड गर्न अनुमति दिन्छ।" - "sim सञ्‍चार" + "SIM मा आदेशहरू पठाउन दिनुहोस्" "SIM लाई आदेश पठाउन अनुप्रयोगलाई अनुमति दिन्छ। यो निकै खतरनाक हुन्छ।" "तस्बिरहरू र भिडियोहरू लिनुहोस्।" "अनुप्रयोगलाई क्यामेरासँग तस्बिर र भिडियोहरू लिन अनुमति दिन्छ। यस अनुमतिले अनुप्रयोगलाई तपाईंको पुष्टिकरण बिना कुनै पनि समयमा क्यामेरा प्रयोग गर्न स्वीकृति दिन्छ।" @@ -382,7 +382,7 @@ "फोनलाई थाहा भएका खाताहरूको सूची प्राप्त गर्न अनुप्रयोगलाई अनुमति दिन्छ। यसले तपाईँले स्थापना गर्नु भएका अनुप्रयोगहरूबाट सृजित कुनै खाताहरू समावेश हुन सक्छ।" "नेटवर्क जडानहरू हेर्नहोस्" "अनुप्रयोगलाई नेटवर्क जडानहरू जस्तै कुन नेटवर्कहरू अवस्थित हुन्छन् र जडित छन् जसले हेर्नलाई अनुमति दिन्छ।" - "पूर्ण नेटवर्क पहुँच" + "पूर्ण नेटवर्क पहुँच प्राप्त छ" "नेटवर्क सकेटहरू सिर्जना गर्न र कस्टम नेटवर्क प्रोटोकल प्रयोग गर्न अनुप्रयोगलाई अनुमति दिन्छ। ब्राउजर र अन्य अनुप्रयोगहरूले इन्टरनेटमा डेटा पठाउने माध्यम प्रदान गर्छन्, त्यसैले इन्टरनेटमा डेटा पठाउन यो अनुमतिको आवश्यकता पर्दैन।" "नेटवर्क जडान परिवर्तन गर्नुहोस्" "अनुप्रयोगलाई नेटवर्क जडानको स्थिति परिवर्तन गर्न अनुमति दिन्छ।" @@ -402,7 +402,7 @@ "अनुप्रयोगलाई स्थानीय ब्लुटुथ फोन कन्फिगर गर्न र टाढाका उपकरणहरूसँग खोज गर्न र जोडी गर्न अनुमति दिन्छ।" "WiMAXसँग जोड्नुहोस् वा छुटाउनुहोस्" "अनुप्रयोगलाई वाइम्याक्स सक्षम छ कि छैन र जडान भएको कुनै पनि वाइम्याक्स नेटवर्कहरूको बारेमा जानकारी निर्धारिण गर्न अनुमति दिन्छ।" - "वाइम्याक्स स्थिति परिवर्तन गर्नुहोस्" + "वाइम्याक्स अवस्था परिवर्तन गर्नुहोस्" "अनुप्रयोगलाई वाइम्याक्स नेटवर्कहरूबाट ट्याब्लेट जडान गर्न र ट्याब्लेट विच्छेदन गर्न अनुमति दिन्छ।" "अनुप्रयोगलाई अनुमति दिन्छ TV लाई जडान गर्न र WiMAX सञ्जालबाट TV को जडान टुटाउन" "वाइम्याक्स नेटवर्कहरूसँग फोन जोड्न र छुटाउन अनुप्रयोगलाई अनुमति दिन्छ।" @@ -485,7 +485,7 @@ "अनुप्रयोगलाई टच स्क्रीनको प्यारामिटरहरू क्यालिब्रेसन परिमार्जन गर्न अनुमति दिन्छ। साधारण अनुप्रयोगहरूको लागि कहिल्यै आवश्यक पर्दैन।" "DRM प्रमाणपत्रको पहुँच" "DRM प्रमाणपत्रहरू प्रावधान र प्रयोग गर्ने निवेदनको अनुमति दिन्छ। साधारण अनुप्रयोगहरूको लागि कहिल्यै पनि आवश्यक पर्दैन।" - "Android Beam स्थानान्तरण अवस्था प्राप्त गर्नुहोस्" + "Android Beam स्थानान्तरण अवस्था प्राप्त गर्नुहोस्" "यस आवेदनले वर्तमान Android Beam स्थानान्तरण बारेमा जानकारी प्राप्त गर्न अनुमति दिन्छ" "DRM प्रमाणपत्रहरू हटाउनुहोस्" "DRM प्रमाणपत्रहरू हटाउन अनुप्रयोगलाई अनुमति दिन्छ। सामान्य अनुप्रयोगहरूको लागि कहिल्यै आवश्यकता पर्दैन।" @@ -1097,11 +1097,11 @@ "फरम्याट गर्दै…" "सम्मिलित छैन" "कुनै मिल्ने गतिविधि पाइएन।" - "मिडिया परिणाम दिशानिर्देश गर्नुहोस्" + "मिडिया निकास दिशानिर्देश गराउनुहोस्" "मिडिया परिणामलाई अन्य बाहिरी उपकरणहरूसँग लैजानको लागि अनुप्रयोगलाई अनुमति दिन्छ।" - "स्थापना सत्रहरू पढ्नुहोस्" + "स्थापना सत्रहरू पढ्नु दिनुहोस्" "स्थापित सत्र पढ्न अनुप्रयोगलाई अनुमति दिनुहोस्। यसले सक्रिय प्याकेज प्रतिष्ठानहरू बारेमा विवरण हेर्ने अनुमति दिन्छ।" - "स्थापना प्याकेजहरू अनुरोध गर्नुहोस्" + "स्थापना प्याकेजहरू अनुरोध गर्नुहोस्" "प्याकेजहरूको स्थापना अनुरोध गर्न अनुप्रयोगलाई अनुमति दिन्छ।" "जुम नियन्त्रणको लागि दुई चोटि टच गर्नुहोस्" "विजेट थप गर्न सकिँदैन।" diff --git a/core/res/res/values-nl-watch/strings.xml b/core/res/res/values-nl-watch/strings.xml index 989fa277185b4..95baf7b18b823 100644 --- a/core/res/res/values-nl-watch/strings.xml +++ b/core/res/res/values-nl-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d van %2$d." + "Sensoren" diff --git a/core/res/res/values-nl/cm_strings.xml b/core/res/res/values-nl/cm_strings.xml new file mode 100644 index 0000000000000..0dcc2aa95130c --- /dev/null +++ b/core/res/res/values-nl/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Screenshot + + beschermd sms-bericht ontvangen + + Hiermee kan de app een inkomend beschermd sms-bericht ontvangen. + + beschermde sms-berichtenlijst wijzigen + + Hiermee kan de app de lijst van beschermde sms-adressen wijzigen. + + Beveiliging + + Machtigingen gerelateerd aan beveiligingsinformatie van het apparaat. + + zwarte lijst lezen + + Hiermee kan de app informatie lezen over telefoonnummers waarvan inkomende oproepen of berichten zijn geblokkeerd. + + zwarte lijst aanpassen + + Hiermee kan de app telefoonnummers aanpassen waarvan inkomende oproepen of berichten zijn geblokkeerd. + + achtergrond van vergrendelingsscherm instellen + + Hiermee kan de app de achtergrond van het vergrendelingsscherm aanpassen. + + Herstarten + + Huidige + + + Herstarten + + Recovery + + Bootloader + + Download + + Snelle herstart + + Herstarten + + Uw tablet wordt herstart. + Uw telefoon wordt herstart. + + Herstarten\u2026 + + App afgesloten + + ADB over netwerk ingeschakeld + + ADB over USB & netwerk ingeschakeld + + Tik om foutopsporing uit te schakelen. + + ADB - %1$s + USB & netwerk + USB + Netwerk + + Openen van app onderscheppen + + %s is niet geïnstalleerd + + Prioriteit + Geen + + Wifi-hotspot uitgeschakeld door een SIM-abonnementwijziging + + Wifi uitschakelen + + Privacybescherming in- of uitschakelen + Hiermee kan de app bepalen of een andere app start met Privacybescherming. Als een app start met Privacybescherming, zal het geen toegang hebben tot persoonsgegevens zoals contacten, berichten of gespreksstatistieken. + Privacybescherming actief + %1$s zal geen toegang hebben tot persoonsgegevens + Privacybescherming + %1$s wil %2$s. + + Keuze onthouden + + toegang tot camera + toegang tot uw locatie + meldingen lezen + VPN activeren + starten tijdens opstarten + gespreksstatistieken verwijderen + contacten verwijderen + mms-berichten verwijderen + sms-berichten verwijderen + bovenop tekenen + app-gebruiksstatistieken opvragen + apparaat wakker houden + telefoongesprek starten + agenda vernieuwen + gespreksstatistieken vernieuwen + klembord aanpassen + contacten vernieuwen + systeeminstellingen vernieuwen + microfoon in-/uitschakelen + audio afspelen + melding tonen + media projecteren + agenda lezen + gespreksstatistieken lezen + klembord lezen + contacten lezen + mms-berichten lezen + sms-berichten lezen + sms-bericht ontvangen + audio opnemen + mms-bericht versturen + sms-bericht versturen + starten tijdens opstarten + meldingen weergeven + Bluetooth aan-/uitzetten + mobiele gegevens aan-/uitzetten + NFC aan-/uitzetten + wifi aan-/uitzetten + alarmvolume beheren + audiofocus beheren + Bluetooth-volume beheren + hoofdvolume beheren + mediaknoppen gebruiken + mediavolume beheren + meldingsvolume beheren + beltoonvolume beheren + trillen gebruiken + stemvolume beheren + mms-bericht schrijven + sms-bericht schrijven + vingerafdruk gebruiken + voicemail toevoegen + toegang tot telefoonstatus + wifi-netwerken scannen + achtergrond aanpassen + structuur voor ondersteuning gebruiken + screenshot maken + lichaamssensoren gebruiken + nooduitzendingen lezen + neplocatie gebruiken + externe opslag lezen + naar externe opslag schrijven + scherm aanzetten + apparaataccounts opvragen + wifi-status aanpassen + root-toegang krijgen + + Blijf de Terug-knop aanraken om dit scherm los te maken. + + Geen aangesloten apparaat + %1$s aangesloten apparaat + %1$s aangesloten apparaten + + + + Starten van activiteit geblokkeerd + %1$s is beschermd tegen opstarten. Tik om aan te melden en de app te starten. + + Accu volledig opgeladen + Ontkoppel uw apparaat van de oplader om de levensduur van de accu te verlengen. + + accustatistieken opnieuw instellen + + Hiermee kan de app de huidige accustatistieken over het gebruik opnieuw instellen. + + Simkaarten zijn veranderd + Tik om standaardinstellingen van simkaart in te stellen + diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 7eef3394caa28..b9415e9ef2ed6 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -254,7 +254,7 @@ "Omvat persoonlijke gegevens zoals creditcardnummers en wachtwoorden." "statusbalk uitschakelen of wijzigen" "Hiermee kan de app de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen." - "statusbalk" + "de statusbalk zijn" "Hiermee kan de app de statusbalk zijn." "statusbalk uitvouwen/samenvouwen" "Hiermee kan de app de statusbalk uitvouwen of samenvouwen." @@ -282,7 +282,7 @@ "Hiermee kan de app WAP-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven." "actieve apps ophalen" "Hiermee kan de app informatie ophalen over actieve en recent uitgevoerde taken. Zo kan de app informatie vinden over welke apps op het apparaat worden gebruikt." - "Profiel- en apparaateigenaren beheren" + "profiel- en apparaateigenaren beheren" "Apps toestaan de profieleigenaren en apparaateigenaar in te stellen." "actieve apps opnieuw rangschikken" "Hiermee kan de app taken naar de voor- en achtergrond verplaatsen. De app kan dit doen zonder om je bevestiging te vragen." @@ -324,7 +324,7 @@ "Toestaan dat de app het gesprekkenlijst van je tablet aanpast, waaronder gegevens over inkomende en uitgaande oproepen. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen." "Toestaan dat de app het gesprekkenlijst van je tv aanpast, waaronder gegevens over inkomende en uitgaande oproepen. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen." "Toestaan dat de app het gesprekkenlijst van je telefoon aanpast, waaronder gegevens over inkomende en uitgaande oproepen. Schadelijke apps kunnen hiermee je gesprekkenlijst wissen of aanpassen." - "lichaamssensoren (zoals hartslagmeters)" + "toegang tot lichaamssensoren (zoals hartslagmeters)" "Hiermee kan de app toegang krijgen tot gegevens van sensoren die je lichamelijke conditie controleren, zoals je hartslag." "agenda-afspraken en vertrouwelijke informatie lezen" "Hiermee kan de app alle agenda-afspraken lezen die zijn opgeslagen op je tablet, inclusief die van vrienden of collega\'s. De app kan je agenda delen of je agendagegevens opslaan, ongeacht vertrouwelijkheid of gevoeligheid." @@ -336,15 +336,15 @@ "Hiermee kan de app afspraken toevoegen, verwijderen en wijzigen die u kunt bewerken op je telefoon, inclusief afspraken van vrienden of collega\'s. Zo kan de app berichten verzenden die afkomstig lijken te zijn van agenda-eigenaren, of afspraken aanpassen zonder medeweten van de eigenaar." "toegang tot extra opdrachten van locatieaanbieder" "Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van GPS of andere locatiebronnen te verstoren." - "precieze locatie (GPS- en netwerkgebaseerd)" + "toegang tot precieze locatie (GPS- en netwerkgebaseerd)" "Hiermee kan de app je precieze locatie bepalen via GPS (Global Positioning System) of netwerklocatiebronnen zoals zendmasten en wifi. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op je apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om te bepalen waar u bent en verbruiken mogelijk extra acculading." - "geschatte locatie (netwerkgebaseerd)" + "toegang tot geschatte locatie (netwerkgebaseerd)" "Hiermee kan de app beschikken over je geschatte locatie. Deze locatie wordt afgeleid van locatieservices die netwerklocatiebronnen zoals zendmasten en wifi gebruiken. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op je apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om ongeveer te bepalen waar u zich bevindt." "je audio-instellingen wijzigen" "Hiermee kan de app algemene audio-instellingen wijzigen zoals het volume en welke luidspreker wordt gebruikt voor de uitvoer." "audio opnemen" "Hiermee kan de app audio opnemen met de microfoon. Met deze toestemming kan de app op elk moment audio opnemen, zonder om je bevestiging te vragen." - "sim-communicatie" + "opdrachten verzenden naar de simkaart" "Hiermee kan de app opdrachten verzenden naar de simkaart. Dit is erg gevaarlijk." "foto\'s en video\'s maken" "Hiermee kan de app foto\'s en video\'s maken met de camera. Met deze toestemming kan de app de camera altijd gebruiken, zonder je bevestiging." @@ -382,7 +382,7 @@ "Hiermee krijgt de app toegang tot de lijst met accounts die op de telefoon bekend zijn. Dit kunnen ook accounts zijn die zijn gemaakt door apps die je hebt geïnstalleerd." "netwerkverbindingen weergeven" "Hiermee kan de app informatie bekijken over netwerkverbindingen, zoals welke netwerken er zijn en welke verbonden zijn." - "volledige netwerktoegang" + "volledige netwerktoegang" "Hiermee kan de app netwerksockets maken en aangepaste netwerkprotocollen gebruiken. De browser en andere apps bieden mogelijkheden om gegevens via internet te verzenden, dus deze toestemming is niet vereist om gegevens via internet te verzenden." "netwerkverbinding wijzigen" "Hiermee kan de app de status van de netwerkverbinding wijzigen." @@ -402,7 +402,7 @@ "Hiermee kan de app de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en koppelen." "WiMAX-verbinding maken en verbreken" "Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt." - "WiMAX-status wijzigen" + "WiMAX-status wijzigen" "Hiermee kan de app de tablet verbinden met WiMAX-netwerken en de verbinding daarmee verbreken." "Hiermee kan de app een verbinding maken tussen de tv en WiMAX-netwerken en deze verbinding verbreken." "Hiermee kan de app de telefoon verbinden met WiMAX-netwerken en de verbinding daarmee verbreken." @@ -485,7 +485,7 @@ "Hiermee kan de app de kalibratieparameters van het aanraakscherm aanpassen. Nooit vereist voor normale apps." "toegang tot DRM-certificaten" "Toestaan dat een app DRM-certificaten registreert en gebruikt. Nooit vereist voor normale apps." - "Android Beam-overdrachtsstatus ontvangen" + "Android Beam-overdrachtsstatus ontvangen" "Hiermee kan deze app informatie over huidige Android Beam-overdrachten ontvangen" "DRM-certificaten verwijderen" "Toestaan dat een app DRM-certificaten verwijdert. Nooit vereist voor normale apps." @@ -1091,11 +1091,11 @@ "Formatteren…" "Niet geplaatst" "Geen overeenkomende activiteiten gevonden." - "Media-uitvoer aansturen" + "media-uitvoer aansturen" "Hiermee kan een app media-uitvoer naar andere externe apparaten doorsturen." - "Installatiesessies lezen" + "installatiesessies lezen" "Hiermee wordt een app toegestaan installatiesessies te lezen. Zo kan de app informatie bekijken over actieve pakketinstallaties." - "Installatiepakketten aanvragen" + "installatiepakketten aanvragen" "Hiermee kan een app installatie van pakketten aanvragen." "Raak twee keer aan voor zoomregeling" "Kan widget niet toevoegen." diff --git a/core/res/res/values-oc-rFR/cm_strings.xml b/core/res/res/values-oc-rFR/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-oc-rFR/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-oc-rFR/strings.xml b/core/res/res/values-oc-rFR/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-oc-rFR/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-or-rIN/cm_strings.xml b/core/res/res/values-or-rIN/cm_strings.xml new file mode 100644 index 0000000000000..a591a6297b5e0 --- /dev/null +++ b/core/res/res/values-or-rIN/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + ସ୍କ୍ରିନସଟ୍ + + ସୁରଷିତ SMS ପ୍ରାପ୍ତ କରନ୍ତୁ + + ଆସୁଥିବା ସୁରଷିତ SMSକୁ ଗ୍ରହଣ କରିବା ପାଇଁ ଆପ୍ଲିକେସ‌ନକୁ ଅ୍ନୁମତି ଦିଏ। + + ସୁ୍ରଷିତ SMS ତାଲିକା ସମ୍ପାଦନା କରନ୍ତୁ + + ସୁରଷିତ SMS ଠିକଣା ତାଲିକା ସମ୍ପାଦନା କରିବା ପାଇଁ ଆପ୍ଲିକେସ‌ନକୁ ଅ୍ନୁମତି ଦିଏ। + + ସୁରକ୍ଷା + + ଡିଭାଇସ୍‍ ସୁରଷା ସୂଚନା ସମ୍ବଧିତ ଅନୁମତି। + + ଫୋନ୍‍ ବ୍ଲା‌କ୍‍ଲିଷ୍ଟ ପଢନ୍ତୁ + + ଯେଉଁ ଫୋନ୍‍ ନମ୍ବର ପାଇଁ ଆସୁଥିବା କଲ୍‍ ଓ ବାର୍ତ୍ତା ଅବରୁଧ ହୋ‌ଇଛି, ସେହି ବିଷୟରେ ସୂଚନା ପଢିବା ପାଇଁ ଆପ୍ଲିକେସ‌୍କୁ ଅନୁମତି ଦିଏ। + + ଫୋନ୍‍ ବ୍ଲା‌ଲିଷ୍ଟ ପରିବର୍ତ୍ତନ ମ୍କରନ୍ତୁ + + ଯେଉଁ ଫୋନ୍‍ ନମ୍ବର ପାଇଁ ଆସୁଥିବା କଲ୍‍ ଓ ବାର୍ତ୍ତା ଅବରୁଧ ହୋ‌ଇଛି, ସେହି ବିଷୟରେ ସୂଚନା ପଢିବା ପାଇଁ ଆପ୍ଲିକେସ‌୍କୁ ଅନୁମତି ଦିଏ। + + କୀଗାର୍ଡ ୱା‌‍ଲ୍ପେପର୍‍ ସେଟ୍‍ କରନ୍ତୁ + + ଲକ୍‍ ସ୍କ୍ରିନ୍‍ ୱାଲ୍‍ପେପର୍‍ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଏକ ଆପ୍ଲିକେସନ୍‍କୁ ଅନୁମତି ଇଦେ। + + ରିବୁଟ୍ + + ସମ୍ପ୍ରତି + + + ରିବୁଟ୍ + + ପୁନଃପ୍ରାପ୍ତ କରିବା + + ବୁଟ୍‍ଲୋଡର୍‍ + + ଡାଉନ‌ଲୋଡ୍ + + ସଫ୍ଟ ରିବୁଟ୍‍ + + ରିବୁଟ୍ + + ଆପଣଙ୍କ ଟା‌ବଲେଟ୍‍ ରିବୁଟ୍‍ ହେବ। + ଆପଣଙ୍କ ଫୋନ୍ ରିବୁଟ୍ ହେବ। + + ରିବୁଟ୍ କରୁଛି\u2026 + + ଆପ୍ଲିକେସନ୍‍ କଟାଯାଇଛି + + ନେଟ୍‍ୱା‌ର୍କ୍‍ରେ ADB ସଷମ କରାଯାଇଛି + + USB ଓ ନେଟ୍‍ୱା‌ର୍କ୍‍ରେ ADB ସଷମ କରାଯାଇଛି + + ଡିବଗିଙ୍ଗ ଅଷମ କରିବା ପାଇଁ ସ୍ପର୍ଶ ଅକରନ୍ତୁ। + + ADB - %1$s + USB ଓ ନେଟ୍‍ୱାର୍କ୍‍ + USB + ନେଟୱାର୍କ୍ + + ଆପ୍ଲିକେସନ୍‍ ଲଞ୍ଚ ଇଣ୍ଟରସେପ୍ଟ କରନ୍ତୁ + + %s ସଂ‍ସ୍ଥାପିତ ହୋଇନାହିଁ + + ଅଗ୍ରାଧିକାର + କିଛି ନୁହେଁ + + SIM ଗ୍ରହୀତା‍ ପରିବର୍ତ୍ତନ କାରଣରୁ Wi-Fi ହଟ୍‍ସ୍ପଟ୍‍ ଅଷମ କରାଯାଇଛି + + Wi-Fi ଅଫ୍‍ କରନ୍ତୁ + + ପ୍ରାଇଭେସି ଗାର୍ଡ ସଷମ ବା ଅଷମ କରନ୍ତୁ + ପ୍ରାଇଭେସି ଗାର୍ଡ ସହିତ ଅନ୍ୟ ଏକ ଆପ୍ଲିକେସ‌‌ନ୍‍ ର‌ନ୍‍ କରିପାରିବ କି ନାହିଁ ତାହା ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଏକ ଆପ୍ଲିକେସ‌କୁ ଅନୁମତି ଦିଏ। ଯେତେବେଳେ ପ୍ରାଇଭେସି ଗାର୍ଡ ସହିତ ଏକ ଆପ୍ଲିକେସନ୍‍ ଚାଳନା କରାଯାଉଥାଏ, ଏହା ବ୍ୟକ୍ତିଗତ ତଥ୍ୟ ଯଥା ସମ୍ପର୍କ, କଲ୍‍ ସୂୀ, ବା ସନ୍ଦେଶଗୁ୍ଡିକ ଆକ୍‍ସେସ୍‍ କରିପାରିବ ନାହିଁ। + ପ୍ରାଇଭେସି ଗାର୍ଡ ଆକ୍ଟିଭ୍‍ + %1$s ବ୍ୟକ୍ତିଗତ ତଥ୍ୟ ଆକ୍‍ସେସ୍‍ କରିବା ପାଇଁ ସଷମ ହେବ ନାହିଁ + ପ୍ରାଇଭେସି ଗାର୍ଡ + %1$Sଚାହିଁବ ଚାହିଁବ %2$s + + ମୋ ପସନ୍ଦ ମନେରଖନ୍ତୁ + + କ୍ୟାମେରା ଆ‌କ୍‍ସେସ୍‍ କରନ୍ତୁ + ଆପଣଙ୍କ ଅବସ୍ଥାନ ଆକ୍‍ସେସ୍‍ କରନ୍ତୁ + ଆପଣଙ୍କ ସୂଚନାବଳି ପଢନ୍ତୁ + ଏକ VPN ସକ୍ରିୟ କରନ୍ତୁ + ପାୱା‌ର୍‍ ଅପ୍‍ ସମୟରେ ଆ୍ର‍ମ୍ଭ କରନ୍ତୁ + ଆପଣଙ୍କ କଲ୍‍ ସୂଚୀ ବିଲୋପ କରନ୍ତୁ + ଆପଣଙ୍କ ସମ୍ପର୍କଗୁଡିକ ବିଲୋପ କରନ୍ତୁ + ଆପଣଙ୍କ MMS ସନ୍ଦେଶ ବିଲୋପ କରନ୍ତୁ + ଆପଣଙ୍କ SMS ସନ୍ଦେଶ ବିଲୋପ କରନ୍ତୁ + ଶୀଷରେ ୱିଣ୍ଡୋଜ୍‍ ଆଙ୍କନ୍ତୁ + ଆପ୍ଲିକେସନ୍‍ ବ୍ୟବହାରର ପରିସଂଖ୍ୟାନ ପ୍ରାପ୍ତ କରନ୍ତୁ + ଆପଣଙ୍କ ଡିଭାଇ‌ସ୍‍କୁ ଜାଗ୍ରତ ରଖନ୍ତୁ + ଏକ ଫୋନ୍‍ କଲ୍‍ କରନ୍ତୁ + ଆପଣଙ୍କ କ୍ୟାଲେନ୍ଡର ଅଦ୍ୟତନ କରନ୍ତୁ + କଲ୍‍ ସୂଚୀ ଅଦ୍ୟତନ କରନ୍ତୁ + କ୍ଲି‌ପ୍‍ବୋର୍ଡ୍‍ ସମ୍ପାଦନା କରନ୍ତୁ + ଆପଣଙ୍କ ସମ୍ପର୍କଗୁଡିକ ଅଦ୍ୟତନ କରନ୍ତୁ + ସିଷ୍ଟମ୍‍ ସେଟିଂଗୁଡିକ ଅଦ୍ୟତନ କରନ୍ତୁ + ମାଇକ୍ରୋଫୋନ୍‍ ମ୍ୟୁଟ୍‍/ଅନ୍‍ମ୍ୟୁଟ୍‍ କରନ୍ତୁ + ଅଡିଓ ବଜାନ୍ତୁ + ଏକ ନୋଟିଫିକେସନ୍‍ ପୋଷ୍ଟ କରନ୍ତୁ + ପ୍ରୋଜେକ୍ଟ ମିଡିଆ + ଆପଣଙ୍କ କ୍ୟା୍ଲେଣ୍ଡର ପଢନ୍ତୁ + କଲ୍‍ ସୂଚୀ ପଢନ୍ତୁ + କ୍ଲିପ୍‍ବୋର୍ଡ ପଢନ୍ତୁ + ଆପଣଙ୍କ ସମ୍ପର୍କଗୁଡିକ ପଢନ୍ତୁ + ଆପଣଙ୍କ MMS ସନ୍ଦେଶ ପଢନ୍ତୁ + ଆପଣଙ୍କ SMS ସନ୍ଦେଶ ପଢନ୍ତୁ + ଏକ SMS ସନ୍ଦେଶ ପ୍ରାପ୍ତ କରନ୍ତୁ + ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ + ଏକ MMS ସନ୍ଦେଶ ପଠାନ୍ତୁ + ଏକ SMS ସନ୍ଦେଶ ପଠାନ୍ତୁ + ପାୱା‌ର୍‍ ଅପ୍‍ ସମୟରେ ଆ୍ର‍ମ୍ଭ କରନ୍ତୁ + ଟୋଷ୍ଟ ସନ୍ଦେଶ ପ୍ରଦର୍ଶନ କରନ୍ତୁ + ବ୍ଲୁଟୁଥ୍‍ ଟୋଗଲ୍‍ କରନ୍ତୁ + ଡାଟା ଟୋଗଲ୍‍ କରନ୍ତୁ + NFC ଟୋଗଲ୍‍ କରନ୍ତୁ + WiFi ଟୋଗଲ୍‍ କରନ୍ତୁ + ଆଲାର୍ମ୍‍ ଭୋଲ୍ୟୁମ୍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ଅଡିଓ ଫୋକସ୍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ବ୍ଲୁଟୁଥ୍‍ ଭୋଲ୍ୟୁମ୍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ମାଷ୍ଟର୍‍ ଭୋଲ୍ୟୁମ୍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ମିଡିଆ ବଟ‌ନ୍‍ଗୁଡିକ ବ୍ୟବହାର କରନ୍ତୁ + ମିଡିଆ ଭୋଲ୍ୟୁମ୍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ନୋଟିଫିକେସନ୍‍ ଭୋଲ୍ୟୁମ୍‍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ରିଙ୍ଗ୍‍ଟୋନ୍‍ ଭୋଲ୍ୟୁମ୍‍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ହାପ୍‍ଟିକ୍‍ ଫିଡ୍‍ବ୍ୟାକ୍‍ ବ୍ୟବହାର କରନ୍ତୁ + ସ୍ୱର କଲ୍‍ ଭୋଲ୍ୟୁମ୍‍‍‍ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ + ଏକ MMS ସନ୍ଦେଶ ଲେଖନ୍ତୁ + ଏକ SMS ସନ୍ଦେଶ ଲେଖନ୍ତୁ + ଫିଙ୍ଗର୍‍ପ୍ରିଣ୍ଟ ବ୍ୟବହାର କରନ୍ତୁ + ଭଏସମେଲ୍ ଯୋଗ କରନ୍ତୁ + ଆକ୍ସେସ୍ ଫୋନ୍ ସ୍ଟେଟ + ସ୍କାନ୍ Wi-Fi ନେଟୱାର୍କ + ୱାଲପେପର୍ ପରିବର୍ତ୍ତନ କରନ୍ତୁ + ନିର୍ମାଣର ସହାୟତା ପାଇଁ ବ୍ୟବହାର + ସ୍କ୍ରିନ୍‍ସଟ୍‍ ନିଅନ୍ତୁ + ବଡି ସେନସର୍ ବ୍ୟବହାର କରନ୍ତୁ + ସେଲ୍ ପ୍ରସାରଣ ପଢ + ଆପଣଙ୍କ ନକଲି ଅବସ୍ଥାନ + ବାହ୍ୟ ଷ୍ଟୋରେଜ୍ ପଢନ୍ତୁ + ବାହ୍ୟ ଷ୍ଟୋରେଜ୍ ଲେଖନ୍ତୁ + ସ୍କ୍ରିନ୍‍ ଅନ କରନ୍ତୁ + ଡିଭାଇସ୍ ଆକାଉଣ୍ଟ ମିଳିଲା + Wi-Fi ସ୍ତିତି ପରିବର୍ତ୍ତନ କରନ୍ତୁ + ରୁଟ୍‍ ପ୍ରବେଶ ପ୍ରାପ୍ତ କରନ୍ତୁ + + ଏହି ସ୍କ୍ରିନ୍‍ ଅନ୍‍ପିନ୍‍ କରିବା ପାଇଁ, ବ୍ୟାକ୍‍ ବଟନ୍‍ ସ୍ପର୍ଶ କରନ୍ତୁ ଓ ଧରିରଖନ୍ତୁ। + + ସଂଯୋଗ ହୋଇଥିବା କିଛି ଡିଭାଇସ୍‍ ନା୍ହିଁ + %1$s ସଂଯୋଗ ହୋଇଥିବା ଡିଭାଇସ୍ + %1$s ସଂଯୋଗ ହୋଇଥିବା ଡିଭାଇସ୍ଗୁଡିକ + + + + ଉନ୍ମୋଚନ କରିବା ପାଇଁ ଅବରୋଧ + %1$sଆରମ୍ଭ କରିବାରୁ ସୁରକ୍ଷିତ | ପ୍ରମାଣିତ ଏବଂ ଆବେଦନ ପାଇଁ ଟ୍ୟାପ୍ କରନ୍ତୁ | + + ବ୍ୟାଟେରୀ ସମ୍ପୁର୍ଣ ଚାରଜ୍ ହୋଇସାରିଛି + ଚାରଜରୁ ଡିଭାଇସ୍ ଅଲଗାକରନ୍ତୁ ବ୍ୟାଟେରୀର ଦୀର୍ଘାୟୁ କରିବା ପାଇଁ + + ବ୍ୟାଟେରୀ ପରିସଂଖ୍ୟାନ ରିସେଟ୍‍ କରନ୍ତୁ + + ସମ୍ପ୍ରତି ଲୋ-ଲେବେଲ୍‍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର ତଥ୍ୟକୁ ରିସେଟ୍‍ କରିବା ପାଇଁ ଏକ ଆପ୍ଲିକେସନ୍‍କୁ ଅନୁମତି ଦିଏ। + + diff --git a/core/res/res/values-or-rIN/strings.xml b/core/res/res/values-or-rIN/strings.xml new file mode 100644 index 0000000000000..b4c9596593f96 --- /dev/null +++ b/core/res/res/values-or-rIN/strings.xml @@ -0,0 +1,1662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-pa-rIN-watch/strings.xml b/core/res/res/values-pa-rIN-watch/strings.xml index b30daa4f0f6be..9fc71f06da93f 100644 --- a/core/res/res/values-pa-rIN-watch/strings.xml +++ b/core/res/res/values-pa-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "ਐਪ %2$d ਦਾ %1$d" + "ਸੰੰਵੇਦਕ" diff --git a/core/res/res/values-pa-rIN/cm_strings.xml b/core/res/res/values-pa-rIN/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-pa-rIN/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml index 1743570d07dcd..54db14bdcb377 100644 --- a/core/res/res/values-pa-rIN/strings.xml +++ b/core/res/res/values-pa-rIN/strings.xml @@ -254,7 +254,7 @@ "ਇਸ ਵਿੱਚ ਨਿੱਜੀ ਡਾਟਾ ਸ਼ਾਮਲ ਹੈ ਜਿਵੇਂ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ ਅਤੇ ਪਾਸਵਰਡ।" "ਸਥਿਤੀ ਬਾਰ ਅਸਮਰੱਥ ਬਣਾਓ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ" "ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਜਾਂ ਸਿਸਟਮ ਆਈਕਨਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" - "ਸਥਿਤੀ ਬਾਰ" + "ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ" "ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "ਸਥਿਤੀ ਬਾਰ ਦਾ ਵਿਸਤਾਰ/ਨਸ਼ਟ ਕਰੋ" "ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਦਾ ਵਿਸਤਾਰ ਕਰਨ ਜਾਂ ਨਸ਼ਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" @@ -282,7 +282,7 @@ "ਐਪ ਨੂੰ WAP ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਅਨੁਮਤੀ ਵਿੱਚ ਸ਼ਾਮਲ ਹੈ ਐਪ ਦੀ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰਨ ਅਤੇ ਮਿਟਾਉਣ ਦੀ ਸਮਰੱਥਾ।" "ਚੱਲ ਰਹੇ ਐਪਸ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ" "ਐਪ ਨੂੰ ਵਰਤਮਾਨ ਵਿੱਚ ਅਤੇ ਹੁਣੇ ਜਿਹੇ ਚੱਲ ਰਹੇ ਕੰਮਾਂ ਬਾਰੇ ਵਿਸਤ੍ਰਿਤ ਜਾਣਕਾਰੀ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਇਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਖੋਜਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ ਕਿ ਡਿਵਾਈਸ ਤੇ ਕਿਹੜੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵਰਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ।" - "ਪ੍ਰੋਫ਼ਾਈਲ ਅਤੇ ਡਿਵਾਈਸ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਪ੍ਰਬੰਧਿਤ ਕਰੋ" + "ਪ੍ਰੋਫ਼ਾਈਲ ਅਤੇ ਡਿਵਾਈਸ ਮਾਲਕਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ" "ਪ੍ਰੋਫ਼ਾਈਲ ਦੇ ਮਾਲਕ ਅਤੇ ਡਿਵਾਈਸ ਦਾ ਮਾਲਕ ਨੂੰ ਸੈੱਟ ਕਰਨ ਲਈ ਐਪਸ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ।" "ਚੱਲ ਰਹੇ ਐਪਸ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ" "ਐਪ ਨੂੰ ਕੰਮਾਂ ਨੂੰ ਅਗਲੇ ਭਾਗ ਅਤੇ ਪਿਛੋਕੜ ਵਿੱਚ ਮੂਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਐਪ ਤੁਹਾਡੇ ਇਨਪੁਟ ਤੋਂ ਬਿਨਾਂ ਇਹ ਕਰ ਸਕਦਾ ਹੈ।" @@ -324,7 +324,7 @@ "ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਟੈਬਲੇਟ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖ਼ਰਾਬ ਐਪਸ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੇ ਹਨ।" "ਐਪ ਨੂੰ ਤੁਹਾਡੇ TV ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖ਼ਰਾਬ ਐਪਸ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੇ ਹਨ।" "ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫੋਨ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖ਼ਰਾਬ ਐਪਸ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੇ ਹਨ।" - "ਸਰੀਰ ਸੰਵੇਦਕ (ਜਿਵੇਂ ਦਿਲ ਦੀ ਧੜਕਣ ਦੇ ਨਿਰੀਖਕ)" + "ਸਰੀਰ ਸੰਵੇਦਕਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (ਜਿਵੇਂ ਦਿਲ ਦੀ ਧੜਕਣ ਦੇ ਨਿਰੀਖਕ)" "ਐਪ ਨੂੰ ਉਹਨਾਂ ਸੰਵੇਦਕਾਂ ਦੇ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜੋ ਤੁਹਾਡੀ ਸਰੀਰਕ ਸਥਿਤੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੇ ਹਨ, ਜਿਵੇਂ ਤੁਹਾਡੇ ਦਿਲ ਦੀ ਧੜਕਣ।" "ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਪਲਸ ਗੁਪਤ ਜਾਣਕਾਰੀ ਪੜ੍ਹੋ" "ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਟੈਬਲੇਟ ਤੇ ਸਟੋਰ ਕੀਤੀਆਂ ਸਾਰੀਆਂ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਦੋਸਤਾਂ ਜਾਂ ਸਹਿਯੋਗੀਆਂ ਦੀਆਂ ਇਵੈਂਟਾਂ ਸਮੇਤ। ਇਹ ਐਪ ਨੂੰ ਤੁਹਾਡਾ ਕੈਲੰਡਰ ਡਾਟਾ ਸ਼ੇਅਰ ਜਾਂ ਸੁਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ, ਗੁਪਤਤਾ ਜਾਂ ਸੰਵੇਦਨਸ਼ੀਲਤਾ ਤੇ ਧਿਆਨ ਦਿੱਤੇ ਬਿਨਾਂ।" @@ -336,15 +336,15 @@ "ਐਪ ਨੂੰ ਉਹ ਇਵੈਂਟਾਂ ਜੋੜਨ, ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜਿਹਨਾਂ ਨੂੰ ਤੁਸੀਂ ਆਪਣੇ ਫੋਨ ਤੇ ਸੰਸ਼ੋਧਿਤ ਕਰ ਸਕਦੇ ਹੋ, ਦੋਸਤਾਂ ਜਾਂ ਸਹਿਯੋਗੀਆਂ ਦੀਆਂ ਇਵੈਂਟਾਂ ਸਮੇਤ। ਇਹ ਐਪ ਨੂੰ ਮਾਲਕ ਦੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਉਹ ਸੁਨੇਹੇ, ਜੋ ਕੈਲੰਡਰ ਮਾਲਕਾਂ ਤੋਂ ਆਉਂਦੇ ਜਾਪਦੇ ਹਨ, ਭੇਜਣ ਦੀ ਜਾਂ ਇਵੈਂਟਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ।" "ਵਾਧੂ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ" "ਐਪ ਨੂੰ ਵਾਧੂ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ GPS ਜਾਂ ਹੋਰ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸ੍ਰੋਤਾਂ ਦੇ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾਉਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ।" - "ਨਿਯਤ ਨਿਰਧਾਰਿਤ ਸਥਾਨ (GPS ਅਤੇ ਨੈਟਵਰਕ-ਆਧਾਰਿਤ)" + "ਸਟੀਕ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (GPS ਅਤੇ ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)" "ਐਪ ਨੂੰ ਗਲੋਬਲ ਪੋਜੀਸ਼ਨਿੰਗ ਸਿਸਟਮ (GPS) ਜਾਂ ਨੈਟਵਰਕ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸ੍ਰੋਤ ਜਿਵੇਂ ਸੈਲ ਟਾਵਰ ਅਤੇ Wi-Fi, ਵਰਤਦੇ ਹੋਏ ਤੁਹਾਡਾ ਨਿਯਤ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾਵਾਂ ਚਾਲੂ ਅਤੇ ਐਪ ਨੂੰ ਉਹਨਾਂ ਨੂੰ ਵਰਤਣ ਲਈ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ। ਐਪਸ ਇਸਦੀ ਵਰਤੋਂ ਇਹ ਨਿਰਧਾਰਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੇ ਹਨ ਕਿ ਤੁਸੀਂ ਕਿੱਥੇ ਹੋ ਅਤੇ ਵਾਧੂ ਬੈਟਰੀ ਪਾਵਰ ਖ਼ਰਚ ਸਕਦੇ ਹਨ।" - "ਅਨੁਮਾਨਿਤ ਨਿਰਧਾਰਿਤ ਸਥਾਨ (ਨੈਟਵਰਕ-ਆਧਾਰਿਤ)" + "ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)" "ਐਪ ਨੂੰ ਤੁਹਾਡਾ ਅਨੁਮਾਨਿਤ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਨੈਟਵਰਕ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸ੍ਰੋਤ ਵਰਤਦੇ ਹੋਏ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾਵਾਂ ਰਾਹੀਂ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਜਿਵੇਂ ਸੈਲ ਟਾਵਰ ਅਤੇ Wi-Fi. ਇਹ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾਵਾਂ ਚਾਲੂ ਅਤੇ ਐਪ ਨੂੰ ਉਹਨਾਂ ਨੂੰ ਵਰਤਣ ਲਈ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ। ਐਪਸ ਇਸਦੀ ਵਰਤੋਂ ਇਹ ਅਨੁਮਾਨ ਲਗਾਉਣ ਲਈ ਕਰ ਸਕਦੇ ਹਨ ਕਿ ਤੁਸੀਂ ਕਿੱਥੇ ਹੋ।" "ਆਪਣੀਆਂ ਔਡੀਓ ਸੈਟਿੰਗਾਂ ਬਦਲੋ" "ਔਪ ਨੂੰ ਗਲੋਬਲ ਔਡੀਓ ਸੈਟਿੰਗਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਵੌਲਯੂਮ ਅਤੇ ਆਊਟਪੁਟ ਲਈ ਕਿਹੜਾ ਸਪੀਕਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।" "ਔਡੀਓ ਰਿਕਾਰਡ ਕਰੋ" "ਐਪ ਨੂੰ ਮਾਈਕ੍ਰੋਫੋਨ ਨਾਲ ਔਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਅਨੁਮਤੀ ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਪੁਸ਼ਟੀ ਤੋਂ ਬਿਨਾਂ ਕਿਸੇ ਵੀ ਸਮੇਂ ਔਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।" - "sim ਸੰਚਾਰ" + "SIM ਨੂੰ ਕਮਾਂਡਾਂ ਭੇਜੋ" "ਐਪ ਨੂੰ SIM ਨੂੰ ਕਮਾਂਡਾਂ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਬਹੁਤ ਘਾਤਕ ਹੈ।" "ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਬਣਾਓ" "ਐਪ ਨੂੰ ਕੈਮਰੇ ਨਾਲ ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਲੈਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਅਨੁਮਤੀ ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਪੁਸ਼ਟੀ ਤੋਂ ਬਿਨਾਂ ਕਿਸੇ ਵੀ ਸਮੇਂ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।" @@ -382,7 +382,7 @@ "ਐਪ ਨੂੰ ਫੋਨ ਵੱਲੋਂ ਗਿਆਤ ਖਾਤਿਆਂ ਦੀ ਸੂਚੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਕੋਈ ਵੀ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ।" "ਨੈਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੇਖੋ" "ਐਪ ਨੂੰ ਨੈਟਵਰਕ ਕਨੈਕਸ਼ਨਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿਹੜੇ ਨੈਟਵਰਕ ਮੌਜੂਦ ਹਨ ਅਤੇ ਕਨੈਕਟ ਕੀਤੇ ਹੋਏ ਹਨ।" - "ਪੂਰੀ ਨੈਟਵਰਕ ਪਹੁੰਚ" + "ਪੂਰੀ ਨੈੱਟਵਰਕ ਪਹੁੰਚ ਪਾਓ" "ਐਪ ਨੂੰ ਨੈਟਵਰਕ ਸੌਕੇਟ ਬਣਾਉਣ ਅਤੇ ਕਸਟਮ ਨੈਟਵਰਕ ਪ੍ਰੋਟੋਕੋਲ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਬ੍ਰਾਊਜ਼ਰ ਅਤੇ ਹੋਰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਇੰਟਰਨੈਟ ਨੂੰ ਡਾਟਾ ਭੇਜਣ ਲਈ ਸਾਧਨ ਮੁਹੱਈਆ ਕਰਦਾ ਹੈ, ਇਸਲਈ ਇੰਟਰਨੈਟ ਡਾਟਾ ਭੇਜਣ ਲਈ ਇਹ ਅਨੁਮਤੀ ਲੁੜੀਂਦੀ ਨਹੀਂ ਹੈ।" "ਨੈਟਵਰਕ ਕਨੈਕਟੀਵਿਟੀ ਬਦਲੋ" "ਐਪ ਨੂੰ ਨੈਟਵਰਕ ਕਨੈਕਟੀਵਿਟੀ ਦੀ ਸਥਿਤੀ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" @@ -402,7 +402,7 @@ "ਐਪ ਨੂੰ ਸਥਾਨਕ Bluetooth ਫੋਨ ਨੂੰ ਕੌਂਫਿਗਰ ਕਰਨ ਅਤੇ ਰਿਮੋਟ ਡਿਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਪੇਅਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "WiMAX ਤੋਂ ਕਨੈਕਟ ਅਤੇ ਡਿਸਕਨੈਕਟ ਕਰੋ" "ਐਪ ਨੂੰ ਇਹ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਕਿ WiMAX ਸਮਰਥਿਤ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਕਿਸੇ ਵੀ WiMAX ਨੈਟਵਰਕਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਜੋ ਕਨੈਕਟ ਕੀਤੇ ਹੋਏ ਹਨ।" - "WiMAX ਸਥਿਤੀ ਬਦਲੋ" + "WiMAX ਸਥਿਤੀ ਬਦਲੋ" "ਐਪ ਨੂੰ ਟੈਬਲੇਟ ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈਟਵਰਕਾਂ ਤੋਂ ਟੈਬਲੇਟ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "ਐਪ ਨੂੰ TV ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈਟਵਰਕਾਂ ਤੋਂ TV ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "ਐਪ ਨੂੰ ਫੋਨ ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈਟਵਰਕਾਂ ਤੋਂ ਫੋਨ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" @@ -485,7 +485,7 @@ "ਐਪ ਨੂੰ ਟਚ ਸਕ੍ਰੀਨ ਦੇ ਕੈਲੀਬ੍ਰੇਸ਼ਨ ਪੈਰਾਮੀਟਰਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਸ ਲਈ ਕਦੇ ਵੀ ਲੁੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।" "DRM ਸਰਟੀਫਿਕੇਟਾਂ ਤੱਕ ਪਹੁੰਚ" "ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਵਿਵਸਥਾ ਕਰਨ ਅਤੇ DRM ਸਰਟੀਫਿਕੇਟ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਸ ਲਈ ਕਦੇ ਵੀ ਲੁੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।" - "Android Beam ਟ੍ਰਾਂਸਫਰ ਸਥਿਤੀ ਪ੍ਰਾਪਤ ਕਰੋ" + "Android ਬੀਮ ਟ੍ਰਾਂਸਫਰ ਸਥਿਤੀ ਪ੍ਰਾਪਤ ਕਰੋ" "ਇਸ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਮੌਜੂਦਾ Android Beam ਟ੍ਰਾਂਸਫਰਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "DRM ਸਰਟੀਫਿਕੇਟ ਹਟਾਓ" "ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ DRM ਸਰਟੀਫਿਕੇਟ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਸ ਲਈ ਕਦੇ ਵੀ ਲੁੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।" @@ -1091,11 +1091,11 @@ "ਫੌਰਮੈਟ ਕਰ ਰਿਹਾ ਹੈ..." "ਰੁਚੀ ਨਹੀਂ" "ਕੋਈ ਮੇਲ ਖਾਂਦੀਆਂ ਗਤੀਵਿਧੀਆਂ ਨਹੀਂ ਮਿਲੀਆਂ।" - "ਰੂਟ ਮੀਡੀਆ ਆਊਟਪੁਟ" + "ਰੂਟ ਮੀਡੀਆ ਆਊਟਪੁਟ" "ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੂੰ ਹੋਰਾਂ ਬਾਹਰੀ ਡਿਵਾਈਸਾਂ ਲਈ ਮੀਡੀਆ ਆਊਟਪੁਟ ਰੂਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" - "ਇੰਸਟੌਲ ਸੈਸ਼ਨ ਪੜ੍ਹੋ" + "ਸਥਾਪਿਤ ਸੈਸ਼ਨਾਂ ਨੂੰ ਪੜ੍ਹੋ" "ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਇੰਸਟੌਲ ਸੈਸ਼ਨ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਸਨੂੰ ਸਕਿਰਿਆ ਪੈਕੇਜ ਇੰਸਟੌਲੇਸ਼ਨਾਂ ਬਾਰੇ ਵੇਰਵੇ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" - "ਪੈਕੇਜ ਸਥਾਪਨਾ ਦੀ ਬੇਨਤੀ ਕਰੋ" + "ਪੈਕੇਜ ਸਥਾਪਿਤ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕਰੋ" "ਪੈਕੇਜ ਦੀ ਸਥਾਪਨਾ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ" "ਜ਼ੂਮ ਨਿਯੰਤਰਣ ਲਈ ਦੋ ਵਾਰ ਛੋਹਵੋ" "ਵਿਜੇਟ ਨਹੀਂ ਜੋੜ ਸਕਿਆ।" diff --git a/core/res/res/values-pl-watch/strings.xml b/core/res/res/values-pl-watch/strings.xml index d9608f32776e9..1a855d133bae4 100644 --- a/core/res/res/values-pl-watch/strings.xml +++ b/core/res/res/values-pl-watch/strings.xml @@ -21,4 +21,5 @@ "Aplikacja %1$d z %2$d." + "Czujniki" diff --git a/core/res/res/values-pl/cm_strings.xml b/core/res/res/values-pl/cm_strings.xml new file mode 100644 index 0000000000000..c0edab422f0c4 --- /dev/null +++ b/core/res/res/values-pl/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Zrzut ekranu + + odbieranie chronionych SMS-ów + + Umożliwia aplikacji odbieranie przychodzących chronionych SMS-ów. + + Modyfikowanie listy chronionych SMS-ów + + Umożliwia aplikacji modyfikowanie listy chronionych SMS-ów. + + Zabezpieczenia + + Uprawnienia związane z informacjami o bezpieczeństwie urządzenia. + + odczytywanie czarnej listy + + Umożliwia aplikacji odczytywanie informacji o numerach telefonów, od których przychodzące połączenia i wiadomości są blokowane. + + edytowanie czarnej listy + + Umożliwia aplikacji zmianę numerów telefonów, od których przychodzące połączenia i wiadomości są blokowane. + + Ustawianie tła ekranu blokady + + Umożliwia aplikacji zmianę tła ekranu blokady. + + Uruchom ponownie + + Bieżący + + + Uruchom ponownie + + Uruchom w trybie Recovery + + Uruchom w trybie Bootloader + + Uruchom w trybie Download + + Miękki restart + + Uruchom ponownie + + Tablet zostanie uruchomiony ponownie. + Telefon zostanie uruchomiony ponownie. + + Ponowne uruchamianie\u2026 + + Aplikacja została zamknięta + + ADB przez sieć włączone + + ADB przez USB & sieć włączone + + Dotknij, aby wyłączyć debugowanie. + + ADB - %1$s + USB & sieć + USB + Sieć + + przechwytywanie uruchamiania aplikacji + + Nie zainstalowano aplikacji %s + + Priorytet + Brak + + Wyłączono hotspot WiFi z powodu zmiany karty SIM + + Wyłącz Wi-Fi + + włącz/wyłącz Ochronę Prywatności + Pozwala aplikacji decydować, kiedy inna aplikacja zostanie uruchomiona w trybie ochrony prywatności. W trybie tym aplikacje nie mają dostępu do osobistych danych użytkownika, takich jak kontakty, historia połączeń czy wiadomości. + Ochrona prywatności aktywna + %1$s nie będzie mieć dostępu do osobistych danych + Ochrona prywatności + %1$s czy chciałbyś %2$s. + + Zapamiętaj mój wybór + + dostęp do kamery + dostęp do lokalizacji + czytanie powiadomień + aktywowanie VPN + uruchamianie podczas włączania urządzenia + usuwanie dziennika połączeń + usuwanie kontaktów + usuwanie wiadomości MMS + usuwanie wiadomości SMS + rysowanie okien na wierzchu + uzyskanie statystyk użytkowania aplikacji + zapobieganie przejściu telefonu w stan uśpienia + wykonywanie połączeń telefonicznych + aktualizowanie kalendarza + aktualizowanie rejestru połączeń + modyfikowanie schowka + aktualizowanie kontaktów + aktualizowanie ustawień systemowych + włączanie/wyłączanie mikrofonu + odtwarzanie dźwięków + wysyłanie powiadomienia + wyświetlanie multimediów + czytanie kalendarza + czytanie rejestru połączeń + czytanie schowka + czytanie kontaktów + czytanie MMS-ów + czytanie SMS-ów + odbieranie SMS-ów + nagrywanie dźwięku + wysyłanie MMS-ów + wysyłanie SMS-ów + uruchamianie podczas włączania urządzenia + wyświetlanie komunikatów w dymkach + przełączanie Bluetooth + przełączanie transmisji danych + Przełączanie NFC + przełączanie Wi-Fi + kontrolowanie głośności alarmu + kontrolowanie priorytetów audio + kontrolowanie głośności urządzenia Bluetooth + kontrolowanie głośności + używanie przycisków mediów + kontrolowanie głośności mediów + kontrolowanie głośności powiadomień + kontrolowanie głośności dzwonka + używanie haptic feedback + kontrolowanie głośności rozmów + pisanie MMS-ów + pisanie SMS-ów + odczyt linii papilarnych + dodawanie wiadomości głosowej + dostęp do stanu telefonu + skanowanie sieci Wi-Fi + zmiana tapety + wykorzystanie asystenta + tworzenie zrzutów ekranu + odczyt czujników ciała + odczyt transmisji komórkowych + pozorowanie twojej lokalizacji + odczyt pamięci zewnętrznej + zapis pamięci zewnętrznej + włączanie ekranu + dostęp do kont urządzenia + zmiana stanu Wi-Fi + dostęp do roota + + Aby odpiąć ekran, dotknij i przytrzymaj przycisk Wstecz. + + Brak podłączonego urządzenia + %1$s podłączone urządzenie + %1$s podłączone urządzenia + + + + Aktywność uruchamiania zablokowana + %1$s jest chroniony(a) przed uruchomieniem. Kliknij, aby uwierzytelnić i uruchomić tę aplikację. + + Bateria naładowana + Odłącz urządzenie od ładowarki, aby poprawić żywotność baterii. + + resetowanie statystyk baterii + + Umożliwia aplikacji na zresetowanie statystyk użycia baterii. + + Karty SIM zostały zamienione + Dotknij, aby ustawić domyślne preferencje karty SIM + diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 308bf89aa83d8..2604829ae39b0 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -256,7 +256,7 @@ "Obejmuje informacje osobiste, takie jak numery kart kredytowych i hasła." "wyłączanie lub zmienianie paska stanu" "Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych." - "pasek stanu" + "działanie jako pasek stanu" "Pozwala aplikacji na występowanie na pasku stanu." "rozwijanie/zwijanie paska stanu" "Pozwala aplikacji na rozwijanie lub zwijanie paska stanu." @@ -284,7 +284,7 @@ "Pozwala aplikacji na odbieranie i przetwarzanie wiadomości WAP. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia." "pobieranie uruchomionych aplikacji" "Pozwala aplikacji na pobieranie informacji o aktualnie i niedawno działających zadaniach. Dzięki temu aplikacja może uzyskać informacje o tym, które aplikacje są używane na urządzeniu." - "Zarządzanie właścicielami profilu i urządzenia" + "zarządzanie właścicielami profilu i urządzenia" "Zezwala aplikacjom na ustawianie właścicieli profilu i urządzenia." "zmienianie kolejności uruchomionych aplikacji" "Pozwala aplikacji na przenoszenie zadań między tłem a pierwszym planem. Aplikacja może to robić bez Twojego udziału." @@ -326,7 +326,7 @@ "Zezwala aplikacji na modyfikowanie rejestru połączeń tabletu, w tym danych o połączeniach przychodzących i wychodzących. Złośliwe aplikacje mogą wykorzystać tę możliwość, by wyczyścić lub zmodyfikować rejestr połączeń." "Pozwala aplikacji modyfikować rejestr połączeń telewizora, w tym dane o połączeniach przychodzących i wychodzących. Szkodliwe aplikacje mogą to wykorzystać do skasowania lub zmodyfikowania rejestru połączeń." "Zezwala aplikacji na modyfikowanie rejestru połączeń telefonu, w tym danych o połączeniach przychodzących i wychodzących. Złośliwe aplikacje mogą wykorzystać tę możliwość, by wyczyścić lub zmodyfikować rejestr połączeń." - "czujniki ciała (np. monitorujące tętno)" + "dostęp do czujników ciała (np. monitorujących tętno)" "Pozwala aplikacji na dostęp do danych z czujników, które monitorują Twój stan fizyczny (np. tętno)." "odczyt wydarzeń w kalendarzu wraz z informacjami poufnymi" "Pozwala aplikacji na odczytywanie wszystkich wydarzeń w kalendarzu zapisanych na tablecie, w tym pochodzących od znajomych i współpracowników. Aplikacja z takim uprawnieniem może udostępniać i zapisywać dane kalendarza niezależnie od ich poufności." @@ -338,15 +338,15 @@ "Pozwala aplikacji na dodawanie, usuwanie i zmienianie zdarzeń, które możesz modyfikować na swoim telefonie, w tym pochodzących od znajomych i współpracowników. Aplikacja z tym uprawnieniem może wysyłać wiadomości, które wyglądają jak pochodzące od właścicieli kalendarza, a także modyfikować zdarzenia bez wiedzy właścicieli." "dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji" "Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie GPS-u lub innych źródeł lokalizacji." - "dokładna lokalizacja (na podstawie sygnału GPS i sieci)" + "dostęp do dokładnej lokalizacji (na podstawie GPS-u i sieci)" "Zezwala aplikacji na określanie dokładnej lokalizacji dzięki sygnałowi GPS lub źródłom lokalizacji sieciowej, takim jak wieże sieci komórkowych i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne dla urządzenia, by aplikacja mogła z nich korzystać. Gdy to uprawnienie jest aktywne, aplikacje mogą określać Twoje położenie. Pamiętaj jednak, że telefon zużywa wtedy więcej energii." - "przybliżona lokalizacja (na podstawie sieci)" + "dostęp do przybliżonej lokalizacji (na podstawie sieci)" "Zezwala aplikacji na określanie przybliżonej lokalizacji. Jest ona odczytywana z usług lokalizacyjnych wykorzystujących źródła lokalizacji sieciowej, takie jak wieże sieci komórkowych i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne dla urządzenia, by aplikacja mogła z nich korzystać. Gdy to uprawnienie jest aktywne, aplikacje mogą określać Twoje przybliżone położenie." "zmienianie ustawień audio" "Pozwala aplikacji na modyfikowanie globalnych ustawień dźwięku, takich jak głośność oraz urządzenie wyjściowe." "nagrywanie dźwięku" "Pozwala aplikacji na nagrywanie dźwięku przez mikrofon. Aplikacja z tym uprawnieniem może nagrywać dźwięk w dowolnym momencie bez Twojego potwierdzenia." - "komunikacja z kartą SIM" + "wysyłanie poleceń do karty SIM" "Pozwala aplikacji na wysyłanie poleceń do karty SIM. To bardzo niebezpieczne." "wykonywanie zdjęć i filmów wideo" "Pozwala aplikacji na robienie zdjęć i nagrywanie filmów przy użyciu aparatu. Aplikacja z tym uprawnieniem może użyć aparatu w dowolnym momencie bez Twojego potwierdzenia." @@ -384,7 +384,7 @@ "Pozwala aplikacji na uzyskanie listy kont zapisanych w telefonie. Może ona obejmować wszystkie konta utworzone przez zainstalowane aplikacje." "wyświetlanie połączeń sieciowych" "Pozwala aplikacji na dostęp do informacji o połączeniach sieciowych – np. o dostępnych i połączonych sieciach." - "pełny dostęp do sieci" + "pełny dostęp do sieci" "Pozwala aplikacji na tworzenie gniazd sieciowych i używanie niestandardowych protokołów sieciowych. Przeglądarka i inne aplikacje zapewniają metody wysyłania danych do internetu, więc w ich przypadku to uprawnienie nie jest potrzebne." "zmienianie połączeń sieci" "Pozwala aplikacji na zmianę stanu łączności sieciowej." @@ -404,7 +404,7 @@ "Pozwala aplikacji na konfigurowanie lokalnego telefonu z funkcją Bluetooth oraz na wykrywanie urządzeń zdalnych i parowanie z nimi." "łączenie się i rozłączanie z siecią WiMAX" "Pozawala aplikacji określić, czy obsługa WiMAX jest włączona, oraz uzyskać informacje o wszystkich podłączonych sieciach WiMAX." - "zmienianie stanu WiMAX" + "zmiana stanu WiMAX" "Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w tablecie." "Pozwala aplikacji nawiązywać i kończyć połączenia telewizora z sieciami WiMAX." "Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w telefonie." @@ -487,7 +487,7 @@ "Zezwala aplikacji na modyfikowanie parametrów kalibracji ekranu dotykowego. Nieprzeznaczone dla zwykłych aplikacji." "dostęp do certyfikatów DRM" "Zezwala aplikacji na dodanie i używanie certyfikatów DRM. Nieprzeznaczone dla zwykłych aplikacji." - "Uzyskiwanie informacji o stanie transmisji Android Beam" + "uzyskiwanie informacji o stanie transmisji Android Beam" "Zezwala tej aplikacji na otrzymywanie informacji o aktualnych transmisjach Android Beam" "usuwanie certyfikatów DRM" "Zezwala aplikacji na usuwanie certyfikatów DRM. Nie powinno być nigdy potrzebne w zwykłych aplikacjach." @@ -1105,11 +1105,11 @@ "Formatuję…" "Nie podłączono" "Nie znaleziono pasujących działań." - "Kierowanie wyjścia multimediów" + "kierowanie wyjścia multimediów" "Pozwala aplikacji na kierowanie wyjściowych danych multimedialnych do innych urządzeń zewnętrznych." - "Odczyt sesji instalacji" + "odczytywanie sesji instalacji" "Pozwala aplikacji odczytywać sesje instalacji. Umożliwia to jej na poznanie szczegółów aktywnych instalacji pakietów." - "Żądanie instalacji pakietów" + "żądanie instalacji pakietów" "Zezwala aplikacji żądanie instalacji pakietów." "Dotknij dwukrotnie, aby sterować powiększeniem." "Nie można dodać widżetu." diff --git a/core/res/res/values-pt-rBR-watch/strings.xml b/core/res/res/values-pt-rBR-watch/strings.xml index 120e4a56044c4..e2053261cc132 100644 --- a/core/res/res/values-pt-rBR-watch/strings.xml +++ b/core/res/res/values-pt-rBR-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d de %2$d." + "Sensores" diff --git a/core/res/res/values-pt-rBR/cm_strings.xml b/core/res/res/values-pt-rBR/cm_strings.xml new file mode 100644 index 0000000000000..9957b78d70bf7 --- /dev/null +++ b/core/res/res/values-pt-rBR/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Captura de tela + + receber SMS protegido + + Permite ao aplicativo receber um SMS protegido. + + modificar lista de SMS protegidos + + Permite ao aplicativo modificar a lista de endereços de SMS protegido. + + Segurança + + Permissões relacionadas às informações de segurança do aparelho. + + ler a lista negra do telefone + + Permite que um aplicativo leia informações sobre números de telefone bloqueados para receber chamadas ou mensagens. + + alterar a lista negra do telefone + + Permite que um aplicativo altere os números de telefone bloqueados para receber chamadas ou enviar mensagens. + + definir papel de parede da tela de bloqueio + + Permite que um aplicativo mude o papel de parede da tela de bloqueio. + + Reiniciar + + Atual + + + Reiniciar + + Recuperação + + Bootloader + + Download + + Reiniciar via software + + Reiniciar + + Seu tablet irá reiniciar. + Seu telefone irá reiniciar. + + Reiniciando\u2026 + + Aplicativo encerrado + + ADB sobre rede ativado + + ABD sobre USB e rede ativado + + Toque para desativar a depuração. + + ADB - %1$s + USB e rede + USB + Rede + + interceptar início de aplicativo + + %s não está instalado + + Prioridade + Nenhum + + Hotspot Wi-Fi desativado devido a mudança de assinatura do SIM + + Desligar Wi-Fi + + ativar ou desativar a Proteção à Privacidade + Permite ao aplicativo alterar se outro aplicativo é executado com Proteção à Privacidade. Quando um aplicativo estiver sendo executado com Proteção à Privacidade, ele não terá acesso a dados pessoais como contatos, registro de chamadas ou mensagens. + Proteção à Privacidade ativa + %1$s não terá acesso a dados pessoais + Proteção à Privacidade + %1$s gostaria de %2$s. + + Lembrar minha escolha + + acessar a câmera + acessar sua localização + ler suas notificações + ativar uma VPN + iniciar ao ligar + deletar seu registro de chamadas + deletar seus contatos + deletar suas mensagens MMS + deletar suas mensagens SMS + desenhar janelas em primeiro plano + obter estatísticas de uso de aplicativo + manter seu dispositivo acordado + fazer uma chamada telefônica + atualizar seu calendário + atualizar o registro de chamadas + modificar a área de transferência + atualizar seus contatos + atualizar configurações de sistema + ligar/desligar o microfone + reproduzir áudio + exibir uma notificação + projetar mídia + ler seu calendário + ler o registro de chamadas + ler a área de transferência + ler seus contatos + ler suas mensagens MMS + ler suas mensagens SMS + receber uma mensagem SMS + gravar áudio + enviar uma mensagem MMS + enviar uma mensagem SMS + iniciar ao ligar + exibir mensagens de aviso na tela + alternar Bluetooth + alternar dados de celular + alternar NFC + alternar Wi-Fi + controlar volume do alarme + controlar o foco do áudio + controlar o volume do Bluetooth + controlar o volume principal + usar os botões de mídia + controlar o volume de mídia + controlar o volume da notificação + controlar o volume do toque + usar reposta ao toque + controlar o volume de chamadas de voz + escrever uma mensagem MMS + escrever uma mensagem SMS + usar a impressão digital + adicionar uma mensagem de voz + acessar estado do telefone + procurar rede Wi-Fi + mudar o papel de parede + usar estrutura de assistência + capturar a tela + usar sensores corporais + ler transmissões da rede de celular + simular a sua localização + ler o armazenamento externo + gravar no armazenamento externo + ligar a tela + obter as contas do dispositivo + alterar o estado do Wi-Fi + obter acesso super usuário + + Para desafixar esta tela, toque e segure o botão Voltar. + + Nenhum dispositivo conectado + %1$s dispositivo conectado + %1$s dispositivos conectados + + + + Início de atividade foi bloqueado + %1$s está protegido de ser iniciado. Toque para autenticar e iniciar o aplicativo. + + Bateria totalmente carregada + Desconecte seu dispositivo do carregador para aumentar a vida útil da bateria. + + redefinir estatísticas da bateria + + Permite a um aplicativo redefinir os dados de baixo nível de uso da bateria. + + Os cartões SIM foram alterados + Toque para definir as preferências do cartão SIM + diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 7050cf82bba65..888b6ed4b232f 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -254,7 +254,7 @@ "Inclui dados pessoais, como números de cartão de crédito e senhas." "desativar ou modificar a barra de status" "Permite que o app desative a barra de status ou adicione e remova ícones do sistema." - "barra de status" + "ser a barra de status" "Permite que o app seja a barra de status." "expandir/recolher barra de status" "Permite que o app expanda ou recolha a barra de status." @@ -282,7 +282,7 @@ "Permite que o app receba e processe mensagens WAP. Esta permissão inclui a capacidade de monitorar ou excluir mensagens enviadas para você sem mostrá-las para você." "recuperar apps em execução" "Permite que o app obtenha informações sobre tarefas em execução atuais e recentes. Pode permitir que o app descubra informações sobre os apps usados ​​no dispositivo." - "Gerenciar proprietários de perfis e de dispositivos" + "gerenciar proprietários de perfis e de dispositivos" "Permitir que os apps definam os proprietários de perfis e de dispositivos." "reordenar os apps em execução" "Permite que o app mova tarefas para o primeiro plano e o plano de fundo, sem sua intervenção." @@ -324,7 +324,7 @@ "Permite que o app modifique o registro de chamadas de seu tablet, incluindo dados sobre chamadas recebidas e efetuadas. Apps maliciosos podem usar esta permissão para apagar ou modificar seu registro de chamadas." "Permite que o app modifique o registro de chamadas da sua TV, incluindo dados sobre chamadas recebidas e efetuadas. Apps maliciosos podem usá-lo para apagar ou modificar seu registro de chamadas." "Permite que o app modifique o registro de chamadas de seu telefone, incluindo dados sobre chamadas recebidas e efetuadas. Apps maliciosos podem usar esta permissão para apagar ou modificar seu registro de chamadas." - "sensores corporais" + "acessar sensores corporais (como monitores de frequência cardíaca)" "Permite que o app acesse dados de sensores que monitoram sua condição física, como a frequência cardíaca." "ler compromissos e informações confidenciais" "Permite que o app leia todos os eventos do calendário armazenados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que o app compartilhe ou salve os dados do calendário, independentemente de sua confidencialidade." @@ -336,15 +336,15 @@ "Permite que o app adicione, remova e altere eventos que você pode modificar em seu telefone, incluindo os de amigos e colegas de trabalho. Isso pode permitir que o app envie mensagens que parecem ser de autoria do proprietário do calendário, ou modifique eventos sem conhecimento do proprietário." "acessar comandos extras do provedor de localização" "Permite que o app acesse comandos do provedor não relacionados à localização. Isso pode permitir que o app interfira no funcionamento do GPS ou de outras fontes de localização." - "localização precisa (GPS e com base na rede)" + "acessar localização precisa (GPS e com base na rede)" "Permite que o app acesse sua localização exata por meio do sistema de posicionamento global (GPS) ou de fontes de localização da rede, como torres de celulares e redes Wi-Fi. Esses serviços de localização devem estar ativados e disponíveis para que sejam usados pelo app. O app pode usar esta permissão para determinar onde você está, além de consumir mais bateria." - "localização aproximada (com base na rede)" + "acessar localização aproximada (com base na rede)" "Permite que o app acesse sua localização aproximada por meio do sistema de posicionamento global (GPS) ou de fontes de localização da rede, como torres de celulares e redes Wi-Fi. Esses serviços de localização devem estar ativados e disponíveis para que sejam usados pelo app. O app pode usar esta permissão para determinar aproximadamente onde você está." "alterar as suas configurações de áudio" "Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída." "gravar áudio" "Permite que o app grave áudio com o microfone. Esta permissão autoriza o app a gravar áudio a qualquer momento, sem sua confirmação." - "comunicação com sim" + "enviar comandos para o SIM" "Permite que o app envie comandos ao SIM. Muito perigoso." "tirar fotos e gravar vídeos" "Permite que o app tire fotos e filme vídeos com a câmera. Esta permissão autoriza o app a usar a câmera a qualquer momento sem sua confirmação." @@ -382,7 +382,7 @@ "Permite que o app obtenha a lista de contas conhecidas pelo telefone. Isso pode incluir todas as contas criadas pelos apps instalados." "ver conexões de rede" "Permite que o app acesse informações sobre conexões de rede, como as redes existentes e conectadas." - "acesso total à rede" + "ter acesso total à rede" "Permite que o app crie soquetes de rede e utilize protocolos de rede personalizados. O navegador e outros apps fornecem meios de enviar dados para a Internet, e por isso esta permissão não é necessária para enviar os dados." "alterar conectividade da rede" "Permite que o app altere o estado de conectividade de rede." @@ -402,7 +402,7 @@ "Permite que um app configure o telefone Bluetooth local, descubra e emparelhe com dispositivos remotos." "conectar e desconectar do WiMAX" "Permite que o app determine se o WiMAX está ativado e acesse informações sobre as redes WiMAX conectadas." - "Alterar estado do WiMAX" + "alterar estado do WiMAX" "Permite que o app conecte e desconecte o tablet de redes WiMAX." "Permite que o app se conecte à TV e desconecte-a de redes WiMAX." "Permite que o app conecte e desconecte o telefone de redes WiMAX." @@ -485,7 +485,7 @@ "Permite que o app modifique os parâmetros de calibragem da tela sensível ao toque. Não deve ser necessário para apps normais." "acessar certificados de DRM" "Permite que o app provisione e use certificados de DRM. Não deve ser necessário para apps comuns." - "Receber status de transferência do Android Beam" + "receber status de transferência do Android Beam" "Permite que este app receba informações sobre as atuais transferências do Android Beam" "remover certificados de DRM" "Permite que um app remova certificados de DRM. Não deve ser necessário para apps comuns." @@ -1091,11 +1091,11 @@ "Formatando..." "Não inserida" "Nenhum atividade correspondente foi encontrada." - "Rotear saída de mídia" + "rotear saída de mídia" "Permite que um app faça o roteamento de saída de mídia para outros dispositivos externos." - "Ler sessões de instalação" + "ler sessões de instalação" "Permite que um app leia sessões de instalação. Isso permite que ele veja detalhes sobre as instalações de pacote ativas." - "Solicitar instalação de pacotes" + "solicitar pacotes de instalação" "Permite que um app solicite a instalação de pacotes." "Toque duas vezes para controlar o zoom" "Não foi possível adicionar widget." diff --git a/core/res/res/values-pt-rPT-watch/strings.xml b/core/res/res/values-pt-rPT-watch/strings.xml index 69d2c0aded780..c992bd6e7b41c 100644 --- a/core/res/res/values-pt-rPT-watch/strings.xml +++ b/core/res/res/values-pt-rPT-watch/strings.xml @@ -21,4 +21,5 @@ "Aplicação %1$d de %2$d." + "Sensores" diff --git a/core/res/res/values-pt-rPT/cm_strings.xml b/core/res/res/values-pt-rPT/cm_strings.xml new file mode 100644 index 0000000000000..db3a1d5d5b282 --- /dev/null +++ b/core/res/res/values-pt-rPT/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Captura de ecrã + + receber SMS protegida + + Permite que a aplicação receba uma SMS protegida. + + modificar a lista de SMS protegidas + + Permite que uma aplicação modifique a lista de endereços de SMS protegidas. + + Segurança + + Permissões relacionadas com as informações de segurança do dispositivo. + + Ler a lista negra do telefone + + Permite que uma aplicação leia informações sobre números de telefone que são bloqueados para chamadas ou mensagens de entrada. + + Alterar a lista negra do telefone + + Permite que uma aplicação altere os números de telefone que são bloqueados para chamadas ou mensagens de entrada. + + Definir a imagem de fundo do ecrã de bloqueio + + Permite que uma aplicação troque a imagem de fundo do ecrã de bloqueio. + + Reiniciar + + Atual + + + Reiniciar + + Recuperação + + Bootloader + + Download + + Reinicialização suave + + Reiniciar + + O seu tablet vai reiniciar. + O seu telefone irá reiniciar. + + A reiniciar\u2026 + + Aplicação terminada + + ADB através da rede ativado + + ABD através de USB e da rede ativado + + Toque para desativar a depuração. + + ADB - %1$s + USB e rede + USB + Rede + + Intercetar a inicialização de uma aplicação + + %s não está instalada + + Prioridade + Nenhum + + Zona Wi-Fi portátil desligada devido à alteração da assinatura SIM + + Desligar Wi-Fi + + ativar ou desativar a Proteção da Privacidade + Permite à aplicação escolher se outra aplicação corre com Proteção da Privacidade. Quando uma aplicação corre com Proteção da Privacidade, não terá acesso a dados pessoais como contactos, registo de chamadas ou mensagens. + Proteção da Privacidade ativa + %1$s não poderá aceder a dados pessoais + Proteção da Privacidade + %1$s gostaria de %2$s. + + Memorizar a minha escolha + + aceder à câmara + aceder à sua localização + ler as suas notificações + ativar uma VPN + iniciar no arranque + eliminar o registo de chamadas + eliminar os seus contactos + eliminar as suas mensagens MMS + eliminar as suas mensagens SMS + desenhar janelas em primeiro plano + obter estatísticas de utilização + manter o seu dispositivo acordado + fazer uma chamada telefónica + atualizar o seu calendário + atualização do registo de chamadas + modificar a área de transferência + atualizar os seus contatos + atualizar as definições de sistema + ligar/desligar o microfone + reproduzir áudio + postar uma notificação + projetar multimédia + ver o seu calendário + ver o registo de chamadas + ver a área de transferência + ver os seus contactos + ver as suas mensagens MMS + ler as suas mensagens SMS + receber uma mensagem de SMS + gravar áudio + Enviar uma mensagem MMS + Enviar uma mensagem SMS + iniciar no arranque + exibir avisos no ecrã + ligar/desligar o bluetooth + alternar o estado dos dados móveis + alternar NFC + alternar Wi-Fi + controlar volume do alarme + controlar o foco de áudio + controlar o volume do bluetooth + controlar o volume principal + usar os botões multimédia + controlar o volume multimédia + controlar o volume de notificação + controlar o volume da campainha + usar a reação tátil + controlar o volume das chamadas de voz + escrever uma mensagem MMS + escrever uma mensagem SMS + usar a impressão digital + adicionar um correio de voz + aceder ao estado do telefone + procurar redes Wi-Fi + mudar a imagem de fundo + usar estrutura de assistência + realizar uma captura de ecrã + usar os sensores corporais + ler transmissões celulares + simular a sua localização + ler do armazenamento externo + escrever no armazenamento externo + ligar o ecrã + obter contas do dispositivo + alterar o estado do Wi-Fi + obter acesso root + + Para soltar este ecrã, toque e segure o botão Anterior. + + Nenhum dispositivo conectado + %1$s dispositivo conectado + %1$s dispositivos conectados + + + + Início de atividades bloqueado + A abertura de %1$s está protegida. Toque para se autenticar e poder iniciar a aplicação. + + Bateria completamente carregada + Desligue o carregador do dispositivo para aumentar a vida útil da bateria. + + reiniciar estatísticas da bateria + + Permite que uma aplicação reinicie os dados de utilização de baixo nível da bateria. + + Os cartões SIM foram alterados + Toque para definir as preferências do cartão SIM + diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 48baf70db9796..27472e9ce3a28 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -254,7 +254,7 @@ "Inclui dados pessoais, como números de cartões de crédito e palavras-passe." "desativar ou modificar barra de estado" "Permite à aplicação desativar a barra de estado ou adicionar e remover ícones do sistema." - "barra de estado" + "ser apresentada na barra de estado" "Permite que a aplicação seja apresentada na barra de estado." "expandir/fechar barra de estado" "Permite à aplicação expandir ou fechar a barra de estado." @@ -282,7 +282,7 @@ "Permite que a aplicação receba e processe mensagens WAP. Esta autorização inclui a capacidade de monitorizar ou eliminar mensagens enviadas para si sem as apresentar." "obter aplicações em execução" "Permite que a aplicação recupere informações acerca de tarefas executadas atual e recentemente. Isto pode permitir que a aplicação descubra informações acerca de quais as aplicações utilizadas no dispositivo." - "Gerir proprietários de perfis e do dispositivo" + "gerir proprietários de perfis e de dispositivos" "Permite que as aplicações definam proprietários de perfis e o proprietário do dispositivo." "reordenar as aplicações em execução" "Permite que a aplicação mova tarefas para primeiro e segundo plano. A aplicação poderá fazê-lo sem qualquer entrada do utilizador." @@ -324,7 +324,7 @@ "Permite à aplicação modificar o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas." "Permite à aplicação modificar o registo de chamadas da sua TV, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas." "Permite à aplicação modificar o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o seu registo de chamadas." - "sensores corporais (como monitores do ritmo cardíaco)" + "aceder a sensores corp. (como monit. do ritmo cardíaco)" "Permite que a aplicação aceda a dados de sensores que monitorizam a sua condição física, como o ritmo cardíaco." "ler eventos do calendário, para além de informações confidenciais" "Permite que a aplicação leia todos os eventos do calendário guardados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que a aplicação partilhe ou guarde dados do calendário, independentemente da confidencialidade ou sensibilidade." @@ -336,15 +336,15 @@ "Permite que a aplicação adicione, remova e altere eventos que pode modificar no telemóvel, incluindo eventos relacionados com amigos ou colegas de trabalho. Pode permitir que a aplicação envie mensagens que parecem ser enviadas pelos proprietários dos calendários ou modifique eventos sem o conhecimento do proprietário." "aceder a comandos adicionais do fornecedor de localização" "Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Esta opção pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização." - "localização exata (baseada no GPS e na rede)" + "aceder à localização exata (baseada no GPS e na rede)" "Permite que a aplicação obtenha a sua localização exata através do Sistema de Posicionamento Global (GPS) ou das fontes de localização da rede, tais como torres de telemóvel e Wi-Fi. Estes serviços de localização têm de estar ativados e disponíveis no dispositivo para que a aplicação os utilize. As aplicações poderão utilizá-los para determinar a sua localização e poderão consumir mais energia da bateria." - "localização aproximada (baseada na rede)" + "aceder à localização aproximada (baseada na rede)" "Permite que a aplicação obtenha a sua localização aproximada. Esta localização é gerada pelos serviços de localização, que utilizam fontes de localização da rede, tais como torres de telemóvel e Wi-Fi. Estes serviços de localização têm de estar ativados e disponíveis no dispositivo para que a aplicação os utilize. As aplicações poderão utilizá-los para determinar a sua localização aproximada." "alterar as suas definições de áudio" "Permite que a aplicação modifique definições de áudio globais, tais como o volume e qual o altifalante utilizado para a saída de som." "gravar áudio" "Permite que a aplicação grave áudio com o microfone. Esta autorização permite que a aplicação grave áudio em qualquer altura sem a confirmação do utilizador." - "comunicação com o SIM" + "enviar comandos para o SIM" "Permite que a aplicação envie comandos para o SIM. Esta ação é muito perigosa." "tirar fotografias e vídeos" "Permite que a aplicação tire fotografias e grave vídeos com a câmara. Esta autorização permite que a aplicação utilize a câmara sem a sua confirmação em qualquer altura." @@ -382,7 +382,7 @@ "Permite que a aplicação obtenha a lista de contas reconhecidas pelo telemóvel. Pode incluir qualquer conta criada pelas aplicações instaladas." "ver ligações de rede" "Permite que a aplicação visualize informações acerca das ligações de rede como, por exemplo, que redes que existem e estão ligadas." - "acesso total à rede" + "ter acesso total à rede" "Permite que a aplicação crie ligações de rede e utilize protocolos de rede personalizados. O navegador e outras aplicações fornecem meios para enviar dados para a Internet, pelo que esta autorização não é necessária para enviar dados para a Internet." "mudar conectividade de rede" "Permite que a aplicação altere o estado de conectividade da rede." @@ -402,7 +402,7 @@ "Permite que a aplicação configure o telemóvel Bluetooth local, bem como descobrir e emparelhar com dispositivos remotos." "ligar e desligar do WiMAX" "Permite que a aplicação determine se o WiMAX está ativado e aceda a informações acerca de qualquer rede WiMAX que esteja ligada." - "Alterar estado do WiMAX" + "alterar estado do WiMAX" "Permite que a aplicação ligue e desligue o tablet de redes WiMAX." "Permite à aplicação ligar e desligar a TV de redes WiMAX." "Permite que a aplicação ligue e desligue o telemóvel de redes WiMAX." @@ -485,7 +485,7 @@ "Permite à aplicação modificar os parâmetros de calibragem do ecrã tátil. Esta funcionalidade nunca deverá ser necessária para aplicações normais." "Aceder a certificados DRM" "Permite que uma aplicação forneça e utilize certificados DRM. Nunca deverá ser necessário para aplicações normais." - "Receber estado de transferência do Android Beam" + "receber estado de transferência do Android Beam" "Permite que esta aplicação receba informações acerca das transferências atuais do Android Beam" "remover certificados DRM" "Permite que uma aplicação remova certificados DRM. Nunca deverá ser necessário para aplicações normais." @@ -1091,11 +1091,11 @@ "A formatar..." "Não inserido" "Não foi encontrada nenhuma atividade correspondente." - "Encaminhar saída de som multimédia" + "encaminhar saída de som multimédia" "Permite que a aplicação encaminhe a saída de som multimédia para outros dispositivos externos." - "Ler sessões de instalação" + "ler sessões de instalação" "Permite que uma aplicação leia sessões de instalação. Isto permite que veja detalhes acerca de instalações de pacotes ativas." - "Solicitar a instalação de pacotes" + "solicitar pacotes de instalação" "Permite que uma aplicação solicite a instalação de pacotes." "Toque duas vezes para controlar o zoom" "Não foi possível adicionar widget." diff --git a/core/res/res/values-pt-watch/strings.xml b/core/res/res/values-pt-watch/strings.xml index 120e4a56044c4..e2053261cc132 100644 --- a/core/res/res/values-pt-watch/strings.xml +++ b/core/res/res/values-pt-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d de %2$d." + "Sensores" diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 7050cf82bba65..888b6ed4b232f 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -254,7 +254,7 @@ "Inclui dados pessoais, como números de cartão de crédito e senhas." "desativar ou modificar a barra de status" "Permite que o app desative a barra de status ou adicione e remova ícones do sistema." - "barra de status" + "ser a barra de status" "Permite que o app seja a barra de status." "expandir/recolher barra de status" "Permite que o app expanda ou recolha a barra de status." @@ -282,7 +282,7 @@ "Permite que o app receba e processe mensagens WAP. Esta permissão inclui a capacidade de monitorar ou excluir mensagens enviadas para você sem mostrá-las para você." "recuperar apps em execução" "Permite que o app obtenha informações sobre tarefas em execução atuais e recentes. Pode permitir que o app descubra informações sobre os apps usados ​​no dispositivo." - "Gerenciar proprietários de perfis e de dispositivos" + "gerenciar proprietários de perfis e de dispositivos" "Permitir que os apps definam os proprietários de perfis e de dispositivos." "reordenar os apps em execução" "Permite que o app mova tarefas para o primeiro plano e o plano de fundo, sem sua intervenção." @@ -324,7 +324,7 @@ "Permite que o app modifique o registro de chamadas de seu tablet, incluindo dados sobre chamadas recebidas e efetuadas. Apps maliciosos podem usar esta permissão para apagar ou modificar seu registro de chamadas." "Permite que o app modifique o registro de chamadas da sua TV, incluindo dados sobre chamadas recebidas e efetuadas. Apps maliciosos podem usá-lo para apagar ou modificar seu registro de chamadas." "Permite que o app modifique o registro de chamadas de seu telefone, incluindo dados sobre chamadas recebidas e efetuadas. Apps maliciosos podem usar esta permissão para apagar ou modificar seu registro de chamadas." - "sensores corporais" + "acessar sensores corporais (como monitores de frequência cardíaca)" "Permite que o app acesse dados de sensores que monitoram sua condição física, como a frequência cardíaca." "ler compromissos e informações confidenciais" "Permite que o app leia todos os eventos do calendário armazenados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que o app compartilhe ou salve os dados do calendário, independentemente de sua confidencialidade." @@ -336,15 +336,15 @@ "Permite que o app adicione, remova e altere eventos que você pode modificar em seu telefone, incluindo os de amigos e colegas de trabalho. Isso pode permitir que o app envie mensagens que parecem ser de autoria do proprietário do calendário, ou modifique eventos sem conhecimento do proprietário." "acessar comandos extras do provedor de localização" "Permite que o app acesse comandos do provedor não relacionados à localização. Isso pode permitir que o app interfira no funcionamento do GPS ou de outras fontes de localização." - "localização precisa (GPS e com base na rede)" + "acessar localização precisa (GPS e com base na rede)" "Permite que o app acesse sua localização exata por meio do sistema de posicionamento global (GPS) ou de fontes de localização da rede, como torres de celulares e redes Wi-Fi. Esses serviços de localização devem estar ativados e disponíveis para que sejam usados pelo app. O app pode usar esta permissão para determinar onde você está, além de consumir mais bateria." - "localização aproximada (com base na rede)" + "acessar localização aproximada (com base na rede)" "Permite que o app acesse sua localização aproximada por meio do sistema de posicionamento global (GPS) ou de fontes de localização da rede, como torres de celulares e redes Wi-Fi. Esses serviços de localização devem estar ativados e disponíveis para que sejam usados pelo app. O app pode usar esta permissão para determinar aproximadamente onde você está." "alterar as suas configurações de áudio" "Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída." "gravar áudio" "Permite que o app grave áudio com o microfone. Esta permissão autoriza o app a gravar áudio a qualquer momento, sem sua confirmação." - "comunicação com sim" + "enviar comandos para o SIM" "Permite que o app envie comandos ao SIM. Muito perigoso." "tirar fotos e gravar vídeos" "Permite que o app tire fotos e filme vídeos com a câmera. Esta permissão autoriza o app a usar a câmera a qualquer momento sem sua confirmação." @@ -382,7 +382,7 @@ "Permite que o app obtenha a lista de contas conhecidas pelo telefone. Isso pode incluir todas as contas criadas pelos apps instalados." "ver conexões de rede" "Permite que o app acesse informações sobre conexões de rede, como as redes existentes e conectadas." - "acesso total à rede" + "ter acesso total à rede" "Permite que o app crie soquetes de rede e utilize protocolos de rede personalizados. O navegador e outros apps fornecem meios de enviar dados para a Internet, e por isso esta permissão não é necessária para enviar os dados." "alterar conectividade da rede" "Permite que o app altere o estado de conectividade de rede." @@ -402,7 +402,7 @@ "Permite que um app configure o telefone Bluetooth local, descubra e emparelhe com dispositivos remotos." "conectar e desconectar do WiMAX" "Permite que o app determine se o WiMAX está ativado e acesse informações sobre as redes WiMAX conectadas." - "Alterar estado do WiMAX" + "alterar estado do WiMAX" "Permite que o app conecte e desconecte o tablet de redes WiMAX." "Permite que o app se conecte à TV e desconecte-a de redes WiMAX." "Permite que o app conecte e desconecte o telefone de redes WiMAX." @@ -485,7 +485,7 @@ "Permite que o app modifique os parâmetros de calibragem da tela sensível ao toque. Não deve ser necessário para apps normais." "acessar certificados de DRM" "Permite que o app provisione e use certificados de DRM. Não deve ser necessário para apps comuns." - "Receber status de transferência do Android Beam" + "receber status de transferência do Android Beam" "Permite que este app receba informações sobre as atuais transferências do Android Beam" "remover certificados de DRM" "Permite que um app remova certificados de DRM. Não deve ser necessário para apps comuns." @@ -1091,11 +1091,11 @@ "Formatando..." "Não inserida" "Nenhum atividade correspondente foi encontrada." - "Rotear saída de mídia" + "rotear saída de mídia" "Permite que um app faça o roteamento de saída de mídia para outros dispositivos externos." - "Ler sessões de instalação" + "ler sessões de instalação" "Permite que um app leia sessões de instalação. Isso permite que ele veja detalhes sobre as instalações de pacote ativas." - "Solicitar instalação de pacotes" + "solicitar pacotes de instalação" "Permite que um app solicite a instalação de pacotes." "Toque duas vezes para controlar o zoom" "Não foi possível adicionar widget." diff --git a/core/res/res/values-rm/cm_strings.xml b/core/res/res/values-rm/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-rm/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ro-watch/strings.xml b/core/res/res/values-ro-watch/strings.xml index 95c8ec3871cd6..dc50565d05c6d 100644 --- a/core/res/res/values-ro-watch/strings.xml +++ b/core/res/res/values-ro-watch/strings.xml @@ -21,4 +21,5 @@ "Aplic. %1$d din %2$d." + "Senzori" diff --git a/core/res/res/values-ro/cm_strings.xml b/core/res/res/values-ro/cm_strings.xml new file mode 100644 index 0000000000000..1587713f57962 --- /dev/null +++ b/core/res/res/values-ro/cm_strings.xml @@ -0,0 +1,189 @@ + + + + + + Captură de ecran + + primește SMS-uri protejate + + Permite aplicației să primească un SMS protejat. + + modifică lista de SMS-uri protejate + + Permite aplicației să modifice lista adreselor SMS protejate. + + Securitate + + Permisiunile legate de informațiile de securitate ale dispozitivului. + + citește lista neagră a telefonului + + Permite unei aplicații să citească informații despre numerele de telefon care sunt blocate pentru primirea de apeluri sau de mesaje. + + schimbă lista neagră a telefonului + + Permite unei aplicații să schimbe numere de telefon care sunt blocate pentru primirea de apeluri sau mesaje. + + setare fundal ecran de blocare + + Permite unei aplicații să schimbe imaginea de fundal a ecranului de blocare. + + Repornire + + Actual + + + Repornire + + Recovery + + Bootloader + + Descărcare + + Repornirea sistemului + + Repornire + + Tableta va reporni. + Telefonul dvs. va reporni. + + Repornire\u2026 + + Aplicație oprită + + ADB prin rețea activ + + ADB prin USB & rețea activ + + Apasă pentru dezactivarea depanării. + + ADB - %1$s + USB & rețea + USB + Rețea + + interceptează lansarea aplicației + + %s nu este instalată + + Prioritate + Nimic + + + Oprește Wi-Fi + + activează sau dezactivează Privacy Guard + Permite aplicației să stabilească dacă o altă aplicație rulează cu garda de confidențialitate. Când o aplicație rulează cu garda de confidențialitate, nu va avea acces la date personale, cum ar fi contacte, jurnalul de apeluri sau mesaje. + Protejarea datelor activată + %1$s nu va putea accesa datele personale + Privacy Guard + %1$s dorește să %2$s. + + Memorează alegerea mea + + accesează camera + accesează locația + citește notificările + activați un VPN + lansează la pornire + șterge lista de apeluri + șterge lista de contacte + șterge mesajele MMS + șterge mesajele SMS + lansează ferestre deasupra + obține statistici de utilizare a aplicației + ține dispozitivul deschis + inițiază un apel telefonic + actualizează calendarul + actualizează jurnalul de apeluri + modifică clipboard + actualizează contacte + actualizează setări de sistem + activează/dezactivează microfonul + redă sunet + trimite o notificare + proiect media + citește calendarul + citește jurnalul de apeluri + citește clipboard-ul + citește contactele + citește mesajele MMS + citește mesajele SMS + primește un mesaj SMS + înregistrare audio + trimite un mesaj MMS + trimite un mesaj SMS + începe la pornire + afișează mesajele temporare + comută Bluetooth + comutare date mobile + Comutare NFC + comută Wi-Fi + controlează volumul alarmei + controlează focalizarea audio + controlează volumul Bluetooth + controlează volumul master + folosește butoanele media + controlează volumul media + controlează volumul la notificare + controlează volumul la sonerie + folosește răspunsul tactil + controlează volumul apelului de voce + scrie un mesaj MMS + scrie un mesaj SMS + utilizează amprentă digitală + adaugă un mesaj vocal + citește starea telefonului + scanează rețelele Wi-Fi + schimbă imaginea de fundal + folosește structura de asistență + face o captură de ecran + utilizează senzorii corporali + citește trasmisiunile din rețea + simulează locația dvs. + citește stocare externă + scrie stocare externă + pornește ecranul + obține conturile dispozitivului + schimbă starea Wi-Fi + obțină acces root + + Pentru a anula fixarea acestui ecran, atingeți și țineți apăsat butonul Înapoi. + + Niciun dispozitiv conectat + %1$s dispozitiv conectat + %1$s dispozitive conectate + + + + Lansarea activității blocată + + Acumulator încărcat complet + Deconectați aparatul de la încărcător pentru a îmbunătăți longevitatea bateriei. + + resetează statisticile bateriei + + Permite unei aplicații să reseteze datele curente de utilizare a bateriei. + + diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 1bbabfaa49e5b..9a503a33ed762 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -201,7 +201,7 @@ "Telefonul dvs. se va închide." "Doriți să închideţi?" "Reporniţi în modul sigur" - "Doriți să reporniţi în modul sigur? Astfel vor fi dezactivate toate aplicațiile terţă parte pe care le-aţi instalat. Acestea vor fi restabilite când reporniţi din nou." + "Doriți să reporniţi în modul sigur? Astfel vor fi dezactivate toate aplicațiile terţă parte pe care le-ați instalat. Acestea vor fi restabilite când reporniţi din nou." "Recente" "Nu există aplicații recente." "Opţiuni tablet PC" @@ -255,7 +255,7 @@ "Include date personale, cum ar fi numere ale cardurilor de credit sau parole." "dezactivare sau modificare bare de stare" "Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem." - "bară de stare" + "să fie bara de stare" "Permite aplicației să fie bară de stare." "extindere/restrângere bară de stare" "Permite aplicației să extindă sau să restrângă bara de stare." @@ -283,7 +283,7 @@ "Permite aplicației să primească și să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau șterge mesajele care v-au fost trimise fără a vi le arăta." "preluare aplicații care rulează" "Permite aplicației să preia informațiile despre activităţile care rulează în prezent și care au rulat recent. În acest fel, aplicația poate descoperi informații despre aplicațiile care sunt utilizate pe dispozitiv." - "Gestionează proprietarii de profiluri și proprietarul dispozitivului" + "să gestioneze profilul și proprietarii dispozitivului" "Permite aplicațiilor să seteze proprietarii de profiluri și proprietarul dispozitivului." "reordonare aplicații care rulează" "Permite aplicației să mute activităţile în prim-plan și în fundal. Aplicaţia poate face acest lucru fără aportul dvs." @@ -325,7 +325,7 @@ "Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri." "Permite aplicației să modifice jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău-intenționate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul de apeluri." "Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri." - "senzori (ex.: senzori de ritm cardiac)" + "să acceseze senzorii corporali (cum ar fi monitoarele cardiace)" "Permite aplicației să acceseze date de la senzorii care vă monitorizează starea fizică, cum ar fi ritmul cardiac." "citirea evenimentelor din calendar și a informaţiilor confidenţiale" "Permite aplicației să citească toate evenimentele din calendar stocate pe tabletă, inclusiv cele ale prietenilor sau colegilor. Acest lucru poate permite aplicației să distribuie sau să salveze datele din calendar, indiferent dacă acestea sunt confidenţiale sau sensibile." @@ -337,15 +337,15 @@ "Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe telefon, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără știrea proprietarilor." "accesare comenzi suplimentare ale furnizorului locației" "Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații." - "locaţia exactă (bazată pe rețea și GPS)" - "Permite aplicației să obţină locaţia dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. și pot să consume mai multă energie a bateriei." - "locaţia aproximativă (bazată pe rețea)" - "Permite aplicației să obţină locaţia dvs. aproximativă. Această locație este dedusă de serviciile de localizare utilizând surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locaţia dvs. aproximativă." + "să acceseze locația exactă (bazată pe GPS și pe rețea)" + "Permite aplicației să obţină locația dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locația dvs. și pot să consume mai multă energie a bateriei." + "să acceseze locația aproximativă (bazată pe rețea)" + "Permite aplicației să obţină locația dvs. aproximativă. Această locație este dedusă de serviciile de localizare utilizând surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicaţiile pot utiliza această permisiune pentru a determina locația dvs. aproximativă." "modificare setări audio" "Permite aplicației să modifice setările audio globale, cum ar fi volumul și difuzorul care este utilizat pentru ieșire." "înregistreze sunet" "Permite aplicației să efectueze înregistrări audio cu ajutorul microfonului. Cu această permisiune aplicația efectuează oricând înregistrări audio fără confirmare." - "comunicare cu cardul SIM" + "să trimită comenzi către SIM" "Permite aplicației să trimită comenzi pe cardul SIM. Această permisiune este foarte periculoasă." "realizarea de fotografii și videoclipuri" "Permite aplicației să realizeze fotografii și videoclipuri cu camera foto. Cu această permisiune aplicația utilizează camera foto oricând și fără confirmare." @@ -358,7 +358,7 @@ "accesează serviciul de apelare IMS" "Permite aplicației să folosească serviciul IMS pentru apeluri, fără intervenția dvs." "citeşte starea și identitatea telefonului" - "Permite aplicației să acceseze funcţiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanţă conectat printr-un apel." + "Permite aplicației să acceseze funcţiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel." "împiedicarea computerului tablet PC să intre în repaus" "împiedică intrarea televizorului în stare de inactivitate" "împiedicare intrare telefon în repaus" @@ -378,19 +378,19 @@ "Permite aplicației să modifice fusul orar al televizorului." "Permite aplicației să schimbe fusul orar al telefonului." "găseşte conturi pe dispozitiv" - "Permite aplicației să obţină lista de conturi cunoscute de tabletă. Aceasta poate include conturile create de aplicațiile pe care le-aţi instalat." + "Permite aplicației să obţină lista de conturi cunoscute de tabletă. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat." "Permite aplicației să obțină lista de conturi cunoscute de televizor. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat." - "Permite aplicației să obţină lista de conturi cunoscute de telefon. Aceasta poate include conturile create de aplicațiile pe care le-aţi instalat." + "Permite aplicației să obţină lista de conturi cunoscute de telefon. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat." "vizualizează conexiunile la rețea" - "Permite aplicației să vadă informaţiile despre conexiunile la rețea, cum ar fi reţelele existente și cele care sunt conectate." - "acces deplin la rețea" + "Permite aplicației să vadă informațiile despre conexiunile la rețea, cum ar fi reţelele existente și cele care sunt conectate." + "să aibă acces deplin la rețea" "Permite aplicației să creeze socluri de rețea și să utilizeze protocoale de rețea personalizate. Browserul și alte aplicații oferă mijloacele de trimitere a datelor pe internet, astfel încât această permisiune nu este necesară pentru trimiterea datelor pe internet." "modificare conectivitate în rețea" "Permite aplicației să modifice starea de conectivitate la rețea." "modificare conectivitate tethering" "Permite aplicației să modifice starea de conectivitate prin tethering la rețea." "vizualizează conexiunile Wi-Fi" - "Permite aplicației să vadă informaţiile despre reţelele Wi-Fi, de ex. dacă o rețea Wi-Fi este activată, precum și numele dispozitivelor conectate la rețeaua Wi-Fi." + "Permite aplicației să vadă informațiile despre reţelele Wi-Fi, de ex. dacă o rețea Wi-Fi este activată, precum și numele dispozitivelor conectate la rețeaua Wi-Fi." "se conectează și se deconectează de la Wi-Fi" "Permite aplicației să se conecteze și să se deconecteze de la punctele de acces Wi-Fi, precum și să efectueze modificări în configuraţia dispozitivului pentru reţelele Wi-Fi." "permitere recepţionare difuzare multiplă Wi-Fi" @@ -398,12 +398,12 @@ "Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar televizorul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă." "Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar telefonul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă." "accesează setările Bluetooth" - "Permite aplicației să configureze tableta Bluetooth locală, să descopere și să se împerecheze cu dispozitive la distanţă." + "Permite aplicației să configureze tableta Bluetooth locală, să descopere și să se împerecheze cu dispozitive la distanță." "Permite aplicației să configureze televizorul Bluetooth local, precum și să descopere și să se asocieze cu dispozitive la distanță." - "Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanţă." + "Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanță." "se conectează și se deconectează de la WiMAX" - "Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informaţiile cu privire la toate reţelele WiMAX conectate." - "Schimbaţi starea WiMAX" + "Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informațiile cu privire la toate reţelele WiMAX conectate." + "schimbaţi starea WiMAX" "Permite aplicației să conecteze și să deconecteze tableta la și de la reţelele WiMAX." "Permite aplicației să conecteze și să deconecteze televizorul la și de la rețelele WiMAX." "Permite aplicației să conecteze și să deconecteze telefonul la și de la reţelele WiMAX." @@ -486,7 +486,7 @@ "Permite aplicației să modifice parametrii de calibrare a ecranului tactil. Nu ar trebui să fie necesară pentru aplicațiile obișnuite." "accesează certificatele DRM" "Permite unei aplicații să furnizeze și să utilizeze certificate DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite." - "Primiți starea transferului prin Android Beam" + "să primească starea transferului prin Android Beam" "Permite acestei aplicații să primească informații despre transferurile actuale Android Beam" "eliminarea certificatelor DRM" "Permite unei aplicații să elimine certificatele DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite." @@ -499,7 +499,7 @@ "Setați reguli pentru parolă" "Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului." "Monitorizați încercările de deblocare a ecranului" - "Monitorizaţi numărul de parole incorecte introduse la deblocarea ecranului și blocaţi tableta sau ştergeţi datele acesteia dacă sunt introduse prea multe parole incorecte." + "Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocaţi tableta sau ștergeți datele acesteia dacă sunt introduse prea multe parole incorecte." "Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați televizorul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte." "Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați telefonul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte." "Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați tableta sau ștergeți toate datele acestui utilizator dacă se introduc prea multe parole incorecte." @@ -716,7 +716,7 @@ "Modelul a fost desenat" "Zonă model." "%1$s. Widget %2$d din %3$d." - "Adăugaţi un widget." + "Adăugați un widget." "Gol" "Zona de deblocare a fost extinsă." "Zona de deblocare a fost restrânsă." @@ -747,7 +747,7 @@ "%-l %p" "Testarea de fabrică nu a reuşit" "Acţiunea FACTORY_TEST este acceptată doar pentru pachetele instalate în /system/app." - "Nu s-a găsit niciun pachet care să ofere acţiunea FACTORY_TEST." + "Nu s-a găsit niciun pachet care să ofere acțiunea FACTORY_TEST." "Reporniți" "La pagina de la „%s” apare:" "JavaScript" @@ -785,8 +785,8 @@ "Permite aplicației să seteze o alarmă într-o aplicație de ceas cu alarmă instalată. Este posibil ca unele aplicații de ceas cu alarmă să nu implementeze această funcție." "adăugare mesagerie vocală" "Permite aplicației să adauge mesaje în Mesaje primite în mesageria vocală." - "modificare permisiuni pentru locaţia geografică a browserului" - "Permite aplicației să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri web arbitrare." + "modificare permisiuni pentru locația geografică a browserului" + "Permite aplicației să modifice permisiunile privind locația geografică a browserului. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informaţiilor privind locația către site-uri web arbitrare." "Doriți ca browserul să reţină această parolă?" "Nu acum" "Reţineţi" @@ -806,8 +806,8 @@ "Trimiteți interogarea" "Căutare vocală" "Activați Explorați prin atingere?" - "%1$s doreşte să activeze funcţia Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu tableta." - "%1$s doreşte să activeze funcţia Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu telefonul." + "%1$s doreşte să activeze funcția Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu tableta." + "%1$s doreşte să activeze funcția Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu telefonul." "cu 1 lună în urmă" "Cu mai mult de 1 lună în urmă" @@ -848,7 +848,7 @@ O oră "Problemă video" - "Acest fişier video nu este valid pentru a fi transmis în flux către acest dispozitiv." + "Acest fișier video nu este valid pentru a fi transmis în flux către acest dispozitiv." "Nu puteți reda acest videoclip" "OK" "%1$s, %2$s" @@ -867,7 +867,7 @@ "Copiați adresa URL" "Selectați text" "Selectare text" - "Adăugaţi în dicţionar" + "Adăugați în dicţionar" "Ștergeți" "Metodă de intrare" "Acţiuni pentru text" @@ -897,8 +897,8 @@ "Se utilizează în mod prestabilit pentru această acţiune." "Utilizați altă aplicație" "Ștergeți setările prestabilite din Setări de sistem > Aplicații > Descărcate." - "Alegeţi o acţiune" - "Alegeţi o aplicație pentru dispozitivul USB" + "Alegeți o acţiune" + "Alegeți o aplicație pentru dispozitivul USB" "Această acţiune nu poate fi efectuată de nicio aplicație." "Din păcate, %1$s s-a oprit." @@ -932,14 +932,14 @@ "Comutaţi între aplicații?" "O altă aplicație rulează deja și trebuie oprită înainte a putea porni o aplicație nouă." "Reveniţi la %1$s" - "Nu porniţi aplicația nouă." + "Nu porniți aplicația nouă." "Porniţi %1$s" - "Opriți vechea aplicație fără să salvaţi." + "Opriți vechea aplicație fără să salvați." "%1$s a depășit limita de memorie" "Datele privind memoria au fost culese; atingeți pentru a trimite" "Trimiteți datele privind memoria?" "Procesul %1$s și-a depășit limita de memorie de %2$s. Sunt disponibile datele privind memoria, pe care le puteți trimite dezvoltatorului. Atenție: aceste date privind memoria pot conține informațiile personale la care aplicația are acces." - "Alegeţi o acţiune pentru text" + "Alegeți o acţiune pentru text" "Volum sonerie" "Volum media" "Redare prin Bluetooth" @@ -1006,7 +1006,7 @@ "Acest lucru va genera costuri în contul dvs. mobil." "Trimiteți" "Anulați" - "Doresc să se reţină opţiunea" + "Doresc să se reţină opțiunea" "Puteți modifica ulterior în Setări > Aplicații" "Permiteți întotdeauna" "Nu permiteți niciodată" @@ -1098,11 +1098,11 @@ "Se formatează…" "Nu este introdus" "Nu s-a găsit nicio activitate potrivită." - "Direcționează rezultatele media" + "să direcționeze rezultatele media" "Permite unei aplicații să direcționeze rezultate media către alte dispozitive externe." - "Citirea sesiunilor de instalare" + "să citească sesiunile de instalare" "Permite unei aplicații accesul la citirea sesiunilor de instalare. Aceasta poate vedea detalii despre instalările de pachete active." - "Solicită instalarea pachetelor" + "să solicite pachete de instalare" "Permite unei aplicații să solicite instalarea pachetelor." "Atingeți de două ori pentru a mări/micşora" "Nu s-a putut adăuga widgetul." @@ -1114,7 +1114,7 @@ "Înapoi" "Executați" "Formaţi numărul\nutilizând %s" - "Creaţi contactul\nutilizând %s" + "Creați contactul\nutilizând %s" "Următoarele aplicații solicită permisiunea de a accesa contul dvs. acum și în viitor." "Permiteți această solicitare?" "Solicitare de acces" @@ -1139,7 +1139,7 @@ "Conectat(ă) la reţeaua VPN activată permanent" "Eroare de rețea VPN activată permanent" "Atingeți pentru a configura" - "Alegeţi un fişier" + "Alegeți un fișier" "Nu au fost găsite fișiere" "Resetaţi" "Trimiteți" @@ -1175,25 +1175,25 @@ "Ștergeți elementele" "Anulați aceste ştergeri" "Nu trebuie să luați nicio măsură deocamdată" - "Alegeţi un cont" - "Adăugaţi un cont" - "Adăugaţi un cont" + "Alegeți un cont" + "Adăugați un cont" + "Adăugați un cont" "Creșteți" - "Reduceţi" + "Reduceți" "Atingeți și țineți apăsat %s." "Glisaţi în sus pentru a creşte și în jos pentru a reduce." "Creșteți valoarea pentru minute" - "Reduceţi valoarea pentru minute" + "Reduceți valoarea pentru minute" "Creșteți valoarea pentru oră" - "Reduceţi valoarea pentru oră" + "Reduceți valoarea pentru oră" "Setaţi valoarea PM" "Setaţi valoarea AM" "Creșteți valoarea pentru lună" - "Reduceţi valoarea pentru lună" + "Reduceți valoarea pentru lună" "Creșteți valoarea pentru zi" - "Reduceţi valoarea pentru zi" + "Reduceți valoarea pentru zi" "Creșteți valoarea pentru an" - "Reduceţi valoarea pentru an" + "Reduceți valoarea pentru an" "Luna trecută" "Luna viitoare" "Alt" @@ -1203,7 +1203,7 @@ "Schimbarea modului" "Shift" "Enter" - "Alegeţi o aplicație" + "Alegeți o aplicație" "Nu s-a putut lansa %s" "Permiteți accesul pentru" "Permiteți accesul pentru %s" @@ -1213,7 +1213,7 @@ "Punct." "Navigaţi la ecranul de pornire" "Navigaţi în sus" - "Mai multe opţiuni" + "Mai multe opțiuni" "%1$s, %2$s" "%1$s, %2$s, %3$s" "Stocare internă" @@ -1251,7 +1251,7 @@ "Amprentă SHA-256:" "Amprentă SHA-1:" "Afişaţi-le pe toate" - "Alegeţi activitatea" + "Alegeți activitatea" "Distribuiţi pentru" ", " "Se trimite..." diff --git a/core/res/res/values-ru-watch/strings.xml b/core/res/res/values-ru-watch/strings.xml index f32f63b96ba81..29f3516febb05 100644 --- a/core/res/res/values-ru-watch/strings.xml +++ b/core/res/res/values-ru-watch/strings.xml @@ -21,4 +21,5 @@ "Приложение %1$d из %2$d" + "Датчики" diff --git a/core/res/res/values-ru/cm_strings.xml b/core/res/res/values-ru/cm_strings.xml new file mode 100644 index 0000000000000..38f6a5992399e --- /dev/null +++ b/core/res/res/values-ru/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Скриншот + + Получение защищённых SMS + + Приложение сможет получать входящие защищённые SMS-сообщения. + + Изменение списка защищённых SMS + + Приложение сможет изменять список адресатов защищённых SMS-сообщений. + + Безопасность + + Разрешения, относящиеся к безопасности данных на устройстве. + + Просмотр чёрного списка + + Приложение сможет считывать информацию о списке абонентов, от которых заблокированы входящие вызовы или сообщения. + + Изменение чёрного списка + + Приложение сможет изменять список абонентов, от которых заблокированы входящие вызовы или сообщения. + + Установка обоев экрана блокировки + + Приложение сможет изменять обои экрана блокировки устройства. + + Перезагрузить + + Текущий + + + Перезагрузка + + Режим восстановления + + Загрузчик + + Режим обновления ПО + + Перезапуск интерфейса + + Перезагрузка + + Ваш планшет будет перезагружен. + Ваш телефон будет перезагружен. + + Перезагрузка\u2026 + + Приложение закрыто + + Отладка по сети разрешена + + Отладка по сети и USB разрешена + + Нажмите, чтобы отключить отладку. + + Отладка %1$s + по сети и USB + по USB + по сети + + Перехват запуска приложений + + «%s» не установлено + + Важные + Нет + + Точка доступа Wi-Fi отключена из-за переключения SIM-карты + + Выключить Wi-Fi + + Включение или выключение защищённого режима + Приложение сможет изменять состояние защищённого режима для других приложений. Когда приложение запущено в защищённом режиме, оно не получает доступ к персональным данным, таким как контакты, сообщения или журнал звонков. + Защищённый режим включён + У «%1$s» нет доступа к персональным данным + Защищённый режим + Приложение «%1$s» пытается %2$s. + + Запомнить разрешение + + получить доступ к камере + получить доступ к местоположению устройства + получить доступ к уведомлениям + активировать VPN + назначить запуск при включении устройства + удалить журнал звонков + удалить контакты + удалить MMS-сообщения + удалить SMS-сообщения + отображать элементы интерфейса поверх других окон + получать статистику использования приложений + запретить устройству переход в спящий режим + выполнить телефонный звонок + изменить данные календаря + изменить данные журнала звонков + изменить содержимое буфера обмена + изменить данные контактов + изменить системные параметры + выключить или включить микрофон + воспроизведение аудио + вывести уведомление + выполнить трансляцию контента + считать данные календаря + считать данные списка вызовов + считать содержимое буфера обмена + считать данные контактов + считать MMS-сообщения + считать SMS-сообщения + получить SMS-сообщение + записать аудио + отправить MMS-сообщение + отправить SMS-сообщение + назначить запуск при включении устройства + отображать всплывающие уведомления + переключить состояние Bluetooth + переключить состояние мобильного интернета + переключить состояние модуля NFC + переключить состояние Wi-Fi + получить управление громкостью будильника + получить управление аудиофокусом + получить управление громкостью Bluetooth-устройств + получить управление общей громкостью + использовать кнопки мультимедиа + получить управление громкостью мультимедиа + получить управление громкостью уведомлений + получить управление громкостью звонка + использовать виброотклик + получить управление громкостью при разговоре + создать MMS-сообщение + создать SMS-сообщение + использовать сканер отпечатков пальцев + добавить сообщение голосовой почты + получить данные о состоянии телефона + выполнить сканирование сетей Wi-Fi + изменить обои + использовать структуру ассистента + сделать скриншот + использовать нательные датчики + прочитать сообщения оповещения населения + предоставить фиктивные сведения о местоположении + прочитать данные с внешнего накопителя + записать данные на внешнее запоминающее устройство + включить экран + получить информацию об аккаунтах + изменить состояние Wi-Fi + получить права суперпользователя + + Чтобы открепить экран, нажмите и удерживайте кнопку «Назад». + + Нет подключенных устройств + %1$s подключенное устройство + Подключено устройств: %1$s + + + + Запуск приложения запрещён + Приложение «%1$s» заблокировано. Нажмите, чтобы ввести пароль и запустить приложение. + + Аккумулятор полностью заряжен + Отключите устройство от сети для продления срока службы батареи. + + Обнуление статистики батареи + + Разрешить приложению очищать данные об использовании аккумуляторной батареи устройства. + + SIM-карты изменились + Нажмите, чтобы задать параметры по умолчанию для SIM-карты + diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index b857f27598549..e1d344e568b9c 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -256,7 +256,7 @@ "В том числе личные данные, например номера кредитных карт и пароли." "Отключение/изменение строки состояния" "Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки." - "Строка состояния" + "Замена строки состояния" "Приложение сможет заменять собой строку состояния." "Разворачивание/сворачивание строки состояния" "Приложение сможет разворачивать и сворачивать строку состояния." @@ -284,7 +284,7 @@ "Приложение сможет получать и обрабатывать WAP-сообщения. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их." "Получение данных о запущенных приложениях" "Приложение сможет получать информацию о недавно запущенных и выполняемых задачах, а следовательно, и о приложениях, используемых на устройстве." - "Управление профилями и владельцами" + "Управление профилями и владельцами" "Приложения смогут определять владельцев профилей и владельца устройства." "Упорядочивание запущенных приложений" "Приложение сможет переключать активный и фоновый режимы выполнения задач без вашего ведома." @@ -326,7 +326,7 @@ "Приложение сможет вносить изменения в список вызовов планшетного ПК и данные о входящих и исходящих звонках. Вредоносные приложения смогут воспользоваться этим для удаления или изменения информации о звонках." "Изменение списка вызовов телевизора и данных о входящих и исходящих звонках. Вредоносные приложения смогут воспользоваться этим для удаления или изменения информации о звонках." "Приложение сможет вносить изменения в список вызовов телефона и данные о входящих и исходящих звонках. Вредоносные приложения смогут воспользоваться этим для удаления или изменения информации о звонках." - "датчики (например, пульсометр)" + "Датчики (например, пульсометр)" "Приложение сможет получить доступ к данным датчиков, размещенных на теле, например измеряющих частоту сердцебиения." "Просмотр в календаре мероприятий и конфиденциальных данных" "Приложение сможет просматривать мероприятия в календаре устройства, в том числе добавленные друзьями или коллегами, а также передавать и сохранять данные календаря независимо от настроек конфиденциальности." @@ -338,15 +338,15 @@ "Приложение сможет добавлять, удалять и изменять мероприятия, доступные для редактирования на вашем телефоне, включая мероприятия, добавленные другими людьми. Так приложение сможет рассылать сообщения от имени владельца календаря и изменять мероприятия без его ведома." "Доступ к дополнительным командам управления источниками геоданных" "Доступ к дополнительным командам управления источниками геоданных и вмешательство в работу системы GPS или других источников геоданных." - "Точное местоположение (на основе сети и сигналов GPS)" + "Доступ к точному местоположению (по координатам сети и спутникам GPS)" "Разрешает приложению получать данные о вашем точном местоположении с помощью глобального позиционирования (GPS), вышек сотовой связи и точек доступа Wi-Fi. Эти службы должны быть включены на устройстве, а приложению должно быть разрешено их использовать. Это может вести к дополнительному расходу заряда батареи." - "Примерное местоположение (на основе сети)" + "Доступ к примерному местоположению (по координатам сети)" "Разрешает приложению получать данные о вашем примерном местоположении с помощью служб определения местоположения, вышек сотовой связи и точек доступа Wi-Fi. Эти службы должны быть включены на устройстве, а приложению должно быть разрешено их использовать." "Изменение настроек аудио" "Приложение сможет изменять системные настройки звука, например уровень громкости и активный динамик." "Запись аудио" "Приложение сможет записывать аудио с помощью микрофона в любое время без уведомления." - "Обращение к SIM-карте" + "Отправка команд SIM-карте" "Приложение сможет отправлять команды SIM-карте (данное разрешение представляет большую угрозу)." "Фото- и видеосъемка" "Приложение сможет снимать фотографии и видеоролики с помощью камеры в любое время без вашего разрешения." @@ -384,7 +384,7 @@ "Приложение сможет получить список всех используемых на устройстве аккаунтов, в том числе созданных установленными приложениями." "Просмотр сетевых подключений" "Приложение сможет просматривать информацию о сетевых подключениях, например о том, какие сети доступны и к каким из них вы подключены." - "Неограниченный доступ в Интернет" + "Неограниченный доступ к Интернету" "Приложение сможет создавать сетевые сокеты и использовать различные сетевые протоколы. Так как браузер и другие приложения обеспечивают средства для отправки данных в Интернет, это разрешение предоставлять не обязательно." "Изменение сетевых настроек" "Приложение сможет изменять состояние подключения к сети." @@ -404,7 +404,7 @@ "Приложение сможет настраивать параметры локального телефона с поддержкой Bluetooth, а также обнаруживать удаленные устройства и выполнять сопряжение с ними." "подключать/отключать сеть WiMAX" "Приложение сможет определять, активирован ли WiMAX, а также получать информацию о подключенных сетях WiMAX." - "Изменение статуса WiMAX" + "Изменение статуса WiMAX" "Приложение сможет подключать устройство к сетям WiMAX и отключать его от них." "Подключение телевизора к сетям WiMAX и его отключение от них." "Приложение сможет подключать устройство к сетям WiMAX и отключать его от них." @@ -487,7 +487,7 @@ "Приложение сможет изменять параметры калибровки сенсорного экрана. Это разрешение обычно используется только специальными приложениями." "Доступ к сертификатам DRM" "Приложение сможет синхронизировать и использовать сертификаты DRM (разрешение актуально только для специальных приложений)." - "Получение статуса передачи Android Beam" + "Получение статуса передачи Android Beam" "Получение информации о текущих передачах Android Beam." "удаление сертификатов DRM" "Удаление сертификатов DRM. Большинству приложений это разрешение не требуется." @@ -1105,11 +1105,11 @@ "Форматирование…" "Отсутствует" "Подходящих действий не найдено." - "Перенаправление мультимедийных данных" + "Перенаправление вывода мультимедиа" "Приложение сможет направлять поток мультимедиа на другие внешние устройства." - "Чтение данных сеансов установки" + "Чтение данных сеансов установки" "Чтение данных текущих сеансов установки пакетов." - "Разрешение на установку пакетов" + "Запрос пакетов установки" "Приложение сможет запрашивать разрешения на установку пакетов." "Нажмите дважды для изменения масштаба" "Не удалось добавить виджет." diff --git a/core/res/res/values-si-rLK-watch/strings.xml b/core/res/res/values-si-rLK-watch/strings.xml index b55687f734262..3df07751fa97b 100644 --- a/core/res/res/values-si-rLK-watch/strings.xml +++ b/core/res/res/values-si-rLK-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d හි %2$d යෙදුම." + "සංවේදක" diff --git a/core/res/res/values-si-rLK/cm_strings.xml b/core/res/res/values-si-rLK/cm_strings.xml new file mode 100644 index 0000000000000..0ceea5e7a997d --- /dev/null +++ b/core/res/res/values-si-rLK/cm_strings.xml @@ -0,0 +1,137 @@ + + + + + + තිර සේයාව + + ආරක්‍ෂිත SMS ලබන්න + + එන ආරක්‍ෂිත SMS ලැබීමට යෙදුමට ඉඩ දෙයි. + + ආරක්‍ෂිත SMS ලැයිස්තුව විකරණය කරන්න + + + ආරක්ෂාව + + උපාංගයේ ආරක්ෂක තොරතුරු වලට අදාළ අනුමැති. + + දුරකථන අපලේඛණය කියවීම + + පැමිණෙන ඇමතුම් හෝ පණිවිඩ සඳහා අවහිර කර ඇති ඇමතුම් අංක පිලිබඳ තොරතුරු කියවීම සඳහා යෙදුමකට අවසර දෙන්න. + + දුරකථන අපලේඛණය වෙනස් කරන්න + + පැමිණෙන ඇමතුම් හෝ පණිවිඩ සඳහා අවහිර කර ඇති ඇමතුම් අංක වෙනස් කිරීම සඳහා යෙදුමකට අවසර දෙන්න. + + යතුරු රැක්මේ වෝල්පේපරය සකසන්න + + අගුළු තිරයේ වෝල්පේපරය වෙනස්කිරීම සඳහා යෙදුමකට අවසර දෙන්න. + + යළි පණගන්වන්න + + + + නැවත පනගන්වන්න + + ප්‍රතිසාධන ප්‍රකාරයට + + ඇරඹුම් ප්‍රවේශකයට + + බාගැනීමේ ප්‍රකාරයට + + මෘදුව නැවත පනගන්වන්න + + + ඔබගේ ටැබ්ලටය නැවත පනගැන්වෙනු ඇත. + ඔබගේ දුරකථනය නැවත පනගැන්වෙනු ඇත. + + නැවත පනගැන්වෙමින්\u2026 + + + ජාලය හරහා ADB සබලයි + + ජාලය & USB හරහා ADB සබලයි + + නිදොස් කරණය අබල කිරීමට ස්පර්ශ කරන්න. + + + + + + + + පෞද්ගලිකත්වයේ මුරකරු සබලනය හෝ අබලනය + තවත් යෙදුමක් පෞද්ගලිකත්වයේ මුරකරු සමග ධාවනය විය යුතුද නැද්ද යන්න වෙනස් කිරීම සඳහා යෙදුමට අවසර දෙන්න. යෙදුමක් පෞද්ගලිකත්වයේ මුරකරු සමග ධාවනය වන විට, එයට සම්බන්ධතා, ඇමතුම් ලොග හෝ පණිවිඩ පරිශීලනය කල නොහැක. + පෞද්ගලිකත්වයේ මුරකරු සක්‍රීයයි + %1$sට පුද්ගලික දත්ත පරිශීලනය කල නොහැක + පෞද්ගලිකත්වයේ මුරකරු + %2$s සඳහා %1$sට අවශ්‍යව ඇත. + + + කැමරාව පරිශීලනය + ඔබගේ ස්ථානය පරිශීලනය + ඔබගේ දැනුම්දීම් කියවීම + ඔබගේ උපාංගය අවදිව තබාගැනීම + දුරකථන ඇමතුමක් ලබාගැනීම + ඔබගේ දින දර්ශකය නවීකරණය + ඇමතුම් ලොගය නවීකරණය + පසුරු පුවරුව වෙනස්කිරීම + ඔබගේ සම්බන්ධතා නවීකරණය + පද්ධති සැකසීම් නවීකරණය + ශ්‍රව්‍ය ධාවනය + දැනුම්දීමක් පල කිරීම + ඔබගේ දින දර්ශකය කියවීම + ඇමතුම් ලොගය කියවීම + පසුරු පුවරුව කියවීම + ඔබගේ සම්බන්ධතා කියවීම + ඔබගේ MMS පනිවිඩ කියවීම + ඔබගේ කෙටි පනිවිඩ කියවීම + කෙටි පනිවිඩයක් බාර ගැනීම + ශ්‍රව්‍ය රෙකෝඩනය + MMS පනිවිඩයක් යැවීම + කෙටි පනිවිඩයක් යැවීම + පණගැන්වීමේදී ධාවනය + බ්ලූටූත් ටොගලනය + NFC ටොගලනය + ඇඟවීම් හඬ පරිමා පාලනය + ශ්‍රව්‍ය කේන්ද්‍රනය පාලනය + බ්ලූටූත් හඬ පරිමා පාලනය + ප්‍රධාන හඬ පරිමා පාලනය + මාධ්‍ය බොත්තම් භාවිතය + මාධ්‍ය හඬ පරිමා පාලනය + දැනුම්දීම් හඬ පරිමා පාලනය + රින්ග්ටෝනයේ ශබ්දය පාලනය + ස්පර්ශක කම්පන ප්‍රතිචාර භාවිතය + හඬ ඇමතුම් ශබ්දය පාලනය + MMS පණිවිඩයක් ලිවීම + කෙටි පණිවිඩයක් ලිවීම + + + + + + + + + + diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml index 76633336e6af3..2da1ecf1fc20f 100644 --- a/core/res/res/values-si-rLK/strings.xml +++ b/core/res/res/values-si-rLK/strings.xml @@ -254,7 +254,7 @@ "ණයවරපත් අංක සහ මුරපද වැනි පුද්ගලික දත්ත ඇතුළත් වේ." "තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න" "තත්ව තීරුව අක්‍රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ." - "තත්ව තීරුව" + "තත්ත්ව තීරුව බවට පත්වීම" "තත්ව තීරුව වීමට යෙදුමට අවසර දෙන්න." "තත්ව තීරුව දිග හැරීම/හැකිලීම" "තත්ව තීරුව දිග හැරීමට හෝ හැකිළීමට යෙදුමට අවසර දෙන්න." @@ -282,7 +282,7 @@ "WAP පණිවිඩ ලැබීමට සහ ක්‍රියාවලි කිරීමට යෙදුමට අවසර දෙන්න. මෙම අවසරයෙහි ඔබව ඒවාට පෙන්වීමකින් තොරව ඔබට පණිවිඩ නිරීක්ෂණයට හෝ මැකීමට හැකියාව ඇතුළත් වේ." "ධාවනය වන යෙදුම් ලබාගැනීම" "දැනට සහ මෑත ක්‍රියාත්මක කාර්යයන් පිළිබඳ විස්තරාත්මක තොරතුරු සොයා ලබාගැනීමට යෙදුමට ඉඩ දෙන්න. මෙය කුමන යෙදුම් උපාංගයේ භාවිතා කරන්නේද යන තොරතුරු යෙදුම්වලට සොයා ගැනීමට ඉඩ දිය හැක." - "පැතිකඩ සහ උපාංග හිමිකරුවන් කළමනාකරණය කරන්න" + "පැතිකඩ සහ උපාංග හිමිකරුවන් කළමනාකරණය කිරීම" "යෙදුම්වලට පැතිකඩ හිමියන් සහ උපාංග හිමිකරු සැකසීමට ඉඩ දෙයි." "ධාවනය වන යෙදුම් නැවත අනුපිළිවෙලට සැකසීම" "පෙරබිමට හෝ පසුබිමට සිදුවීම් ගෙනයාමට යෙදුමට අවසර දෙන්න. ඔබගේ ආදානයකින් තොරව යෙදුම මෙය සිදුකරයි." @@ -324,7 +324,7 @@ "ලැබෙන ඇමතුම් සහ පිටවන ඇමතුම් දත්ත ඇතුළත්ව ඔබගේ ටැබ්ලටයේ ඇමතුම් ලොගය වෙනස් කිරීමට යෙදුමට අවසර දෙන්න. ඔබගේ ඇමතුම් ලොගය මැකීමට හෝ වෙනස් කිරීමට අනිෂ්ට යෙදුම් මෙය භාවිතා කෙරේ." "ලැබෙන ඇමතුම් සහ පිටවන ඇමතුම් දත්ත ඇතුළත්ව ඔබගේ ටැබ්ලටයේ ඇමතුම් ලොගය වෙනස් කිරීමට යෙදුමට අවසර දෙන්න. ඔබගේ ඇමතුම් ලොගය මැකීමට හෝ වෙනස් කිරීමට අනිෂ්ට යෙදුම් මෙය භාවිතා කෙරේ." "පැමිණෙන සහ පිටවෙන ඇමතුම් දත්ත ඇතුළුව ඔබගේ දුරකථනයේ ඇමතුම් ලොගය වෙනස් කිරීමට යෙදුමට අවසර දෙන්න. ඔබගේ ඇමතුම් ලොගය මැකීමට හෝ වෙනස් කිරීමට අනිෂ්ට යෙදුම් මෙය භාවිත කල හැක." - "සිරුර සංවේදකයන් (හෘද ස්පන්දන වේගය නිරීක්ෂණය කිරීම වැනි)" + "දේහ සංවේදකවලට (හෘද ස්පන්දන වේග මොනිටර වැනි) පිවිසීම" "හෘද ස්පන්දන වේගය වැනි ඔබගේ ශාරීරික තත්ත්වය නිරීක්ෂණය කරන සංවේදක වලින් දත්ත ලබාගැනීමට යෙදුමට ඉඩ දෙන්න." "දින දර්ශනයේ සිදුවීම් සහ රහසිගත තොරතුරු කියවීම" "ඔබගේ ටැබ්ලටය තුල ගබඩා කර ඇති මිතුරන්ගේ සහ එක්ව ක්‍රියාකරන්නන්ගේ ද ඇතුළුව සියලුම දින දර්ශන සිද්ධි කියවීමට යෙදුමට අවසර දෙන්න. මෙය රහස්‍යභාවය හෝ සංවේදීතාවය නොසලකා ඔබගේ දින දර්ශන දත්ත බෙදා ගැනීමට හෝ සුරැකීමට යෙදුමට අවසර දෙන්න." @@ -336,15 +336,15 @@ "ඔබගේ යහළුවන් හෝ සමකාලීනයන් ඇතුළත් ඔබගේ දුරකථනයේ ඔබට වෙනස් කළ හැකි සිදු වීම් එකතු කිරීමට, ඉවත් කිරීමට, වෙනස් කිරීමට යෙදුමට අවසර දෙන්න. මෙමගින් දින දර්ශන හිමිකරුවන්ගෙන් පැමිණෙන සේ පෙනෙන පණිවිඩ යැවීමට හෝ හිමිකරුගේ දැනුමකින් තොරව සිදුවීම් වෙනස් කිරීමට යෙදුමට අවසර දෙයි." "අමතර ස්ථාන සැපයුම්කරු විධාන වෙත ප්‍රවේශ වීම" "ස්ථානය සපයන අමතර අණ වලට ප්‍රවේශය කිරීමට යෙදුමට අවසර දෙන්න. GPS ක්‍රියාවන් හෝ වෙනත් ස්ථාන මූලාශ්‍ර සමඟ මැදිහත් වීමට මෙයින් යෙදුමට ඉඩ ලැබේ." - "නිවැරදි ස්ථානය (GPS සහ ජාලය පදනම් කරගත්)" + "නිවැරදි ස්ථානයට (GPS සහ ජාලය පදනම් කරගත්) පිවිසීම" "ගෝලීය ස්ථානීය පද්ධතිය (GPS) හෝ සෙල් කුළුණු සහ Wi-Fi වැනි ජාල ස්ථානීය ප්‍රභව භාවිතයෙන් ඔබගේ නිවැරදි ස්ථානය ලබාගැනීමට යෙදුම අවසර දෙන්න. යෙදුම් වලට ස්ථානීය සේවා භාවිතා කිරීමට ඒවා සක්‍රිය විය යුතු වේ. ඔබව සොයා ගැනීමට යෙදුම් මෙය භාවිතා කරන අතර අමතර බැටරි බලයක්ද පරිභෝජනය කරයි." - "ආසන්නතම ස්ථානය (ජාලය-පාදක වූ)" + "ආසන්නතම ස්ථානයට (ජාලය-පාදක වූ) පිවිසීම" "ඔබගේ දළ ස්ථානය ලබාගැනීමට යෙදුමට අවසර දෙන්න. සන්නේවේදන කුළුණු සහ Wi-Fi ආදී ජාල ස්ථාන මූලාශ්‍ර භාවිත කරන ස්ථාන සේවා විසින් මෙම ස්ථානය ව්‍යුත්පන්න කර ඇත. යෙදුමට භාවිතය සඳහා මෙම ස්ථාන සේවා සක්‍රිය කළ යුතු අතර ඔබගේ උපාංගය සඳහා පැවතිය යුතුය. ඔබ සිටින තැන දළව හඳුනා ගැනීමට යෙදුම් වලට මෙය භාවිත කළ හැකිය." "ඔබගේ ශ්‍රව්‍ය සැකසීම් වෙනස් කරන්න" "ශබ්දය ආදී ගෝලීය ශබ්ද සැකසීම් වෙනස් කිරීමට සහ ප්‍රතිදානය සඳහා භාවිත කරන්නේ කුමන නාදකය දැයි තේරීමට යෙදුමට අවසර දෙන්න." "ශබ්ද පටිගත කරන්න" "මයික්‍රොෆෝනය මඟින් ශබ්ද පටිගත කිරීමට යෙදුමට අවසර දෙන්න. මෙම අවසරය මඟින් යෙදුමට ඕනෑම වේලාවක ඔබගේ අනුදැනුමකින් තොරව ශබ්ද පටිගත කිරීමට ඉඩ ලබා දේ." - "සිම් සන්නිවේදනය" + "SIM වෙත විධාන යැවීම" "SIM වෙත විධාන ගෙන යාමට යෙදුමට අවසර දෙයි. මෙය ඉතා භයානක වේ." "පින්තූර සහ වීඩියෝ ගන්න" "කැමරාවෙන් පින්තූර ගැනීමට සහ වීඩියෝ කිරීමට යෙදුමට අවසර දෙන්න. මෙම අවසරය මඟින් ඔබගේ අනුදැනුමකින් තොරව ඕනෑම වේලාවකදී කැමරාව භාවිතා කිරීමට යෙදුමට අවසර දෙන්න." @@ -382,7 +382,7 @@ "දුරකථනය විසින් දන්නා ගිණුම් ලැයිස්තුවක් ලබාගැනීමට යෙදුමට අවසර දෙන්න. ඔබ ස්ථාපනය කොට ඇති යෙදුම් විසින් සාදා ඇති ගිණුම් මීට ඇතුළත් වේ." "ජාල සම්බන්ධතාවයන් බැලීම" "කුමන ජාල පවතින්නේ ද සහ සම්බන්ධිත ද ආදී ජාල සබඳතා ගැන තොරතුරු බැලීමට යෙදුමට අවසර දෙයි." - "සම්පූර්ණ ජාල ප්‍රවේශය" + "සම්පූර්ණ ජාල ප්‍රවේශය තබා ගැනීම" "උපකරණයට ජාල කෙවනියන් සැදීමට සහ ජාල ප්‍රොටෝකෝල අභිරුචි භාවිතා කිරීමට උපකරණයට ඉඩ දෙන්න. අන්තර්ජාලයට දත්ත යැවීමට විධියන් බ්‍රව්සරය සහ අනෙකුත් යෙදුම් සපයයි, එනිසා මෙම අවසරය දත්ත අන්තර්ජාලයට යැවීමට අවශ්‍ය නොවේ." "ජාල සම්බන්ධතාව වෙනස් කිරීම" "ජාල සම්බන්ධතාවයේ තත්වය වෙනස් කිරීමට යෙදුමට අවසර දෙන්න." @@ -402,7 +402,7 @@ "දුරකථනයේ පෙදෙසි බ්ලූටූත් වින්‍යාස කිරීමට, සහ දුරස්ථ උපාංග ගවේෂණයට සහ යුගල වීමට යෙදුමට අවසර දෙයි." "WiMAX වෙතට සම්බන්ධ කරන්න හෝ විසන්ධි කරන්න" "WiMAX සබල බව සහ සම්බන්ධිත ඕනෑම WiMAX ජාලයක තොරතුරු නිශ්චය කිරීමට යෙදුමට අවසර දෙයි." - "WiMAX තත්වය වෙනස් කරන්න" + "WiMAX තත්වය වෙනස් කිරීම" "ටැබ්ලටය WiMAX ජාල වෙත සම්බන්ධ කිරීමට සහ විසන්ධි කිරීමට යෙදුමට අවසර දෙන්න." "WiMAX ජාල වෙතින් රූපවාහිනිය සම්බන්ධ කරන්න සහ රූපවාහිනිය විසන්ධි කරන්න යෙදුමට ඉඩ දෙන්න." "WiMAX ජාලයන්ට දුරකථනය සම්බන්ධ කිරීමට සහ විසන්ධි කිරීමට යෙදුමට අවසර දෙන්න." @@ -485,7 +485,7 @@ "යෙදුම් වලට ස්පර්ශ තිරයේ ක්‍රමාංකන පරාමිති වෙනස් කිරීමට ඉඩ දේ. සාමාන්‍ය යෙදුම් වලට කිසිදා අවශ්‍ය නොවේ." "DRM සහතික ප්‍රවේශය" "යෙදුමකට DRM සහතික වෙන් කර භාවිතා කිරීමට ඉඩ දේ. සාමාන්‍ය යෙදුම් වලට කිසිදා අවශ්‍ය නොවේ." - "Android බීම් හුවමාරු තත්ත්වය ලබාගන්න" + "Android කදම්බ හුවමාරු තත්ත්වය ලබා ගැනීම" "දැනට තිබෙන Android බීම් හුවමාරු පිළිබඳ තොරතුරු ලබාගැනීමට මෙම යෙදුමට ඉඩ දෙන්න" "DRM සහතික ඉවත් කරන්න" "යෙදුමකට DRM සහතික ඉවත් කිරීමට ඉඩ දේ. සාමාන්‍ය යෙදුම් වලට කිසිදා අවශ්‍ය නොවේ." @@ -1093,11 +1093,11 @@ "ෆෝමැට් කරමින්…" "ඇතුළු කර නැත" "ගැලපෙන ක්‍රියාකාරකම් හමු නොවුණි." - "මාධ්‍ය ප්‍රතිදානයේ මාර්ගගත කිරීම" + "මාධ්‍ය ප්‍රතිදානය මාර්ගගත කිරීම" "වෙනත් බාහිර උපාංග වෙත මාධ්‍ය ප්‍රතිදානය යැවීමට යෙදුමට අවසර දෙන්න." - "ස්ථාපන සැසියන් කියවන්න" + "ස්ථාපන සැසි කියවීම" "ස්ථාපන සැසිය කියවීමට යෙදුමට ඉඩ දෙන්න. සක්‍රිය පැකේජ ස්ථාපනය පිළිබඳ විස්තර බැලීමට එයට මෙයින් ඉඩ දෙයි." - "ස්ථාපන පැකේජ ඉල්ලීම" + "ස්ථාපන පැකේජ ඉල්ලීම" "ස්ථාපන පැකේජ ඉල්ලීමට යෙදුමකට අවසර දීම." "විශාලන පාලනය සඳහා දෙවරක් ස්පර්ශ කරන්න" "විජටය එකතු කිරීමට නොහැකි විය." diff --git a/core/res/res/values-sk-watch/strings.xml b/core/res/res/values-sk-watch/strings.xml index 601c016ee4f1d..ec12e4b5895d4 100644 --- a/core/res/res/values-sk-watch/strings.xml +++ b/core/res/res/values-sk-watch/strings.xml @@ -21,4 +21,5 @@ "Aplikácia %1$d z %2$d." + "Senzory" diff --git a/core/res/res/values-sk/cm_strings.xml b/core/res/res/values-sk/cm_strings.xml new file mode 100644 index 0000000000000..fd847e2974842 --- /dev/null +++ b/core/res/res/values-sk/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Snímka obrazovky + + prijímať chránené SMS + + Umožňuje aplikácii prijímať chránené prichádzajúce SMS. + + upraviť zoznam chránených SMS + + Umožňuje aplikácii upraviť zoznam chránených SMS adries. + + Zabezpečenie + + Povolenia súvisiace s informáciami o bezpečnosti zariadenia. + + čítať čiernu listinu telefónu + + Umožňuje aplikácii čítať informácie o telefónnych číslach, ktoré sú pre prichádzajúce hovory a správy zablokované. + + zmeniť čiernu listinu telefónu + + Umožňuje aplikácii zmeniť telefónne čísla, ktoré sú pre prichádzajúce hovory a správy zablokované. + + nastaviť tapetu obrazovky uzamknutia + + Umožňuje aplikácii zmeniť tapetu obrazovky uzamknutia. + + Reštartovať + + Aktuálny + + + Reštartovať + + Recovery + + Bootloader + + Download + + Softvérový reštart + + Reštartovať + + Váš tablet bude reštartovaný. + Váš telefón bude reštartovaný. + + Reštartuje sa\u2026 + + Aplikácia bola ukončená + + ADB cez sieť povolené + + ADB cez USB a sieť povolené + + Dotykom zakážate ladenie. + + ADB - %1$s + USB a sieť + USB + Sieť + + zachytiť spustenie aplikácie + + Aplikácia %s nie je nainštalovaná + + Priorita + Žiadna + + Wi-Fi hotspot bol zakázaný kvôli prepnutiu karty SIM + + Vypnúť Wi-Fi + + povoliť alebo zakázať Ochranu súkromia + Umožňuje aplikácii určiť, či má byť iná aplikácia spustená s Ochranou súkromia. Keď je aplikácia spustená s Ochranou súkromia, nemá umožnený prístup k osobným údajom ako sú kontakty, denníky hovorov, alebo správy. + Aktívna ochrana súkromia + Aplikácii %1$s nebude umožnený prístup k osobným údajom + Ochrana súkromia + Aplikácia %1$s sa pokúša %2$s. + + Zapamätať voľbu + + prístup k fotoparátu + prístup k polohe + čítať oznámenia + aktivovať VPN + spustiť pri štarte + vymazať denník hovorov + vymazať kontakty + vymazať MMS správy + vymazať SMS správy + vykresliť okná navrchu + získať štatistiky používania aplikácií + ponechať zariadenie prebudené + uskutočniť telefonický hovor + aktualizovať kalendár + aktualizovať denník hovorov + upraviť schránku + aktualizovať kontakty + aktualizovať systémové nastavenia + stlmiť/zrušiť stlmenie mikrofónu + prehrať zvuk + odoslať oznámenie + premietať médiá + čítať údaje z kalendára + čítať údaje z denníka hovorov + čítať údaje zo schránky + čítať kontakty + čítať správy MMS + čítať správy SMS + prijímať správy SMS + nahrať zvuk + odoslať správu MMS + odoslať správu SMS + spustiť pri štaťte + zobraziť vyskakovacie oznámenia + prepnúť bluetooth + prepnúť mobilné dáta + prepnúť NFC + prepnúť Wi-Fi + ovládať hlasitosť budíka + ovládať zvukové zdroje + ovládať hlasitosť bluetooh + ovládať hlavnú hlasitosť + používať tlačidlá médií + ovládať hlasitosť médií + ovládať hlasitosť oznámení + ovládať hlasitosť zvonenia + používať dotykovú odozvu + ovládať hlasitosť hovoru + napísať správu MMS + napísať správu SMS + použiť odtlačok prsta + pridať hlasovú poštu + pristupovať k stavu telefónu + prehľadať Wi-Fi siete + zmeniť tapetu + použiť asistovanú štruktúru + urobiť snímok obrazovky + použiť telové senzory + čítať bunkové vysielanie + falšovať vašu polohu + čítať externé úložisko + zapisovať do externého úložiska + zapnúť obrazovku + získať účty zariadenia + zmeniť stav Wi-Fi + získať root prístup + + Na odopnutie tejto obrazovky stlačte a podržte tlačidlo Späť. + + Žiadne pripojené zariadenie + %1$s pripojené zariadenie + Pripojené zariadenia: %1$s + + + + Spustenie aktivity zablokované + %1$s je chránená proti spusteniu. Kliknite na overenie a spustenie aplikácie. + + Batéria plne nabitá + Odpojte zariadenie od nabíjačky pre zlepšenie životnosti batérie. + + obnoviť štatistiky batérie + + Umožňuje aplikácii obnoviť aktuálne nízkoúrovňové údaje o využití batérie. + + SIM karty sa zmenili + Kliknite na nastavenie redvolieb SIM karty + diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 933c3fe5c6549..b2d435cfd1409 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -256,7 +256,7 @@ "Sledovanie zahŕňa osobné údaje ako sú čísla kreditných kariet a heslá." "zakázanie alebo zmeny stavového riadka" "Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony." - "stavový riadok" + "vydávanie sa za stavový riadok" "Umožňuje aplikácii fungovať ako stavový riadok." "rozbalenie a zbalenie stavového riadka" "Umožňuje aplikácii rozbaliť alebo zbaliť stavový riadok." @@ -284,7 +284,7 @@ "Umožňuje aplikácii prijímať a spracovávať správy WAP. Toto povolenie zahŕňa možnosť sledovať vaše správy alebo ich odstrániť bez toho, aby sa vám zobrazili." "načítať spustené aplikácie" "Umožňuje aplikácii načítať informácie o aktuálne či nedávno spustených úlohách. Toto povolenie môže aplikácii umožniť objaviť informácie o tom, ktoré aplikácie sa na zariadení používajú." - "Správa vlastníkov profilov a zariadenia" + "správa vlastníkov profilov a zariadení" "Povolí aplikáciám nastaviť vlastníkov profilov a vlastníka zariadenia." "zmeniť poradie spustených aplikácií" "Umožňuje aplikácii presunúť úlohy do popredia alebo do pozadia. Aplikácia tak môže urobiť bez vášho zásahu." @@ -326,7 +326,7 @@ "Umožňuje aplikácii upravovať denník hovorov vo vašom tablete vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov." "Umožňuje aplikácii upravovať denník hovorov vo vašom televízore vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov." "Umožňuje aplikácii upravovať denník hovorov vo vašom telefóne vrátane údajov o prichádzajúcich a odchádzajúcich hovoroch. Škodlivé aplikácie to môžu zneužiť na vymazanie alebo úpravu vášho denníka hovorov." - "telesné senzory (napr. snímače tepu)" + "prístup k telesným senzorom (ako sú snímače tepu)" "Umožňuje aplikácii získať prístup k údajom senzorov monitorujúcich vašu fyzickú kondíciu (napríklad pulz)." "čítať udalosti v kalendári a dôverné informácie" "Umožňuje aplikácii čítať všetky udalosti kalendára uložené v tablete vrátane udalostí priateľov alebo spolupracovníkov. Aplikácii to umožní zdieľať alebo ukladať údaje kalendára bez ohľadu na dôvernosť či citlivosť týchto údajov." @@ -338,15 +338,15 @@ "Umožňuje aplikácii pridávať, odstraňovať alebo meniť udalosti, ktoré môžete v telefóne upravovať, a to vrátane udalostí priateľov a spolupracovníkov. Toto povolenie umožňuje aplikácii odosielať správy, ktoré budú zdanlivo prichádzať od vlastníkov kalendára, alebo upravovať udalosti bez vedomia vlastníkov." "prístup k ďalším príkazom poskytovateľa polohy" "Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe." - "zistiť presnú polohu (pomocou GPS a siete)" + "prístup k presnej polohe (pomocou GPS a siete)" "Umožňuje aplikácii získať vašu presnú polohu pomocou systému GPS (Global Positioning System) alebo zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby určovania polohy musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej polohy. Tieto služby môžu zvýšiť spotrebu batérie." - "zistiť približnú polohu (pomocou siete)" + "prístup k približnej polohe (pomocou siete)" "Umožňuje aplikácii získať vašu približnú polohu. Táto poloha je odvodená zo služieb určovania polohy pomocou zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby určovania polohy musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej približnej polohy." "meniť nastavenia zvuku" "Umožňuje aplikácii upraviť globálne nastavenia zvuku, ako je hlasitosť, alebo určiť, z ktorého reproduktora bude zvuk vychádzať." "nahrávať zvuk" "Umožňuje aplikácii zaznamenávať zvuk pomocou mikrofónu. Toto povolenie umožňuje aplikácii zaznamenávať zvuk kedykoľvek bez vášho potvrdenia." - "komunikácia so SIM kartou" + "posielanie príkazov do SIM karty" "Umožňuje aplikácii odosielať príkazy na SIM kartu. Toto je veľmi nebezpečné povolenie." "fotiť a nakrúcať videá" "Umožňuje aplikácii fotografovať a nahrávať videá pomocou fotoaparátu. Toto povolenie umožňuje aplikácii používať fotoaparát kedykoľvek a bez vášho potvrdenia." @@ -384,7 +384,7 @@ "Umožňuje aplikácii získať zoznam účtov v telefóne. Môžu sem patriť akékoľvek účty vytvorené aplikáciami, ktoré ste nainštalovali." "zobraziť sieťové pripojenia" "Umožňuje aplikácii zobraziť informácie o sieťových pripojeniach, ako napríklad o tom, ktoré siete sú k dispozícii a ktoré sú pripojené." - "plný prístup k sieti" + "úplný prístup k sieti" "Umožňuje aplikácii vytvárať sokety siete a používať vlastné protokoly siete. Toto povolenie sa pri odosielaní údajov na internet nevyžaduje, pretože prostriedky na odosielanie údajov na internet poskytujú prehliadač a iné aplikácie." "zmena sieťového pripojenia" "Umožňuje aplikácii zmeniť stav sieťového pripojenia zdieľaného pomocou tetheringu." @@ -404,7 +404,7 @@ "Umožňuje aplikácii konfigurovať miestny telefón s rozhraním Bluetooth, vyhľadávať a spárovať vzdialené zariadenia." "pripojiť a odpojiť od WiMAX" "Umožňuje aplikácii určiť, či je povolený štandard WiMAX, a tiež informácie o všetkých pripojených sieťach WiMAX." - "Meniť stav pripojenia WiMAX" + "zmeniť stav WiMAX" "Umožňuje aplikácii pripojiť tablet k sieťam WiMAX a odpojiť ho od nich." "Umožňuje aplikácii pripojiť televízor k sieťam WiMAX a odpojiť ho z nich." "Umožňuje aplikácii pripojiť telefón k sieťam WiMAX a odpojiť ho od nich." @@ -487,7 +487,7 @@ "Umožňuje aplikácii upraviť parametre kalibrácie dotykovej obrazovky. Bežné aplikácie by toto povolenie nemali nikdy potrebovať." "prístup k certifikátom DRM" "Umožňuje aplikácii vydávať a používať certifikáty DRM. Bežné aplikácie by toto povolenie nemali nikdy potrebovať." - "Prijímať stav prenosu funkcie Android Beam" + "príjem stavu prenosov Android Beam" "Povoľuje tejto aplikácii prijímať informácie o aktuálnych prenosoch funkcie Android Beam" "odstránenie certifikátov DRM" "Umožňuje aplikácii odstraňovať certifikáty DRM. Bežné aplikácie by toto povolenie nemali nikdy potrebovať." @@ -1105,11 +1105,11 @@ "Prebieha formátovanie..." "Nie je zapojené" "Nenašli sa žiadne zodpovedajúce aktivity." - "Smerovanie výstupu médií" + "smerovanie výstupu médií" "Umožňuje aplikácii smerovať výstup médií do ďalších externých zariadení." - "Čítať relácie inštalácií" + "čítanie inštalačných relácií" "Toto povolenie umožňuje aplikácii čítať relácie inštalácií a zobraziť tak podrobnosti o aktívnych inštaláciách balíkov." - "Vyžiadať inštaláciu balíkov" + "odosielanie žiadostí o inštaláciu balíkov" "Umožňuje aplikácii vyžiadať inštaláciu balíkov." "Ovládacie prvky lupy zobrazíte dvojitým dotknutím" "Miniaplikáciu sa nepodarilo pridať." diff --git a/core/res/res/values-sl-watch/strings.xml b/core/res/res/values-sl-watch/strings.xml index bf1190f34bcf8..42c6c1a312fb9 100644 --- a/core/res/res/values-sl-watch/strings.xml +++ b/core/res/res/values-sl-watch/strings.xml @@ -21,4 +21,5 @@ "%1$d. aplikac. od %2$d." + "Tipala" diff --git a/core/res/res/values-sl/cm_strings.xml b/core/res/res/values-sl/cm_strings.xml new file mode 100644 index 0000000000000..75cb7c026a5dc --- /dev/null +++ b/core/res/res/values-sl/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Zaslonska slika + + prejemanje zaščitenih SMS-ov + + Dovoli aplikaciji prejemanje zaščitenih dohodnih SMS-ov. + + spreminjanje seznama zaščitenih SMS-ov + + Dovoli aplikaciji spreminjanje seznama naslovov zaščitenih SMS-ov. + + Varnost + + Dovoljenja, ki so povezana z varnostnimi podatki naprave. + + branje črnega seznama telefona + + Dovoli aplikaciji branje podatkov o blokiranih telefonskih številkah za dohodne klice in sporočila. + + spreminjanje črnega seznama telefona + + Dovoli aplikaciji spreminjanje blokiranih telefonskih številk za dohodne klice in sporočila. + + nastavitev slike ozadja keyguard + + Dovoli aplikaciji spreminjanje slike ozadja zaklenjenega zaslona. + + Ponovno zaženi + + Trenutni + + + Ponovno zaženi + + Obnovitev + + Zagonski nalagalnik + + Prenos + + Mehki ponovni zagon + + Ponovno zaženi + + Tablica se bo ponovno zagnala. + Telefon se bo ponovno zagnal. + + Ponovno zaganjanje \u2026 + + Aplikacija uničena + + ADB preko omrežja omogočen + + ADB preko USB-ja in omrežja omogočen + + Dotaknite se, da onemogočite razhroščevanje. + + ADB - %1$s + USB in omrežje + USB + Omrežje + + prestrezanje zagona aplikacije + + %s ni nameščen + + Prednost + Brez + + Dostopna točka Wi-Fi je bila onemogočena zaradi spremembe naročnine SIM + + Izklopi Wi-Fi + + omogočanje ali onemogočanje Privacy Guarda + Dovoli aplikaciji spreminjanje, ali se druga aplikacija izvaja s Privacy Guardom. Kadar se aplikacija izvaja s Privacy Guardom, ne bo imela dostopa do osebnih podatkov, kot so stiki, dnevniki klicev ali sporočila. + Privacy Guard dejaven + %1$s ne bo imel dostopa do osebnih podatkov + Privacy Guard + %1$s bi rad %2$s. + + Zapomni si mojo izbiro + + dostop do fotoaparata + dostop do lokacije + branje obvestil + omogočanje VPN-a + zagon ob vklopu + brisanje vašega dnevnika klicev + brisanje vaših stikov + brisanje vaših sporočil MMS + brisanje vaših sporočil SMS + risanje oken v ospredju + pridobivanje uporabniške statistike aplikacije + ohranjanje budnosti naprave + opravljanje klicev + posodabljanje koledarja + posodabljanje dnevnika klicev + spreminjanje odložišča + posodabljanje vaših stikov + posodabljanje sistemskih nastavitev + utišanje/vklop mikrofona + predvajanje zvoka + prikaz obvestil + načrtovanje predstavnosti + branje koledarja + branje dnevnika klicev + branje odložišča + branje vaših stikov + branje vaših sporočil MMS + branje vaših sporočil SMS + prejemanje sporočil SMS + snemanje zvoka + pošiljanje sporočil MMS + pošiljanje sporočil SMS + zagon ob vklopu + prikazovanje pojavnih obvestil + preklapljanje Bluetootha + preklapljanje mobilnih podatkov + preklapljanje NFC-ja + preklapljanje omr. Wi-Fi + nadzor glasnosti budilke + nadzor žarišča zvoka + nadzor glasnosti Bluetooth + nadzor glavne glasnost + uporaba gumbov za predstavnost + nadzor glasnosti predstavnosti + nadzor glasnosti obvestil + nadzor glasnosti zvonjenja + uporaba haptičnega zaznavanja + nadzor glasnosti klicev + sestavljanje sporočil MMS + sestavljanje sporočil SMS + uporaba prstnih odtisov + dodajanje glasovne pošte + dostop do stanja telefona + preiskovanje omrežij Wi-Fi + spreminjanje slike ozadja + uporaba zgradbe za pomoč + zajemanje zaslonskih slik + uporaba tipal naprave + branje signala oddajnikov + prikazovanje lažne lokacije + branje zunanje pomnilniške naprave + pisanje zunanje pomnilniške naprave + vklapljanje zaslona + pridobivanje računov naprave + spreminjanje stanja Wi-Fi + pridobitev skrbniškega dostopa + + Da odpnete ta zaslon, se dotaknite in pridržite gumb Nazaj. + + Nobene naprave ni povezane + %1$s povezana naprava + %1$s povezanih naprav + + + + Zagon dejavnosti blokiran + %1$s je zaščiten pred zagonom. Kliknite za overitev in zaženite aplikacijo. + + Baterija napolnjena + Odklopite napravo iz polnilca za izboljšanje življenjske dobe baterije. + + ponastavitev statistike baterije + + Dovoli aplikaciji ponastavitev trenutnih podatkov uporabe baterije ob nizkem stanju. + + Kartice SIM so se spremenile + Tapnite, da nastavite privzete možnosti kartice SIM + diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 304fe52d876e5..f5b1617a908e8 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -256,7 +256,7 @@ "Vključuje osebne podatke, kot so številke kreditnih kartic in gesla." "onemogočanje ali spreminjanje vrstice stanja" "Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema." - "vrstica stanja" + "postane vrstica stanja" "Aplikaciji omogoča, da postane vrstica stanja." "razširjanje/strnjevanje vrstice stanja" "Aplikaciji omogoča razširjanje ali strnjevanje vrstice stanja." @@ -284,7 +284,7 @@ "Aplikaciji omogoča prejemanje in obdelavo sporočil WAP. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala." "dobivanje aplikacij, ki se izvajajo" "Aplikaciji omogoča prejemanje podatkov o trenutnih in nedavno izvajajočih se opravilih. S tem lahko aplikacija odkrije podatke o aplikacijah, ki se uporabljajo v napravi." - "Upravljanje lastnikov profilov in lastnika naprave." + "upravljanje lastnikov profilov in lastnikov naprave" "Dovolite aplikacijam, da nastavijo lastnike profilov in lastnika naprave." "preurejanje aplikacij, ki se izvajajo" "Aplikaciji omogoča premikanje opravil v ospredje in ozadje. Aplikacija lahko to naredi brez vašega nadzora." @@ -326,7 +326,7 @@ "Aplikaciji dovoli spreminjanje dnevnika klicev v tabličnem računalniku, vključno s podatki o dohodnih in odhodnih klicih. Zlonamerne aplikacije lahko tako izbrišejo ali spreminjajo vaš dnevnik klicev." "Aplikaciji dovoljuje spreminjanje dnevnika klicev v televizorju, vključno s podatki o dohodnih in odhodnih klicih. Zlonamerne aplikacije lahko tako izbrišejo ali spreminjajo vaš dnevnik klicev." "Aplikaciji dovoli spreminjanje dnevnika klicev v telefonu, vključno s podatki o dohodnih in odhodnih klicih. Zlonamerne aplikacije lahko tako izbrišejo ali spreminjajo vaš dnevnik klicev." - "tipala telesnih funkcij (npr. merilniki srčnega utripa)" + "dostop do tipal telesnih funkcij (npr. merilnikov srčnega utripa)" "Aplikaciji omogoča dostop do podatkov tipal, ki nadzirajo vaše fizično stanje, med drugim vaš srčni utrip." "branje dogodkov v koledarju in zaupnih podatkov" "Aplikaciji omogoča branje vseh dogodkov v koledarju, ki so shranjeni v tabličnem računalniku, vključno z dogodki prijateljev in sodelavcev. S tem lahko aplikacija objavi ali shrani podatke v koledarju, ne glede na njihovo zaupnost ali občutljivost." @@ -338,15 +338,15 @@ "Aplikaciji omogoča dodajanje, odstranjevanje in spreminjanje dogodkov, ki jih je mogoče spreminjati v telefonu, vključno z dogodki prijateljev in sodelavcev. S tem lahko aplikacija pošilja sporočila, za katera je videti, da jih pošiljajo lastniki koledarjev, ali spreminjajo dogodke brez vednosti lastnikov." "dostopanje do ukazov ponudnika dodatnih lokacij" "Aplikaciji omogoča dostop do dodatnih ukazov ponudnika lokacij. S tem lahko aplikacija moti delovanje sistema GPS ali drugih virov lokacije." - "natančna lokacija (na podlagi podatkov GPS in omrežja)" + "dostop do natančne lokacije (na podlagi podatkov GPS in omrežja)" "Aplikaciji omogoča, da določi vašo natančno lokacijo na podlagi sistema GPS ali omrežnih lokacijskih virov, kot so bazne postaje mobilne telefonije ali Wi-Fi. Te lokacijske storitve morajo biti vklopljene in na voljo v napravi, če želite, da jih aplikacija uporablja. Aplikacije lahko na podlagi tega določijo vašo lokacijo in še dodatno izpraznijo akumulator." - "približna lokacija (na podlagi omrežja)" + "dostop do približne lokacije (na podlagi podatkov omrežja)" "Aplikaciji omogoča, da določi vašo približno lokacijo na podlagi lokacijskih storitev z omrežnimi lokacijskimi viri, kot so bazne postaje mobilne telefonije in Wi-Fi. Te lokacijske storitve morajo biti vklopljene in na voljo v napravi, če želite, da jih aplikacija uporablja. Aplikacije lahko na podlagi tega določijo vašo približno lokacijo." "spreminjanje nastavitev zvoka" "Aplikaciji omogoča spreminjanje splošnih zvočnih nastavitev, na primer glasnost in kateri zvočnik se uporablja." "snemanje zvoka" "Aplikaciji omogoča snemanje zvoka z mikrofonom. S tem dovoljenjem lahko aplikacija kadar koli snema zvok brez vaše potrditve." - "komuniciranje s kartico SIM" + "pošiljanje ukazov na kartico SIM" "Aplikaciji dovoli pošiljanje ukazov kartici SIM. To je lahko zelo nevarno." "fotografiranje in snemanje videoposnetkov" "Aplikaciji omogoča fotografiranje in snemanje videoposnetkov s kamero. S tem dovoljenjem lahko aplikacija kadar koli uporablja kamero brez vaše potrditve." @@ -384,7 +384,7 @@ "Aplikaciji omogoča prejemanje seznama računov, ki jih pozna telefon.To lahko vključuje račune, ki so jih ustvarile nameščene aplikacije." "prikaz omrežnih povezav" "Aplikaciji omogoča ogled podatkov o omrežnih povezavah, na primer o obstoječih in povezanih omrežjih." - "poln dostop do omrežja" + "poln dostop do omrežja" "Aplikaciji omogoča ustvarjanje vtičnic omrežja in uporabo omrežnih protokolov po meri. Brskalnik in druge aplikacije omogočajo pošiljanje podatkov v internet, zato to dovoljenje ni potrebno za pošiljanje podatkov v internet." "spreminjanje povezljivosti omrežja" "Aplikaciji omogoča spreminjanje stanja povezljivosti omrežja." @@ -404,7 +404,7 @@ "Aplikaciji omogoča konfiguriranje lokalnega telefona s tehnologijo Bluetooth ter odkrivanje oddaljenih naprav in povezovanje z njimi." "vzpostavitev povezave z omrežjem WiMax in prekinitev povezave z njim" "Aplikaciji omogoča, da ugotovi, ali je WiMAX omogočen, in ogled podatkov o povezanih omrežjih WiMAX." - "Sprememba stanja omrežja WiMAX" + "sprememba stanja omrežja WiMAX" "Aplikaciji omogoča, da vzpostavi povezavo med tabličnim računalnikom in omrežjem WiMAX ter jo prekine." "Aplikaciji dovoljuje, da televizor poveže v omrežja WiMAX in prekine povezavo televizorja s temi omrežji." "Aplikaciji omogoča, da vzpostavi povezavo med telefonom in omrežjem WiMAX ter jo prekine." @@ -487,7 +487,7 @@ "Aplikaciji dovoli spreminjanje parametrov za umerjanje zaslona na dotik. Tega ni treba nikoli uporabiti za navadne aplikacije." "dostop do potrdil za upravljanje digitalnih pravic" "Aplikaciji omogoča pripravo in uporabo potrdil za upravljanje digitalnih pravic. To naj ne bi bilo nikoli potrebno za običajne aplikacije." - "Prejemanje stanja prenosov s funkcijo Android Beam" + "prejemanje stanja prenosov s funkcijo Android Beam" "Omogoči tej aplikaciji prejemanje podatkov o trenutnih prenosih s funkcijo Android Beam" "odstranjevanje potrdil za upravljanje digitalnih pravic" "Aplikaciji omogoča odstranjevanje potrdil za upravljanje digitalnih pravic. Tega ni treba nikoli uporabiti za navadne aplikacije." @@ -1105,11 +1105,11 @@ "Formatiranje ..." "Ni vstavljeno" "Ni ustreznih dejavnosti." - "Preusmeritev predstavnosti" + "preusmeritev predstavnosti" "Aplikaciji omogoča preusmerjanje predstavnosti v druge zunanje naprave." - "Branje sej namestitev" + "branje sej namestitev" "Aplikaciji omogoča branje sej namestitev. Tako lahko bere podrobnosti o aktivnih namestitvah paketov." - "Zahtevanje paketov za namestitev" + "zahtevanje paketov za namestitev" "Aplikaciji omogoča zahtevanje namestitve paketov." "Dvakrat se dotaknite za nadzor povečave/pomanjšave" "Pripomočka ni bilo mogoče dodati." diff --git a/core/res/res/values-sq-rAL-watch/strings.xml b/core/res/res/values-sq-rAL-watch/strings.xml index d1637ba4e2377..673a7c9090a6f 100644 --- a/core/res/res/values-sq-rAL-watch/strings.xml +++ b/core/res/res/values-sq-rAL-watch/strings.xml @@ -21,4 +21,5 @@ "Aplikacioni %1$d nga %2$d." + "Sensorët" diff --git a/core/res/res/values-sq-rAL/cm_strings.xml b/core/res/res/values-sq-rAL/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-sq-rAL/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml index 3d11d24100655..2ab15e1cb4a00 100644 --- a/core/res/res/values-sq-rAL/strings.xml +++ b/core/res/res/values-sq-rAL/strings.xml @@ -254,7 +254,7 @@ "Përfshi të dhënat personale si numrat e kartave të kreditit si dhe fjalëkalimet." "çaktivizo ose modifiko shiritin e statusit" "Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit." - "shiriti i statusit" + "të bëhet shiriti i statusit" "Lejon aplikacionin të bëhet shiriti i statusit." "zgjero ose shpalos shiritin e statusit" "Lejon aplikacionin të zgjerojë ose shpalosë shiritin e statusit." @@ -282,7 +282,7 @@ "Lejon aplikacionin të marrë dhe përpunojë mesazhe WAP. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato." "gjej aplikacionet në punë" "Lejon aplikacionin të gjejë informacione mbi detyrat aktuale dhe të fundit në punë. Kjo mund të lejojë aplikacionin të zbulojë informacione rreth aplikacioneve të përdorura në pajisje." - "Menaxho pronarët e profilit dhe të pajisjes" + "menaxho zotëruesit e profilit dhe të pajisjes" "Lejo aplikacionet që të caktojnë pronarët e profilit dhe pronarin e pajisjes" "ri-poziciono aplikacionet në punë" "Lejon aplikacionin të zhvendosë detyra në plan të parë dhe në sfond. Aplikacioni mund ta bëjë këtë pa hyrjen tënde." @@ -324,7 +324,7 @@ "Lejon aplikacionin të modifikojë ditarin e telefonatave të tabletit tënd, përfshirë të dhëna rreth telefonatave hyrëse dhe dalëse. Aplikacione keqdashëse mund ta përdorin këtë leje për të fshirë ose modifikuar ditarin tënd të telefonatave." "Lejon aplikacionin të modifikojë ditarin e telefonatave të televizorit tënd, përfshirë të dhëna rreth telefonatave hyrëse dhe dalëse. Aplikacione keqdashëse mund ta përdorin këtë leje për të fshirë ose modifikuar ditarin tënd të telefonatave." "Lejon aplikacionin të modifikojë ditarin e telefonatave të telefonit tënd, përfshirë të dhënat rreth telefonatave hyrëse dhe dalëse. Aplikacionet keqdashëse mund ta përdorin këtë për të fshirë ose modifikuar ditarin tënd të telefonatave." - "ndjesorët e trupit (si monitorimet e rrahjeve të zemrës)" + "qasu te sensorët e trupit (si monitorimet e rrahjeve të zemrës)" "Lejon aplikacionin të ketë qasje në të dhënat nga ndjesorë që monitorojnë gjendjen tënde fizike, siç janë rrahjet e zemrës." "lexo ngjarjet kalendarike si dhe informacionin e privatësisë së tyre" "Lejon aplikacionin të lexojë të gjitha ngjarjet kalendarike të ruajtura në tabletin tënd, përfshirë ato të miqve ose kolegëve. Kjo mund ta lejojë aplikacionin të ndajë ose ruajë të dhënat e tua të kalendarit, pavarësisht privatësisë ose ndjeshmërisë së tyre." @@ -336,15 +336,15 @@ "Lejon aplikacionin të shtojë, heqë, ndryshojë ngjarje që mund t\'i modifikosh në telefonin tënd, përfshi ato të miqve ose kolegëve. Kjo mund ta lejojë aplikacionin të dërgojë mesazhe që duken se vijnë nga zotëruesit e kalendarëve, ose të modifikojë ngjarje pa dijeninë e zotëruesve." "qasje në komandat shtesë të ofruesit të vendndodhjes" "Lejon aplikacionin të ketë qasje në komandat shtesë të ofruesit për vendndodhjen. Kjo mund ta lejojë aplikacionin të ndërhyjë në operacionin e GPS-së apo të burimeve të tjera për vendndodhjen." - "vendndodhja e përpiktë (në bazë të GPS-së dhe rrjetit)" + "qasu te vendndodhja e përpiktë (në bazë të GPS-së dhe rrjetit)" "Lejon aplikacionin të gjejë vendndodhjen tënde të saktë duke përdorur \"Sistemin global të pozicionimit\" (GPS) ose burime të vendndodhjes së rrjetit sikurse antena të operatorëve celularë apo lidhje Wi-Fi. Këto shërbime vendndodhjeje duhet të aktivizohen dhe të ofrohen për pajisjen tënde, në mënyrë që të përdoren nga aplikacioni. Aplikacionet mund ta përdorin këtë për të përcaktuar vendndodhjen momentale, edhe pse ky funksion mund të kërkojë energji shtesë të baterisë." - "vendndodhja e përafërt (bazuar në rrjet)" + "qasu te vendndodhja e përafërt (bazuar në rrjet)" "Lejon aplikacionin të gjejë vendndodhjen tënde të përafërt. Përcaktimi i saj rrjedh nga shërbimet që përdorin burimet e vendndodhjes së rrjetit siç janë antenat e operatorëve celularë apo lidhje Wi-Fi. Këto shërbime vendndodhjeje duhet të aktivizohen dhe të ofrohen për pajisjen tënde, në mënyrë që të përdoren nga aplikacioni. Aplikacionet mund ta përdorin këtë për të përcaktuar afërsisht se ku ndodhesh." "ndrysho cilësimet e audios" "Lejon aplikacionin të modifikojë cilësimet globale të audios siç është volumi dhe se cili altoparlant përdoret për daljen." "regjistro audio" "Lejon aplikacionin të regjistrojë klipe audio me mikrofon. Kjo leje i mundëson aplikacionit të regjistrojë në çdo kohë pa konfirmimin tënd." - "komunikimi i kartës SIM" + "dërgo komanda te karta SIM" "Lejon aplikacionin t\'i dërgojë komanda kartës SIM. Kjo është shumë e rrezikshme." "bëj fotografi dhe video" "Lejon aplikacion të krijojë fotografi dhe video me kamerën. Kjo leje mundëson përdorimin e kamerës në çdo kohë pa konfirmimin tënd." @@ -382,7 +382,7 @@ "Lejon aplikacionin të marrë listën e llogarive të njohura nga telefoni. Kjo mund të përfshijë çdo llogari të krijuar nga aplikacionet që ke instaluar." "shiko lidhjet e rrjetit" "Lejon aplikacionin të shohë informacionin rreth lidhjeve të rrjetit, se çfarë rrjetesh ekzistojnë dhe janë të lidhur." - "qasje e plotë në rrjet" + "qasu plotësisht në rrjet" "Lejon aplikacionin të krijojë fole rrjeti dhe të përdorë protokolle të personalizuara në të. Shfletuesi dhe aplikacionet e tjera sigurojnë mënyra për të dërguar të dhëna në internet, prandaj kjo leje nuk kërkohet për të dërguar të dhëna në internet." "ndrysho lidhjen e rrjetit" "Lejon aplikacionin të ndryshojë gjendjen e lidhjes së rrjetit." @@ -402,7 +402,7 @@ "Lejon aplikacionin të konfigurojë telefonin lokal \"bluetooth\" dhe të zbulojë e çiftohet me pajisjet në distancë." "lidhu dhe shkëputu nga WiMAX" "Lejon aplikacionin të përcaktojë nëse WiMAX është i aktivizuar si dhe të mësojë informacion rreth ndonjë rrjeti të lidhur WiMAX." - "Ndrysho gjendjen WiMAX" + "ndrysho gjendjen WiMAX" "Lejon aplikacionin ta lidhë tabletin dhe ta shkëpusë atë nga rrjetet WiMAX." "Lejon aplikacionin të lidhet me televizorin dhe ta shkëpusë atë nga rrjetet WiMAX." "Lejon aplikacionin të lidhet me telefonin dhe ta shkëpusë atë nga rrjetet WiMAX." @@ -485,7 +485,7 @@ "Lejon aplikacionin të modifikojë parametrat e kalibrimit të ekranit me prekje. Nuk nevojitet për aplikacionet normale." "qasje në certifikatat DRM" "Lejon një aplikacion të përgatisë dhe përdorë certifikatat DRM. Nuk nevojitet për aplikacionet normale." - "Merr statusin e transferimit të \"rrezes android\"" + "merr statusin e transferimit përmes \"Dërgimit me rreze të Android\"" "Lejon këtë aplikacion të marrë informacion rreth transferimeve aktuale \"Rrezja android\" (Android Beam)" "hiq certifikatat DRM" "Lejon një aplikacion të heqë certifikatat DRM. Nuk nevojitet për aplikacionet normale." @@ -1091,11 +1091,11 @@ "Po formaton…" "Nuk është futur" "Nuk u gjet asnjë aktivitet që përputhet." - "Kalo daljet e medias" + "kalo daljet e përmbajtjes audio-vizuale" "Lejon një aplikacion të kalojë daljet mediatike në pajisje të tjera të jashtme." - "Lexo sesionet e instalimit" + "lexo sesionet e instalimit" "Lejon një aplikacion të lexojë sesionet e instalimit. Kjo e lejon atë të shohë detaje rreth instalimeve të paketave aktive." - "Kërko paketat e instalimit" + "kërko paketat e instalimit" "Lejon që një aplikacion të kërkojë instalimin e paketave." "Prek dy herë për të kontrolluar zmadhimin" "Nuk mundi të shtonte miniaplikacion." diff --git a/core/res/res/values-sr-watch/strings.xml b/core/res/res/values-sr-watch/strings.xml index 484977e804587..3f863805dd2cd 100644 --- a/core/res/res/values-sr-watch/strings.xml +++ b/core/res/res/values-sr-watch/strings.xml @@ -21,4 +21,5 @@ "Апликација %1$d од %2$d." + "Сензори" diff --git a/core/res/res/values-sr/cm_strings.xml b/core/res/res/values-sr/cm_strings.xml new file mode 100644 index 0000000000000..b15b557dba45b --- /dev/null +++ b/core/res/res/values-sr/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Снимак екрана + + прими заштићени SMS + + Дозволи да апликације приме долазећи заштићени SMS. + + измените заштићену SMS листу + + Дозвољава апликацији да мења заштићену SMS листу адреса. + + Безбедност + + Дозволе које се односе на безбедносне информације уређаја. + + читај црну листу телефона + + Омогућава апликацији да чита информације о телефонским бројевима који су блокирани за долазне позиве или поруке. + + мењај црну листу телефона + + Омогућава апликацији да промени бројеве телефона које су блокирани за долазне позиве или поруке. + + постави позадину закључаног екрана + + Омогућава апликацији да промени позадину на закључаном екрану. + + Рестартуј + + Тренутно + + + Рестартуј + + Опоравак + + Bootloader + + Преузимање + + Рестартуј интерфејс + + Рестартуј + + Tаблет ће се рестартовати. + Tелефон ће се рестартовати. + + Рестартовање\u2026 + + Апликација је затворена + + ADB преко мреже омогућен + + ADB преко USB & мреже омогућен + + Додирни да онемогућиш отклањање грешака. + + ADB - %1$s + USB & мрежа + USB + Мрежа + + пресретни подизање апликације + + %s није инсталирано + + Приоритет + Ниједан + + Онемогућен Wi-Fi hotspot због промене SIM претплате + + Искључи Wi-Fi + + омогући или онемогући заштиту приватности + Дозвољава апликацији да промени да ли се друга апликација покреће са заштитом приватности. Када је апликација покренута са заштитом приватности, она неће имати приступ личним подацима, као што су контакти, евиденција позива или поруке. + Заштита приватности је активна + %1$s неће бити у могућности да приступи личним подацима + Заштита приватности + %1$s жели да %2$s. + + Запамти мој избор + + приступ камери + приступ твојој локацији + прочитај твоја обавештења + aктивирај VPN + покрени при укључивању + избриши свој дневник позива + избриши своје контакте + избриши своје MMS поруке + избриши своје SMS поруке + исцртај windows на врху + добиј статистику коришћења апликација + држи уређај будним + обави телефонски позив + ажурирај твој календар + ажурирај евиденцију позива + модификуј привремену меморију + ажурирај твоје контакте + ажурирај подешавања система + искључи/укључи микрофон + пусти аудио + постави обавештење + пројектовање медија + прочитај твој календар + прочитај евиденцију позива + прочитај привремену меморију + прочитај твоје контакте + прочитај твоје MMS поруке + прочитај твоје SMS поруке + прими SMS поруку + сними звук + пошаљи MMS поруку + пошаљи SMS поруку + покрени при укључивању + прикажи искачуће поруке + пребаци Bluetooth + Укључи/искључи мобилне податке + пребацуј NFC + Wi-FI прекидач + контрола јачине аларма + контрола аудио фокуса + контрола Bluetooth јачине + контрола главне јачине + користи дугмиће за медије + контрола јачине за медије + контрола јачине обавештења + контрола јачине звона + користи повратне информације + контрола јачине гласовног позива + напиши MMS поруку + напиши SMS поруку + користи отисак прста + додај говорну поруку + приступ стању телефона + Скенирај Wi-Fi мреже + промени тапет + користи помоћну структуру + направи снимак екрана + користи сензоре уређаја + читај ћелију емитовања + лажирај своју локацију + читај спољно складиште + пиши на спољно складиште + укључи екран + добави налог уређаја + промени Wi-Fi стање + дај root приступ + + Да искључиш овај екран додирни и држи дугме за назад. + + Нема повезаног уређаја + %1$s конектован уређај + %1$s конектовани уређаји + + + + Блокирана активност покретања + %1$s је заштићена од покретања. Додирни да потврдиш и покрени апликацију. + + Батерија пуна + Искључи пуњач са уређаја да би побољшао трајност батерије. + + ресетуј статистику батерије + + Омогућава апликацији да ресетује актуелне податке ниског нивоа коришћења батерије. + + SIM картица је промењена + Додирни да поставиш задане поставке за SIM картицу + diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index d4f3ffbe767da..3d259ae5b872d 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -255,7 +255,7 @@ "Обухвата личне податке као што су бројеви кредитних картица и лозинке." "онемогућавање или измена статусне траке" "Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе." - "статусна трака" + "функционисање као статусна трака" "Дозвољава апликацији да функционише као статусна трака." "проширење/скупљање статусне траке" "Дозвољава апликацији да проширује или скупља статусну траку." @@ -283,7 +283,7 @@ "Дозвољава апликацији да прима и обрађује WAP поруке. Ова дозвола укључује могућност праћења или брисања порука које вам се шаљу, а које вам се не приказују." "преузимање покренутих апликација" "Дозвољава апликацији да преузима информације о актуелним и недавно покренутим задацима. Ово може да омогући апликацији да открије информације о томе које се апликације користе на уређају." - "Управљај власницима профила и уређаја" + "управљање власницима профила и уређаја" "Дозвољава апликацији да подеси власнике профила и власника уређаја." "промена редоследа покренутих апликација" "Дозвољава апликацији да премешта задатке у први план и у позадину. Апликација може да ради ово без вашег уноса." @@ -325,7 +325,7 @@ "Дозвољава апликацији да мења евиденцију позива на таблету, укључујући податке о долазним и одлазним позивима. Злонамерне апликације могу ово да користе да би брисале или мењале евиденцију позива." "Дозвољава апликацији да мења евиденцију позива на ТВ-у, укључујући податке о долазним и одлазним позивима. Злонамерне апликације могу ово да користе да би брисале или мењале евиденцију позива." "Дозвољава апликацији да мења евиденцију позива на телефону, укључујући податке о долазним и одлазним позивима. Злонамерне апликације могу ово да користе да би брисале или мењале евиденцију позива." - "телесни сензори (нпр. срчани монитор)" + "приступ сензорима на телу (попут монитора за праћење пулса)" "Дозвољава апликацији да приступа подацима са сензора који надгледају физичку кондицију, као што је број откуцаја срца." "читање календарских догађаја и поверљивих информација" "Дозвољава апликацији да чита све догађаје календара ускладиштене на таблету, укључујући догађаје пријатеља или колега. Ово може да омогући апликацији да дели или чува податке календара, без обзира на поверљивост или осетљивост." @@ -337,15 +337,15 @@ "Дозвољава апликацији да додаје, уклања и мења догађаје које можете да измените на телефону, укључујући догађаје пријатеља и колега. Ово може да омогући апликацији да шаље поруке које изгледају као да их шаљу власници календара или мења догађаје без знања власника." "приступ додатним командама добављача локације" "Омогућава апликацији да приступа додатним командама даваоца услуга локације. То може да омогући апликацији да утиче на рад GPS-а или других извора локације." - "прецизна локација (заснована на GPS-у и мрежи)" + "приступ прецизној локацији (утврђена преко мреже и GPS-а)" "Дозвољава апликацији да преузме прецизне податке о вашој локацији помоћу глобалног система позиционирања (GPS) или мрежних извора локација као што су мобилни предајници и Wi-Fi мреже. Ове услуге лоцирања морају да буду укључене и доступне уређају да би апликација могла да их користи. Апликације на основу овога могу да одреде где се приближно налазите и могу додатно да троше батерију." - "приближна локација (заснована на мрежи)" + "приступ приближној локацији (утврђена преко мреже)" "Дозвољава апликацији да преузме податке о вашој приближној локацији. Податке о овој локацији обезбеђују услуге лоцирања помоћу мрежних извора локација као што су мобилни предајници и Wi-Fi мреже. Ове услуге лоцирања морају да буду укључене и доступне уређају да би апликација могла да их користи. Апликације на основу овога могу да одреде где се приближно налазите." "промена аудио подешавања" "Дозвољава апликацији да мења глобална аудио подешавања као што су јачина звука и избор звучника који се користи као излаз." "снимање аудио записа" "Дозвољава апликацији да снима звук помоћу микрофона. Ова дозвола омогућава апликацији да снима звук у било ком тренутку без ваше потврде." - "Комуникација са SIM картицом" + "слање команди на SIM" "Омогућава апликацији да шаље команде SIM картици. То је веома опасно." "снимање фотографија и видео снимака" "Дозвољава апликацији да снима слике и видео снимке камером. Ова дозвола омогућава апликацији да у било ком тренутку користи камеру без ваше потврде." @@ -383,7 +383,7 @@ "Дозвољава апликацији да преузима листу налога познатих телефону. Ово може да обухвата било које налоге које праве апликације које инсталирате." "преглед мрежних веза" "Дозвољава апликацији да прегледа информације о мрежним везама као што су информације о томе које мреже постоје и које мреже су повезане." - "пун мрежни приступ" + "има пун мрежни приступ" "Дозвољава апликацији да прави мрежне прикључке и користи прилагођене мрежне протоколе. Прегледач и друге апликације омогућавају слање података на Интернет, па ова дозвола није потребна за слање података на Интернет." "промена везе са мрежом" "Дозвољава апликацији да мења статус повезивања са мрежом." @@ -403,7 +403,7 @@ "Дозвољава апликацији да конфигурише локални Bluetooth телефон, као и да открије даљинске уређаје и упари се са њима." "повезивање и прекид везе са WiMAX-ом" "Дозвољава апликацији да утврди да ли је WiMAX омогућен, као и информације о било којим повезаним WiMAX мрежама." - "Промени WiMAX статус" + "промени WiMAX статуса" "Дозвољава апликацији да повезује таблет са WiMAX мрежама и прекида везе са њима." "Дозвољава апликацији да повезује ТВ са WiMAX мрежама и да раскида ту везу." "Дозвољава апликацији да повезује телефон са WiMAX мрежама и прекида везе са њима." @@ -486,7 +486,7 @@ "Дозвољава апликацији да модификује параметре калибрације додирног екрана. Не би требало да буде потребно за нормалне апликације." "приступ DRM сертификатима" "Дозвољава апликацији да додељује и користи DRM сертификате. Никада не би требало да се користи за уобичајене апликације." - "Пријем статуса пребацивања помоћу Android пребацивања" + "пријем статуса пребацивања помоћу Android пребацивања" "Дозвољава овој апликацији да прима информације о актуелним пребацивањима помоћу Android пребацивања" "уклањај DRM сертификате" "Дозвољава апликацији да уклања DRM сертификате. Никада не би требало да се користи за обичне апликације." @@ -1098,11 +1098,11 @@ "Форматира се..." "Није уметнут" "Није пронађена ниједна подударна активност." - "Усмеравање излаза медија" + "усмеравање излаза медија" "Дозвољава апликацији да усмерава излаз медија на друге спољне уређаје." - "Читај сесије инсталирања" + "читање сесија инсталирања" "Дозвољава апликацији да чита сесије инсталирања. То јој дозвољава да види детаље о активним инсталацијама пакета." - "Захтевај инсталирање пакета" + "захтевање пакета за инсталирање" "Омогућава да апликација захтева инсталацију пакета." "Додирните двапут да бисте контролисали зум" "Није могуће додати виџет." diff --git a/core/res/res/values-sv-watch/strings.xml b/core/res/res/values-sv-watch/strings.xml index 3bd7fa50f60de..e6da48ac3368f 100644 --- a/core/res/res/values-sv-watch/strings.xml +++ b/core/res/res/values-sv-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d av %2$d." + "Sensorer" diff --git a/core/res/res/values-sv/cm_strings.xml b/core/res/res/values-sv/cm_strings.xml new file mode 100644 index 0000000000000..c5c91b0535094 --- /dev/null +++ b/core/res/res/values-sv/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Skärmdump + + ta emot skyddade SMS + + Tillåter att appen tar emot ett inkommande skyddat SMS. + + ändra lista över skyddade SMS + + Tillåter att appen ändrar listan över skyddade SMS. + + Säkerhet + + Behörigheter relaterade till enhetssäkerhet. + + läsa telefonens svartlista + + Tillåter en app att läsa information kring telefonnummer som är blockerade för inkommande samtal eller meddelanden. + + ändra telefonens svartlista + + Tillåter en app att ändra de telefonnummer som är blockerade för inkommande samtal eller meddelanden. + + ställa in bakgrundsbild på låsskärm + + Tillåter en app att ändra låsskärmens bakgrundsbild. + + Omstart + + Nuvarande + + + Starta om + + Recovery + + Bootloader + + Download + + Mjuk omstart + + Starta om + + Din surfplatta kommer att startas om. + Din telefon kommer att startas om. + + Startar om\u2026 + + App tvångsavslutad + + ADB över nätverk aktiverat + + ADB över USB och nätverk aktiverat + + Tryck på för att inaktivera felsökning. + + ADB - %1$s + USB & nätverk + USB + Nätverk + + avbryt app-start + + %s är inte installerad + + Prioritet + Ingen + + Wi\u2011Fi hotspot avaktiverad på grund av ändrat SIM-abonnemang + + Inaktivera Wi\u2011Fi + + aktivera eller inaktivera integritetsskydd + Tillåter appen att ändra huruvida en annan app körs med integritetsskydd. När en app körs med integritetsskydd har den ingen tillgång till personlig data som kontakter, samtalslistor och meddelanden. + Integritetsskydd aktivt + %1$s kommer inte få tillgång till personlig data + Integritetsskydd + %1$s skulle vilja %2$s. + + Kom ihåg mitt val + + få tillgång till kamera + få tillgång till din plats + läsa dina aviseringar + aktivera en VPN + starta vid uppstart + ta bort samtalsloggen + ta bort dina kontakter + ta bort dina MMS-meddelanden + ta bort dina SMS-meddelanden + rita fönster överst + få användningsstatistik för app + hålla din enhet vaken + ringa + uppdatera din kalender + uppdatera samtalslistan + modifiera urklipp + uppdatera dina kontakter + uppdatera systeminställningar + slå på/av mikrofonen + spela ljud + skicka en avisering + projektmedia + läsa din kalender + läsa samtalslistan + läsa urklipp + läsa dina kontakter + läsa dina MMS + läsa dina SMS + ta emot ett SMS + spela in ljud + skicka ett MMS + skicka ett SMS + starta vid uppstart + visa toast-meddelanden + växla Bluetooth + växla mobildata + växla NFC + växla Wi\u2011Fi + kontrollera alarmvolym + kontrollera ljudfokus + kontrollera Bluetoothvolymen + kontrollera mastervolymen + använda mediaknapparna + kontrollera mediavolymen + kontrollera aviseringsvolymen + kontrollera ringsignalsvolymen + använda haptisk feedback + kontrollera samtalsvolymen + skriva ett MMS + skriva ett SMS + använd fingeravtryck + lägg till ett röstmeddelande + läs telefonstatus + skanna Wi\u2011Fi-nätverk + ändra bakgrund + använd assistansstruktur + ta en skärmdump + använd kroppssensorer + läs mobila sändningar + ange skenplats + läs extern lagring + skriv extern lagring + aktivera skärmen + hämta enhetskonton + ändra Wi\u2011Fi status + få root-åtkomst + + För att frigöra denna skärm, tryck och håll nere Bakåt-knappen. + + Ingen ansluten enhet + %1$s ansluten enhet + %1$s anslutna enheter + + + + Aktivitetsstart blockerad + %1$s är skyddad från att startas. Tryck för att autentisera och starta programmet. + + Batteriet fulladdat + Koppla bort enheten från laddaren för att förbättra batteriets livslängd. + + återställa batteristatistik + + Tillåter en app att återställa nuvarande lågnivådata för batterianvändning. + + SIM-kort har ändrats + Tryck för att ange standardinställningar för SIM-kortet + diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index e815fdbb77925..e59ddb9cecc6d 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -254,7 +254,7 @@ "Omfattar personuppgifter som kreditkortsnummer och lösenord." "inaktivera eller ändra statusfält" "Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner." - "statusfält" + "visas i statusfältet" "Tillåter att appen visas i statusfältet." "expandera/komprimera statusfält" "Tillåter att appen expanderar eller komprimerar statusfältet." @@ -282,7 +282,7 @@ "Tillåter att appen tar emot och hanterar WAP-meddelanden. Med den här behörigheten kan appen övervaka eller ta bort meddelanden som skickats till dig utan att visa dem för dig." "hämta appar som körs" "Tillåter att appen hämtar information om nyligen körda och pågående aktiviteter. Detta kan innebära att appen tillåts ta reda på vilka appar som används på enheten." - "Hantera profil- och enhetsägare" + "hantera profil- och enhetsägare" "Tillåter att appar anger profilägare och enhetsägare." "byt ordning på appar som körs" "Tillåter att appen flyttar aktiviteter till förgrunden eller bakgrunden. Appen kan göra detta utan åtgärd från dig." @@ -324,7 +324,7 @@ "Tillåter att appen gör ändringar i pekdatorns samtalslista, inklusive i uppgifter om inkommande och utgående samtal. Skadliga program kan använda detta för att radera eller ändra din samtalslista." "Tillåter att appen gör ändringar i TV:ns samtalslista, inklusive i uppgifter om inkommande och utgående samtal. Skadliga appar kan använda detta för att rensa eller ändra din samtalslista." "Tillåter att appen gör ändringar i mobilens samtalslista, inklusive i uppgifter om inkommande och utgående samtal. Skadliga program kan använda detta för att radera eller ändra din samtalslista." - "kroppssens. (för hjärtat m.m.)" + "få åtkomst till kroppssensorer (till exempel pulsmätare)" "Ger appen åtkomst till information från sensorer om ditt fysiska tillstånd, till exempel din puls." "läsa kalenderuppgifter plus konfidentiell information" "Tillåter att appen läser alla kalenderuppgifter som sparats på surfplattan, inklusive dina vänners eller kollegors uppgifter. Med den här behörigheten kan appen tillåtas att dela eller spara kalenderuppgifter även om de är sekretessbelagda eller känsliga." @@ -336,15 +336,15 @@ "Tillåter att appen lägger till, tar bort och ändrar sådana händelser som du kan ändra på mobilen, inklusive dina vänners eller kollegors uppgifter. Detta kan innebära att appen tillåts skicka meddelanden som ser ut att komma från kalenderns ägare eller ändra händelser utan ägarens vetskap." "få åtkomst till extra kommandon för platsleverantör" "Tillåter att appen får åtkomst till extra kommandon för platsleverantör. Detta kan innebära att appen tillåts störa funktionen för GPS eller andra platskällor." - "exakt plats (GPS- och nätverksbaserad)" + "få åtkomst till din exakta position (GPS- och nätverksbaserad)" "Tillåter att appen känner av din ungefärliga position med hjälp av GPS eller platstjänster som mobilmaster och Wi-Fi. Platstjänsterna måste vara aktiverade och tillgängliga på enheten för att appen ska kunna använda dem. Appar kan använda detta för att avgöra ungefär var du befinner dig." - "ungefärlig position (nätverksbaserad)" + "få åtkomst till din ungefärliga position (nätverksbaserad)" "Tillåter att appen känner av din ungefärliga position. Platsen avgörs genom platstjänster med hjälp av nätverksplatskällor som mobilmaster och Wi-Fi. Platstjänsterna måste vara aktiverade och tillgängliga på enheten för att appen ska kunna använda dem. Appar kan använda detta för att avgöra ungefär var du befinner dig." "ändra dina ljudinställningar" "Tillåter att appen ändrar globala ljudinställningar som volym och vilken högtalarutgång som används." "spela in ljud" "Tillåter att appen spelar in ljud med mikrofonen. Med den här behörigheten tillåts appen att spela in ljud när som helst utan ditt godkännande." - "SIM-kommunikation" + "skicka kommandon till SIM-kortet" "Tillåter att appen skickar kommandon till SIM-kortet. Detta är mycket farligt." "ta bilder och spela in videoklipp" "Tillåter att appen tar bilder och spelar in videor med kameran. Med den här behörigheten tillåts appen att använda kameran när som helst utan ditt godkännande." @@ -382,7 +382,7 @@ "Tillåter att appen hämtar en lista över alla kända konton på mobilen. Detta kan inkludera konton som har skapats av appar som du har installerat." "visa nätverksanslutningar" "Tillåter att appen kommer åt information om nätverksanslutningarna, till exempel vilka nätverk som finns och är anslutna." - "fullständig nätverksåtkomst" + "få fullständig nätverksåtkomst" "Tillåter att appen skapar nätverksuttag och använder anpassade nätverksprotokoll. Webbläsaren och andra appar gör det möjligt att skicka data till Internet, så den här behörigheten krävs inte för att skicka data till Internet." "ändra nätverksanslutning" "Tillåter att appen ändrar statusen för en nätverksanslutning." @@ -402,7 +402,7 @@ "Tillåter att appen konfigurerar den lokala Bluetooth-mobilen samt upptäcker och parkopplar den med fjärranslutna enheter." "ansluta till och koppla från WiMAX" "Tillåter att appen avgör om WiMAX är aktiverat och kommer åt information om eventuella anslutna WiMAX-nätverk." - "ändra WiMAX-status" + "ändra WiMAX-status" "Tillåter att appen ansluter surfplattan till eller kopplar från WiMAX-nätverk." "Tillåter att appen ansluter TV:n till och kopplar från TV:n från WiMAX-nätverk." "Tillåter att appen ansluter mobilen till eller kopplar från WiMAX-nätverk." @@ -485,7 +485,7 @@ "Tillåter att appen ändrar kalibreringsparametrarna för pekskärmen. Detta behövs aldrig för vanliga appar." "tillgång till DRM-certifikat" "Tillåter att en app tillhandahåller och använder DRM-certifikat. Behövs inte för vanliga appar." - "Ta emot status för Android Beam-överföring" + "ta emot status för Android Beam-överföring" "Tillåter att appen tar emot information om aktuella Android Beam-överföringar" "ta bort DRM-certifikat" "Tillåter ett program att ta bort DRM-certifikat. Behövs inte för vanliga appar." @@ -1091,11 +1091,11 @@ "Formaterar ..." "Inte isatt" "Det gick inte att hitta några matchande aktiviteter." - "Omdirigera medieuppspelning" + "dirigera medieuppspelning" "Tillåter att appen omdirigerar medieuppspelningar till andra externa enheter." - "Läsa installationssessioner" + "läsa installationssessioner" "Tillåt appen att läsa installationssessioner. Det ger den tillgång till uppgifter om aktiva paketinstallationer." - "Begär installationspaket" + "begära installationspaket" "Tillåter att en app begär paketinstallation." "Tryck två gånger för zoomkontroll" "Det gick inte att lägga till widgeten." diff --git a/core/res/res/values-sw-watch/strings.xml b/core/res/res/values-sw-watch/strings.xml index 5a8c72e2e2201..38c667d6d0c50 100644 --- a/core/res/res/values-sw-watch/strings.xml +++ b/core/res/res/values-sw-watch/strings.xml @@ -21,4 +21,5 @@ "Programu ya %1$d kati ya %2$d." + "Vihisi" diff --git a/core/res/res/values-sw/cm_strings.xml b/core/res/res/values-sw/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-sw/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index da5d6a3c73bd9..71fde57a2d45d 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -256,7 +256,7 @@ "Inajumuisha data binafsi kama vile nambari za kadi ya mkopo na manenosiri." "zima au rekebisha mwambaa hali" "Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa ikoni za mfumo." - "mwamba hali" + "kuwa sehemu ya arifa" "Inaruhusu programu kuwa upau wa hali." "panua/kunja mwambaa hali" "Inaruhusu programu kupanua au kukunja upau wa hali." @@ -284,7 +284,7 @@ "Inaruhusu programu kupokea na kuchakata ujumbe wa WAP. Idhini hii inajumuisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwako bila ya kukuonyesha." "rudisha programu zinazoendeshwa" "Inaruhusu programu kurudisha taarifa kuhusu kazi zinazoendeshwa sasa na hivi karibuni. Hii inaweza kuruhusu programu kugundua taarifa kuhusu ni programu zipi zinazotumika kwenye kifaa." - "Simamia wamiliki wa wasifu na kifaa" + "simamia wamiliki wa wasifu na vifaa" "Huruhusu programu kuweka wamiliki wa wasifu na mmiliki wa kifaa." "Agiza tena programu za kuendeshwa" "Inaruhusu programu kusongesha kazi hadi kwenye mandhari-mbele na mandari nyuma. Programu inaweza kufanya haya bila ya maingizo yako." @@ -326,7 +326,7 @@ "Huruhusu programu kurekebisha rajisi ya kompyuta kibao yako, ikiwa ni pamoja na simu zinazoingia na kutoka. Huenda programu hasidi zikatumia hii ili kufuta au kurekebisha rajisi ya simu yako." "Huruhusu programu kurekebisha rajisi ya runinga yako, ikiwa ni pamoja na data ya simu zinazoingia na kutoka. Huenda programu hasidi zikatumia hii ili kufuta au kurekebisha rajisi ya simu yako." "Huruhusu programu kurekebisha rajisi ya simu yako, ikiwa ni pamoja na simu zinazoingia na kutoka. Huenda programu hasidi zikatumia hii ili kufuta au kurekebisha rajisi ya simu yako." - "vipima hali ya mwili (kama mpigo wa moyo)" + "fikia vihisi vya mwili (kama vifuatiliaji vya mapigo ya moyo)" "Huruhusu programu kufikia data kutoka vihisi vinavyofuatilia hali yako ya kimwili, kama vile mapigo ya moyo." "soma matukio ya kalenda pamoja na maelezo ya siri" "Inaruhusu programu kusoma matukio yote ya kalenda yaliohifadhiwa kwenye kompyuta kibao yako, yakijumuisha yale ya marafiki au wafanyakazi wenza. Hii inaweza kuruhusu programu kushiriki au kuhifadhi data yako ya kaelnda, bila kujali usiri au unyeti." @@ -338,15 +338,15 @@ "Inaruhusu programu kuongeza, kuondoa, kubadilisha matukio ambayo unaweza kurekebisha kwenye simu yako, yakijumulisha yale ya marafiki na wafanyakazi wenza. Hii inaweza kuruhusu programu kutuma ujumbe unaonekana kuwa unatoka kwa mmiliki wa kalenda, au kurekebisha matukio bila mmiliki kujia." "fikia amri za ziada za mtoa huduma ya mahali" "Ruhusu programu kufikia amri za ziada za mtoa huduma za mahali. Hii huenda ikaruhusu programu ikatize matumizi ya GPS au vyanzo vingine vya eneo." - "kutambua eneo sahihi (GPS na mtandao)" + "fikia mahali halisi (inategemea mtandao na GPS)" "Inaruhusu programu kupata eneo lako sahihi kwa kutumia Mfumo wa Mkao Ulimwenguni (GPS) au vyanzo vya mtandao vya eneo kama vile minara na Wi-Fi. Lazima huduma hizi za eneo ziwashwe na kupatikana kwenye kifaa chako ili programu izitumie. Huenda programu zikatumia hii kutambua ulipo, na zinaweza kutumia kawi ya ziada ya betri." - "kukadiria eneo (kwenye mtandao)" + "fikia mahali karibu na hapo (inategemea mtandao)" "Inaruhusu programu kupata eneo lako la kukadiria. Eneo hili linatokana na huduma za maeneo kwa kutumia vyanzo vya mtandao vya eneo kama vile minara na Wi-Fi. Lazima huduma hizi za eneo ziwashwe na kupatikana kwenye kifaa chako ili programu izitumie. Huenda programu zikatumia hii kutambua ulipo kwa kukadiria." "badilisha mipangilio yako ya sauti" "Inaruhusu programu kurekebisha mipangilio ya sauti kila mahali kama vile sauti na ni kipaza sauti kipi ambacho kinatumika kwa kutoa." "kurekodi sauti" "Inaruhusu programu kurekodi sauti kwa kinasa sauti. Idhini hii inaruhusu programu kurekodi sauti wakati wowote bila ya uthibitisho wako." - "mawasiliano ya sim" + "tuma amri kwenye SIM" "Huruhusu programu kutuma amri kwa SIM. Hii ni hatari sana." "Kupiga picha na kurekodi video" "Inaruhusu programu kupiga picha na video kwa kamera. Kibali hiki kinaruhusu programu kutumia kamera kwa wakati wowote bila uthibitisho wako." @@ -384,7 +384,7 @@ "Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa simu. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha." "kuona mitandao" "Inaruhusu programu kuona taarifa kuhusu miunganisho ya mtandao kama vile mitandao ipi iliyopo na imeunganishwa." - "ufikiaji kamili wa mtandao" + "pata ufikiaji kamili wa mtandao" "Inaruhusu programu kuunda soketi za mtandao na kutumia itifaki za mtandao maalum. Kivinajri na programu nyingine zilizotolewa zinamaanisha kutuma data kwenye mtandao, kwa hivyo kibali hiki hakihitajiki kutuma data kwenye mtandao." "kubadilisha muunganisho wa mtandao" "Inaruhusu programu kubadilisha hali ya muunganisho wa mtandao." @@ -404,7 +404,7 @@ "Inaruhusu programu kusanidi simu ya karibu ya Bluetooth, na kutambua na kuoanisha na vifaa vya mbali." "unganisha na uukate muunaganisho kutoka kwenye WiMAX" "Inaruhusu programu kuthibitisha ikiwa WiMAX imewezeshwa na taarifa kuhusu mitandao yoyote ya WiMAX ambayo imeunganishwa." - "Badilisha hali ya WiMAX" + "badilisha hali ya WiMAX" "Inaruhusu programu kuunganisha kompyuta kibao, na kukata kompyuta kibao kutoka mitandao ya WiMAX." "Huruhusu programu kuunganisha runinga kwenye na kuondoa runinga kutoka mitandao ya WiMAX." "Inaruhusu programu kuunganisha simu kwenye, na kukata simu kutoka mitandao ya WiMAX." @@ -487,7 +487,7 @@ "Huruhusu programu kubadilisha vigezo vya urekebishaji vya skrini ya kugusa. Havipaswi kuhitajika kamwe kwa programu za kawaida." "fikia vyeti vya DRM" "Huruhusu programu kwa utoaji na matumizi ya vyeti vya DRM. Havifahi kuhitajika kwa ajili ya programu za kawaida." - "Pokea hali ya uhamisho wa Boriti ya Android" + "pokea hali ya usambazaji wa Boriti ya Android" "Huruhusu programu hii kupokea taarifa kuhusu uhamisho wa Boriti ya Android" "ondoa vyeti vya DRM" "Huruhusu programu kuondoa vyeti vya DRM. Haipaswi kuhitajika kwa programu za kawaida kamwe." @@ -1093,11 +1093,11 @@ "Inaumbiza..." "Haijaingizwa" "Hakuna shughuli zinazolingana zilizopatikana." - "Fuatalia utoaji wa habari" + "sambaza data ya maudhui" "Inaruhusu programu kufuatilia utoaji wa habari kwa vifaa vingine vya nje." - "Soma vipindi vya kusanikisha" + "soma vipindi vya kusakinisha" "Huruhusu programu kusoma vipindi vya kusanikisha. Hii huiruhusu kuona maelezo kuhusu usanikishaji wa programu unaoendelea." - "Omba idhini ya kusakinisha vifurushi" + "omba ruhusa ya kusakinisha vifurushi" "Huruhusu programu kuomba idhini ya kusakinisha vifurushi." "Gusa mara mbili kwa udhibiti cha kuza" "Haikuweza kuongeza wijeti." diff --git a/core/res/res/values-ta-rIN-watch/strings.xml b/core/res/res/values-ta-rIN-watch/strings.xml index 4c05cabdadc34..737f6d05cbe91 100644 --- a/core/res/res/values-ta-rIN-watch/strings.xml +++ b/core/res/res/values-ta-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "பயன்பாடு: %1$d / %2$d." + "உணர்விகள்" diff --git a/core/res/res/values-ta-rIN/cm_strings.xml b/core/res/res/values-ta-rIN/cm_strings.xml new file mode 100644 index 0000000000000..9b129f3573150 --- /dev/null +++ b/core/res/res/values-ta-rIN/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + திரைப்பிடிப்பு + + பாதுகாக்கப்பட்ட SMSஐ பெறுக + + உள்வரும் பாதுகாக்கப்பட்ட SMS ஒன்றை பெற பயன்பாட்டை அனுமதிக்கிறது. + + பாதுகாக்கப்பட்ட SMS பட்டியலை மாற்றியமை. + + பாதுகாக்கப்பட்ட SMS முகவரி பட்டியலை மாற்றியமைக்க பயன்பாட்டை அனுமதிக்கிறது. + + பாதுகாப்பு + + சாதன பாதுகாப்பு தகவல் தொடர்பான அனுமதிகள். + + தொலைப்பேசி தடுப்புபட்டியலை படி + + உள்வரும் அழைப்புகள் அல்லது செய்திகளுக்காக தடுக்கப்பட்ட தொலைப்பேசி எண்கள் குறித்த தகவலை பயன்பாடு படிக்க அனுமதிக்கிறது. + + தொலைப்பேசி தடுப்புபட்டியலை மாற்று + + உள்வரும் அழைப்புகள் அல்லது செய்திகளுக்காக தடுக்கப்பட்ட தொலைப்பேசி எண்கள் குறித்த தகவலை பயன்பாடு மாற்ற அனுமதிக்கிறது. + + விசைபாதுகாப்பு வால்பேப்பரை அமை + + ஒரு பயன்பாடு பூட்டுத் திரையை மாற்ற அனுமதிக்கிறது. + + மீண்டும் தொடங்கு + + நடப்பு + + + மீண்டும் தொடங்கு + + மீட்டல் + + பூட்லோடர் + + இறக்கு + + மென்மையான மறுயியக்கம் + + மீண்டும் தொடங்கு + + உங்கள் டேப்ளட் மறுயியக்கமாகும். + உங்கள் தொலைப்பேசி மறுயியக்கமாகும். + + மறுஇயக்கம்செய்கிறது\u2026 + + பயன்பாடு கொல்லப்பட்டது + + நெட்வொர்க் மீது ADB செயல்படுத்தப்பட்டது + + USB & நெட்வொர்க் மீது ADB செயல்படுத்தப்பட்டது + + பிழைநீக்கலை முடக்க தொடு. + + ADB - %1$s + USB & நெட்வொர்க் + USB + நெட்வொர்க் + + இடைமறிப்பு பயன்பாடு தொடக்கம் + + %s நிறுவப்படவில்லை. + + முன்னுரிமை + ஏதுமில்லை + + SIM சந்தா மாற்றத்தின் காரணமாக wi-fi ஹாட்ஸ்பாட் முடக்கப்பட்டது. + + வை-ஃபைஐ ஆஃப் செய்க + + அந்தரங்கம் பாதுகாப்பானை செயல்படுத்து அல்லது முடக்கு + வேறொரு பயன்பாடு அந்தரங்கம் பாதுகாப்பானுடன் இயங்குகிறதா என்பதை மாற்ற பயன்பாட்டை அனுமதிக்கிறது. ஒரு பயன்பாடு அந்தரங்கம் பாதுகாப்பானுடன் இயங்கும்போது, அது தனிநபர் தரவுகளான தொடர்புகள், அழைப்பு பதிவுகள், அல்லது செய்திகள் போன்றவற்றை அணுகாது. + அந்தரங்கம் பாதுகாப்பான் செயல்பாட்டிலுள்ளது + %1$s தனிநபர் தரவை அணுக முடியாது + அந்தரங்கம் பாதுகாப்பான் + %1$s %2$s செய்ய விரும்புகிறார். + + எனது விருப்பத்தேர்வை நினைவில்கொள் + + கேமராவை அணுகவும் + உங்கள் இருப்பிடத்தை அணுகவும் + உங்கள் அறிவிப்பைப் படி + ஒரு VPNஐ செயல்படுத்து + மின்சக்தி அப்பில் தொடங்கவும் + உங்கள் அழைப்பு பதிவை நீக்குக + உங்கள் தொடர்புகளை நீக்குக + உங்கள் MMS செய்திகளை நீக்குக + உங்கள் SMS செய்திகளை நீக்குக + windosஐ மேலே இழுக்கவும் + பயன்பாட்டு பயன்படுத்தல் புள்ளிவிவரங்களைப் பெறு + உங்கள் சாதனத்தை விழிப்போடு வைத்திருக்கவும் + ஒரு தொலைப்பேசி அழைப்பை ஏற்படுத்தவும் + உங்கள் நாள்காட்டியை புதுப்பிக்கவும் + அழைப்பு பதிவை புதுப்பிக்கவும் + நகலகத்தை மாற்றியமைக்கவும் + உங்கள் தொடர்புகளை புதுப்பிக்கவும் + கணினி அமைப்புகளை புத்துப்பி + மைக்ரோஃபோனை ஒலிதடு/ஒலிதடைநீக்கு + ப்ளே ஆடியோ + ஒரு அறிவிப்பை இடுகையிடவும் + ஊடகத்தை வெளிப்படுத்து + உங்கள் நாள்காட்டியை படிக்கவும் + அழைப்பு பதிவை படிக்கவும் + நகலகத்தை படிக்கவும் + உங்கள் தொடர்புகளைப் படித்தல் + உங்கள் MMS செய்திகளை படிக்கவும் + உங்கள் SMS செய்திகளை படிக்கவும் + உங்கள் SMS செய்திகளை பெறவும் + ஆடியோவைப் பதிவுசெய்தல் + ஒரு MMS குறுந்தகவல் அனுப்புக + ஒரு SMS குறுந்தகவல் அனுப்புக + மின்சக்தி அப்பில் தொடங்கவும் + டோஸ்ட் செய்திகளை காண்பி + டோக்கில் ப்ளுடுத் + மொபைல் தரவு நிலைமாற்று + NFC நிலைமாற்று + Wi-Fi நிலைமாற்று + அலார ஒலியளவை கட்டுப்படுத்து + ஆடியோ குவிமையத்தைக் கட்டுப்படுத்து + ப்ளுடுத் ஒலியளவை கட்டுப்படுத்து + தலைமை ஒலியளவை கட்டுப்படுத்து + ஊடக பொத்தான்களைப் பயன்படுத்து + ஊடக ஒலியளவை கட்டுப்படுத்து + அறிவிப்பு ஒலியளவை கட்டுப்படுத்து + ரிங்டோன் ஒலியளவை கட்டுப்படுத்து + தீண்டும் பின்னூட்டத்தைப் பயன்படுத்து + குரல் அழைப்பு ஒலியளவை கட்டுப்படுத்து + ஒரு MMS செய்தி எழுது + ஒரு SMS செய்தி எழுது + கைரேகையைப் பயன்படுத்து + ஒரு குரலஞ்சலைச் சேர்த்தல் + தொலைபேசி நிலையை அணுகல் + Wi-Fi பிணையங்களை ஸ்கேன்செய் + வால்பேப்பரை மாற்று + உதவி கட்டமைப்பைப் பயன்படுத்து + ஒரு ஸ்க்ரீன்ஷாட்டை எடு + உடல் உணர்கருவிகளைப் பயன்படுத்து + கலம் ஒளிபரப்புகளை படி + உங்கள் இருப்பிடத்தை போலியாக்கு + வெளிப்புற சேமிப்பகத்தைப் படி + உட்புற சேமிப்பகத்தை எழுது + திரையை ஆன் செய் + சாதன கணக்குகளைப் பெறு + Wi-fi நிலையை மாற்று + மூல அணுகலைப் பெறு + + இந்த திரையை அன்பின் செய்ய, பின்செல் பொத்தானைத் தொட்டு பிடித்துக்கொள். + + இணைக்கப்பட்ட சாதனம் இல்லை + %1$s இணைக்கப்பட்ட சாதனம் + %1$s இணைக்கப்பட்ட சாதனங்கள் + + + + செயல்பாட்டு துவக்கம் தடுக்கப்பட்டது + %1$s துவங்கப்படுவதில் இருந்து தடுக்கப்பட்டது. பயன்பாட்டை அங்கீகரிக்கவும் துவங்கவும் தட்டு. + + மின்கலம் முழுமையாக மின்னூட்டப்பட்டது + மின்கலத்தின் ஆயுளை மேம்படுத்த சார்ஜரிலிருந்து உங்கள் சாதனத்தின் இணைப்பை துண்டிக்கவும். + + மின்கல புள்ளிவிவரங்களை மீட்டமை + + நடப்பு குறைந்த-நிலை மின்கல பயன்பாட்டு தரவை மீட்டமைக்க ஒரு பயன்பாட்டை அனுமதிக்கிறது. + + diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml index 48b1e649386a8..544471be800a7 100644 --- a/core/res/res/values-ta-rIN/strings.xml +++ b/core/res/res/values-ta-rIN/strings.xml @@ -254,7 +254,7 @@ "கிரெடிட் கார்டு எண்கள் மற்றும் கடவுச்சொற்கள் போன்ற தனிப்பட்ட தகவலும் உள்ளடங்கும்." "நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்" "நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற பயன்பாட்டை அனுமதிக்கிறது." - "நிலைப் பட்டி" + "நிலைப் பட்டியில் இருக்கும்" "நிலைப் பட்டியில் இருக்க பயன்பாட்டை அனுமதிக்கிறது." "நிலைப் பட்டியை விரிவாக்குதல்/சுருக்குதல்" "நிலைப் பட்டியை விரிவாக்க அல்லது சுருக்க, பயன்பாட்டை அனுமதிக்கிறது." @@ -282,7 +282,7 @@ "WAP செய்திகளைப் பெற, செயற்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது. உங்களுக்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்க அல்லது நீக்குவதற்கான திறன் இந்த அனுமதியில் உள்ளடங்கும்." "இயங்கும் பயன்பாடுகளை மீட்டெடுத்தல்" "நடப்பில் மற்றும் சமீபத்தில் இயங்கும் காரியங்களின் தகவலைப் பெற பயன்பாட்டை அனுமதிக்கிறது. சாதனத்தில் எந்தப் பயன்பாடுகள் பயன்படுத்தப்படுகின்றன என்பது குறித்த தகவலைக் கண்டறிய பயன்பாட்டை இது அனுமதிக்கலாம்." - "சுயவிவரத்தையும் சாதன உரிமையாளர்களையும் நிர்வகிக்கவும்" + "சுயவிவரத்தையும் சாதன உரிமையாளர்களையும் நிர்வகித்தல்" "சுயவிவர உரிமையாளர்களையும் சாதன உரிமையாளரையும் அமைக்க, பயன்பாடுகளை அனுமதிக்கிறது." "இயங்கும் பயன்பாடுகளை மறுவரிசைப்படுத்தல்" "பின்புலத்திலும், முன்புலத்திலும் காரியங்களை நகர்த்த பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உள்ளீடு இல்லாமலே பயன்பாடு இதைச் செய்யலாம்." @@ -324,7 +324,7 @@ "உள்வரும் மற்றும் வெளிச்செல்லும் அழைப்புகள் குறித்த தகவல் உள்பட உங்கள் டேப்லெட்டின் அழைப்புப் பதிவைத் திருத்துவதற்குப் பயன்பாட்டை அனுமதிக்கிறது. உங்கள் அழைப்பின் பதிவை அழிக்க அல்லது திருத்த தீங்கு விளைவிக்கும் பயன்பாடுகள் இதைப் பயன்படுத்தலாம்." "உள்வரும் மற்றும் வெளிச்செல்லும் அழைப்புகள் குறித்த தகவல் உள்ளிட்ட உங்கள் டிவியின் அழைப்பு பதிவைத் திருத்த, பயன்பாட்டை அனுமதிக்கிறது. உங்கள் அழைப்பு பதிவை அழிக்க அல்லது திருத்த தீங்கு விளைவிக்கும் பயன்பாடுகள் இதைப் பயன்படுத்தலாம்." "உள்வரும் மற்றும் வெளிச்செல்லும் அழைப்புகள் குறித்த தகவல் உள்பட உங்கள் மொபைல் அழைப்புப் பதிவைத் திருத்துவதற்குப் பயன்பாட்டை அனுமதிக்கிறது. உங்கள் அழைப்பின் பதிவை அழிக்க அல்லது திருத்த தீங்கு விளைவிக்கும் பயன்பாடுகள் இதைப் பயன்படுத்தலாம்." - "உடல் உணர்விகள் (இதயத்துடிப்பு கண்காணித்தல் போன்றவை)" + "உடல் உணர்விகளை (இதயத் துடிப்பு மானிட்டர்கள் போன்றவை) அணுகுதல்" "உங்கள் இதயத்துடிப்பு விகிதம் போன்ற உங்கள் உடல்நிலையைக் கண்காணிக்கும் உணர்விகளில் இருந்து தரவை அணுக பயன்பாடுகளை அனுமதிக்கும்." "கேலெண்டர் நிகழ்வுகளையும், ரகசிய தகவலையும் படித்தல்" "நண்பர்கள் அல்லது சகப் பணியாளர்கள் ஆகியோரின் நிகழ்வுகளையும் சேர்த்து, உங்கள் டேப்லெட்டில் சேமிக்கப்பட்ட எல்லா கேலெண்டர் நிகழ்வுகளையும் படிக்க பயன்பாட்டை அனுமதிக்கிறது. உங்கள் கேலெண்டர் தரவின் ரகசியத்தன்மை அல்லது முக்கியத்துவத்தைப் பொருட்படுத்தாமல் அதனைப் பகிர அல்லது சேமிக்க பயன்பாட்டை இது அனுமதிக்கிறது." @@ -336,15 +336,15 @@ "நண்பர்கள் அல்லது சகப் பணியாளர்கள் உள்பட உங்கள் மொபைலில் நீங்கள் திருத்தக்கூடிய நிகழ்வுகளைச் சேர்க்கவும், அகற்றவும், மேலும் மாற்றவும் பயன்பாட்டை அனுமதிக்கிறது. இது கேலெண்டர் உரிமையாளர்களிடமிருந்து வரும் செய்திகளை அனுப்பவும் அல்லது உரிமையாளரின் ஒப்புதல் இல்லாமல் நிகழ்வுகளைத் திருத்தவும் பயன்பாட்டை அனுமதிக்கலாம்." "கூடுதல் இட வழங்குநரின் கட்டளைகளின் அணுகல்" "கூடுதல் இட வழங்குநர் கட்டளைகளை அணுகப் பயன்பாட்டை அனுமதிக்கிறது. இது, GPS அல்லது பிற இருப்பிட மூலங்களின் செயல்பாட்டை இடைமறிக்க பயன்பாட்டை அனுமதிக்கலாம்." - "துல்லியமான இருப்பிடம் (GPS மற்றும் நெட்வொர்க் சார்ந்தது)" + "துல்லியமான இருப்பிடத்தை அணுகுதல் (GPS மற்றும் நெட்வொர்க் அடிப்படையில்)" "க்ளோபல் பொசிஷனிங் சிஸ்டம் (GPS) அல்லது செல் கோபுரங்கள் மற்றும் வைஃபை போன்ற நெட்வொர்க் இருப்பிடச் சேவைகளைப் பயன்படுத்தி உங்கள் துல்லியமான இருப்பிடத்தைப் பெறப் பயன்பாட்டை அனுமதிக்கிறது. இந்த இருப்பிடச் சேவைகள் கண்டிப்பாக இயக்கப்பட்டு, பயன்பாடு பயன்படுத்துவதற்கு அவை உங்கள் சாதனத்தில் கிடைக்க வேண்டும். நீங்கள் எங்கிருக்கிறீர்கள் என்பதைத் தீர்மானிக்கப் பயன்பாடுகள் இதைப் பயன்படுத்தலாம், மேலும் இது கூடுதல் பேட்டரி சக்தியை உபயோகிக்கலாம்." - "தோராயமான இருப்பிடம் (நெட்வொர்க் சார்ந்தது)" + "தோராயமான இருப்பிடத்தை அணுகுதல் (நெட்வொர்க் அடிப்படையில்)" "உங்கள் தோராயமான இருப்பிடத்தைப் பெற பயன்பாட்டை அனுமதிக்கிறது. செல் கோபுரங்கள் மற்றும் வைஃபை போன்ற நெட்வொர்க் இருப்பிடச் சேவைகளைப் பயன்படுத்தி இருப்பிடச் சேவைகள் மூலம் இந்த இருப்பிடம் பெறப்படுகிறது. இந்த இருப்பிடச் சேவைகள் கண்டிப்பாக இயக்கப்பட்டு, பயன்பாடு பயன்படுத்துவதற்கு அவை உங்கள் சாதனத்தில் கிடைக்க வேண்டும். நீங்கள் எங்கிருக்கிறீர்கள் என்பதைத் தோராயமாகத் தீர்மானிக்கப் பயன்பாடுகள் இதைப் பயன்படுத்தலாம்." "எனது ஆடியோ அமைப்புகளை மாற்றுதல்" "ஒலியளவு மற்றும் வெளியீட்டிற்கு ஸ்பீக்கர்கள் பயன்படுத்தப்படுவது போன்ற ஒட்டுமொத்த ஆடியோ அமைப்புகளைக் கட்டுப்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது." "ஆடியோவைப் பதிவுசெய்தல்" "மைக்ரோஃபோன் மூலம் ஆடியோவைப் பதிவுசெய்ய பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இல்லாமல் எந்நேரத்திலும் ஆடியோவைப் பதிவுசெய்ய இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது." - "சிம் தகவல்தொடர்பு" + "கட்டளைகளை சிம்மிற்கு அனுப்புதல்" "சிம் க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்." "படங்கள் மற்றும் வீடியோக்களை எடுத்தல்" "கேமரா மூலமாகப் படங்களையும், வீடியோக்களையும் எடுக்க பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இன்றி கேமராவை எந்நேரத்திலும் பயன்படுத்தப் பயன்பாட்டை இது அனுமதிக்கிறது." @@ -382,7 +382,7 @@ "மொபைல் மூலம் அறியப்பட்ட கணக்குகளின் பட்டியலைப் பெற பயன்பாட்டை அனுமதிக்கிறது. நீங்கள் நிறுவிய பயன்பாடுகள் மூலம் உருவாக்கப்பட்ட எல்லா கணக்குகளும் இதில் உள்ளடங்கலாம்." "நெட்வொர்க் இணைப்புகளைக் காட்டு" "தற்போது இருக்கும் நெட்வொர்க்குகள் எவை மற்றும் இணைக்கப்பட்டுள்ளவை எவை போன்ற நெட்வொர்க் இணைப்புகள் குறித்த தகவலைப் பார்க்கப் பயன்பாட்டை அனுமதிக்கிறது." - "முழுமையான நெட்வொர்க் அணுகல்" + "முழுமையான நெட்வொர்க் அணுகலைக் கொண்டிருக்கும்" "நெட்வொர்க் சாக்கெட்டுகளை உருவாக்கவும் மற்றும் தனிப்பயன் நெட்வொர்க் நெறிமுறைகளைப் பயன்படுத்தவும் பயன்பாட்டை அனுமதிக்கிறது. இணையத்தில் தரவை அனுப்ப உலாவியும், பிற பயன்பாடுகளும் இருப்பதால், இணையத்திற்குத் தரவை அனுப்ப இந்த அனுமதி தேவையில்லை." "பிணைய இணைப்புத்தன்மையை மாற்றுதல்" "நெட்வொர்க் இணைப்பின் நிலையை மாற்ற, பயன்பாட்டை அனுமதிக்கிறது." @@ -402,7 +402,7 @@ "மொபைலில் அக புளூடூத் ஐ உள்ளமைக்க, தொலைநிலை சாதனங்களைக் கண்டறிந்து இணைக்க, பயன்பாட்டை அனுமதிக்கிறது." "WiMAX உடன் இணை மற்றும் அதனுடனான தொடர்பைத் துண்டி" "WiMAX இணைக்கப்பட்டுள்ளதா என்பதையும், இணைக்கப்பட்டுள்ள WiMAX நெட்வொர்க்குகள் ஏதேனும் குறித்த தகவலைத் தீர்மானிக்கவும் பயன்பாட்டை அனுமதிக்கிறது." - "WiMAX நிலையை மாற்றவும்" + "WiMAX நிலையை மாற்றுதல்" "WiMAX நெட்வொர்க்குகளில் டேப்லெட்டை இணைக்கவும், அவற்றிலிருந்து துண்டிக்கவும் பயன்பாட்டை அனுமதிக்கிறது." "டிவியுடன் இணைக்க மற்றும் WiMAX நெட்வொர்க்குகளிலிருந்து டிவியைத் துண்டிக்க, பயன்பாட்டை அனுமதிக்கிறது." "WiMAX நெட்வொர்க்குகளில் மொபைலை இணைக்கவும், அவற்றிலிருந்து துண்டிக்கவும் பயன்பாட்டை அனுமதிக்கிறது." @@ -485,7 +485,7 @@ "தொடுதல் திரையின் அளவு திருத்த அளபுருக்களை மாற்ற, பயன்பாட்டை அனுமதிக்கிறது. சாதாரண பயன்பாடுகளுக்குத் தேவைப்படாது." "DRM சான்றிதழ்களை அணுகுதல்" "DRM சான்றிதழ்களை வழங்க மற்றும் பயன்படுத்த, பயன்பாட்டை அனுமதிக்கிறது. சாதாரண பயன்பாடுகளுக்கு எப்போதும் தேவைப்படாது." - "Android பீம் பரிமாற்ற நிலையைப் பெறுக" + "Android பீம் பரிமாற்ற நிலையைப் பெறுதல்" "நடப்பு Android பீம் பரிமாற்றங்கள் குறித்த தகவலைப் பெற, பயன்பாட்டை அனுமதிக்கிறது" "DRM சான்றிதழ்களை அகற்று" "DRM சான்றிதழ்களை அகற்ற, பயன்பாட்டை அனுமதிக்கிறது. சாதாரண பயன்பாடுகளுக்கு எப்போதுமே தேவைப்படாது." @@ -1091,11 +1091,11 @@ "மீட்டமைக்கிறது…" "செருகப்படவில்லை" "பொருந்தும் செயல்பாடுகள் கண்டறியப்படவில்லை." - "மீடியா அவுட்புட்டை வழிசெலுத்துதல்" + "மீடியா அவுட்புட்டை ரூட் செய்தல்" "மீடியாவைப் பிற வெளிப்புறச் சாதனங்களுக்கு வெளியீடாக வழிகாட்ட பயன்பாட்டை அனுமதிக்கிறது." - "நிறுவல் அமர்வுகளைப் படிக்கலாம்" + "நிறுவல் அமர்வுகளைப் படித்தல்" "நிறுவல் அமர்வுகளைப் படிக்க, பயன்பாட்டை அனுமதிக்கிறது. இது செயல்படும் தொகுப்பு நிறுவல்களைப் பற்றிய விவரங்களைப் பார்க்க அனுமதிக்கிறது." - "தொகுப்புகளின் நிறுவலைக் கோருதல்" + "நிறுவல் தொகுப்புகளைக் கோருதல்" "தொகுப்புகளின் நிறுவலைக் கோர, பயன்பாட்டை அனுமதிக்கும்." "அளவை மாற்றும் கட்டுப்பாடுகளுக்கு இருமுறை தொடவும்" "விட்ஜெட்டைச் சேர்க்க முடியவில்லை." diff --git a/core/res/res/values-te-rIN-watch/strings.xml b/core/res/res/values-te-rIN-watch/strings.xml index 6b4b900197cec..f729eaa8dcfb3 100644 --- a/core/res/res/values-te-rIN-watch/strings.xml +++ b/core/res/res/values-te-rIN-watch/strings.xml @@ -21,4 +21,5 @@ "%2$dలో %1$dవ అనువర్తనం." + "సెన్సార్‌లు" diff --git a/core/res/res/values-te-rIN/cm_strings.xml b/core/res/res/values-te-rIN/cm_strings.xml new file mode 100644 index 0000000000000..6200a30b806d2 --- /dev/null +++ b/core/res/res/values-te-rIN/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + స్క్రీన్‌షాట్ + + రక్షిత SMSను స్వీకరించుము + + ఇన్కమింగ్ రక్షిత SMSను అందుకునేందుకు అనువర్తనానికి అనుమతినిస్తుంది. + + రక్షిత SMS జాబితాను సవరించుము + + రక్షిత SMS చిరునామా జాబితాను సవరించేందుకు అనువర్తనానికి అనుమతినిస్తుంది. + + భద్రత + + పరికరం యొక్క భద్రతా సమాచారానికి సంబంధించిన అనుమతులు. + + ఫోన్ యొక్క ఆమోదం కాని జాబితాను చదువుము + + ఇన్కమింగ్ కాల్స్ లేదా మేసేజుల కొరకు నిరోధించబడిన ఫోన్ నంబర్లను గూర్చిన సమాచారాన్ని చదివేందుకు అనువర్తనానికి అనుమతినిస్తుంది. + + ఫోన్ యొక్క ఆమోదం కాని జాబితాను మార్చుము + + ఇన్కమింగ్ కాల్స్ లేదా మేసేజుల కొరకు నిరోధించబడిన ఫోన్ నంబర్లను మార్చేందుకు అనువర్తనానికి అనుమతినిస్తుంది. + + కీగార్డ్ వాల్ పేపరును సెట్ చేయండి + + లాక్ స్క్రీన్ వాల్ పేపరును మార్చడానికి ఒక అనువర్తనానికి అనుమతినిస్తుంది. + + రీబూట్ + + ప్రస్తుత + + + రీబూట్ + + పునరుద్ధరణ + + బూట్‌లోడర్ + + డౌన్‌లోడ్ + + మరలా సాఫ్ట్ బూట్ + + రీబూట్ + + మీ టాబ్లెట్ మరలా బూట్ అవుతుంది. + మీ ఫోన్ మరలా బూట్ అవుతుంది. + + రీబూటింగ్\u2026 + + అనువర్తనం నిర్వీర్యం చేయబడింది + + ADB ఓవర్ నెట్వర్క్ ప్రారంభించబడింది + + ADB ఓవర్ USB మరియు నెట్వర్క్ ప్రారంభించబడ్డాయి + + డీబగ్గింగ్ నిలిపివేయడానికి తాకండి + + ADB - %1$s + USB మరియు నెట్వర్క్ + USB + నెట్‌వర్క్ + + ప్రోగ్రాం ప్రారంభానికి అవరోధం కలిగించుము + + %s ఇన్స్టాల్ చేయబడలేదు + + ప్రాధాన్యత + ఏదీ లేదు + + SIM సభ్యత్వ మార్పు కారణంగా Wi-Fi హాట్ స్పాట్ నిలిపివేయబడింది + + Wi-Fi ను ఆఫ్ చేయుము + + గోప్యతా సంరక్షణను ప్రారంభించుము/నిలిపివేయుము + ఇంకొక అనువర్తనం గోప్యతా సంరక్షణతో పనిచేస్తుందా అనే దానిని మార్చడానికి అనువర్తనానికి అనుమతినిస్తుంది. అనువర్తనం గోప్యతా సంరక్షణతో పనిచేస్తున్నప్పుడు, పరిచయాలు, కాల్ లాగులు, లేదా మెసేజులు వంటి వ్యక్తిగత డేటాకు అది ప్రాప్యతను కలిగి ఉండదు. + గోప్యతా సంరక్షణ క్రియాశీలం + %1$s వ్యక్తిగత డేటాకు ప్రాప్యతను కలిగి ఉండదు + గోప్యత రక్షణ + %2$s ను చేయడానికి %1$s ఇష్టపడుతుంది. + + నా ఎంపికను గుర్తుంచుకో + + కెమెరాను ప్రాప్యత చేయుము + మీ స్థానానికి ప్రాప్యత చేయుము + మీ నోటిఫికేషన్లను చదువుము + ఒక VPNను క్రియాశీలం చేయుము + పవర్ అప్ వద్ద ప్రారంభించుము + మీ కాల్ లాగును తొలిగించుము + మీ పరిచయాలను తొలిగించుము + మీ MMS మెసేజులను తొలిగించుము + మీ SMS మెసేజులను తొలిగించుము + పైన గవాక్షాలను గీయండి + అనువర్తన వినియోగ గణాంకాలను పొందుము + మీ పరికరాన్ని చేతనంగా ఉంచండి + ఫోన్ కాల్ చేయుము + క్యాలెండరును నవీకరించుము + కాల్ లాగును నవీకరించుము + క్లిప్ బోర్డును నవీకరించుము + మీ పరిచయాలను నవీకరించుము + సిస్టమ్ అమరికలను నవీకరించుము + మైక్రోఫోనును మ్యూట్/అన్ మ్యూట్ చేయుము + ఆడియోను ప్లే చేయుము + నోటిఫికేషనును పోస్ట్ చేయుము + మీడియాను ప్రదర్శించుము + మీ కాలెండరును చదువుము + కాల్ లాగును చదువుము + క్లిప్ బోర్డును చదువుము + మీ పరిచయాలను చదవడం + మీ యొక్క MMS మెసేజులను చదువుము + మీ యొక్క SMS మెసేజులను చదువుము + SMS మెసేజ్ అందుకొనుము + ఆడియో రికార్డ్ చేయడం + MMS మెసేజును పంపుము + SMS మెసేజును పంపుము + పవర్ అప్ వద్ద ప్రారంభించుము + టోస్ట్ మెసేజులను ప్రదర్శించుము + బ్లూటూతును ద్విక్రియం చేయుము + మొబైల్ డేటాను ద్విక్రియం చేయుము + NFCను ద్విక్రియ చేయుము + Wi-Fiను ద్విక్రియ చేయుము + అలారం శబ్దాన్ని నియంత్రించుము + ఆడియో కేంద్రీకరణను నియంత్రించుము + బ్లూటూత్ శబ్దాన్ని నియంత్రించుము + మాస్టర్ శబ్దాన్ని నియంత్రించుము + మీడియా బటన్లను ఉపయోగించుము + మీడియా శబ్దాన్ని నియంత్రించుము + నోటిఫికేషన్ శబ్దాన్ని నియంత్రించుము + రింగ్ టోన్ శబ్దాన్ని నియంత్రించుము + చేతి సంబంధ అభిప్రాయాన్ని ఉపయోగించుము + స్వర కాల్ శబ్దాన్ని నియంత్రించుము + MMS మెసేజును వ్రాయుము + SMS మెసేజును వ్రాయుము + వేలిముద్రను ఉపయోగించుము + వాయిస్ మెయిల్‌ను జోడించడం + ఫోన్ స్థితి యొక్క ప్రాప్తి + Wi-Fi నెట్వర్క్స్ స్కాన్ చేయి + వాల్పేపర్ మార్చు + సహాయక నిర్మాణంను ఉపయోగించు + స్క్రీన్‌షాట్ తీయుము + శరీర సెన్సార్లను ఉపయోగించుము + గడి ప్ర్రసారాలను చదువుము + మీ స్థానాన్ని నకిలీ చేయండి + బాహ్య నిల్వను చదువుము + బాహ్య నిల్వకు వ్రాయుము + తెరను ఆన్ చేయుము + మీ పరికరం యొక్క ఖాతాలు పొందుము + Wi-Fi స్థితిని మార్చు + మూలాంశ ప్రాప్యతను పొందుము + + ఈ స్క్రీనును అన్పిన్ చేయడానికి, బ్యాక్ బటనును తాకండి మరియు పట్టుకోండి. + + ఎటువంటి పరికరం అనుసంధానించబడలేదు + %1$s అనుసంధానించబడిన పరికరం + %1$s అనుసంధానించబడిన పరికరాలు + + + + కార్యకలాపం ప్రయోగించడం నిరోధించబడింది + %1$S ప్రయోగించడం నుండి సంరక్షించబడింది అనువర్తనాన్ని అధీకృతం చేయడం మరియు ప్రయోగించడం నుండి సంరక్షించబడింది. + + బ్యాటరీ పూర్తిగా ఛార్జ్ + బ్యాటరీ దీర్ఘాయువు మెరుగు ఛార్జర్ నుండి మీ పరికరాన్ని డిస్కనెక్ట్ చేయండి. + + బ్యాటరీ గణాంకాలను రీసెట్ చేయడం + + ప్రస్తుత తక్కువ-స్థాయి బ్యాటరీ నిల్వ డేటాను రీసెట్ చేసేందుకు అప్లికేషనుకు అనుమతినిస్తుంది. + + diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml index ff639a9de0a89..70a3e5a423400 100644 --- a/core/res/res/values-te-rIN/strings.xml +++ b/core/res/res/values-te-rIN/strings.xml @@ -254,7 +254,7 @@ "క్రెడిట్ కార్డు నంబర్‌లు మరియు పాస్‌వర్డ్‌ల వంటి వ్యక్తిగత డేటాను కలిగి ఉంటుంది." "స్థితి బార్‌ను నిలిపివేయడం లేదా సవరించడం" "స్థితి బార్‌ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." - "స్థితి పట్టీ" + "స్థితి పట్టీగా ఉండటం" "స్థితి బార్‌ ఉండేలా చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "స్థితి పట్టీని విస్తరింపజేయడం/కుదించడం" "స్థితి బార్‌ను విస్తరింపజేయడానికి లేదా కుదించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." @@ -282,7 +282,7 @@ "WAP సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీకు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది." "అమలవుతున్న అనువర్తనాలను పునరుద్ధరించడం" "ప్రస్తుతం మరియు ఇటీవల అమలవుతున్న విధుల గురించి వివరణాత్మక సమాచారాన్ని తిరిగి పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది పరికరంలో ఉపయోగించబడిన అనువర్తనాల గురించి సమాచారాన్ని కనుగొనడానికి అనువర్తనాన్ని అనుమతించవచ్చు." - "ప్రొఫైల్ మరియు పరికరం యజమానులను నిర్వహించడానికి అనుమతి" + "ప్రొఫైల్ మరియు పరికర యజమానులను నిర్వహించడం" "ప్రొఫైల్ యజమానులను మరియు పరికరం యజమానిని సెట్ చేయడానికి అనువర్తనాలను అనుమతిస్తుంది." "అమలవుతున్న అనువర్తనాలను మళ్లీ క్రమం చేయడం" "విధులను ముందుకు మరియు నేపథ్యానికి తరలించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. అనువర్తనం మీ ప్రమేయం లేకుండానే దీన్ని చేయవచ్చు." @@ -324,7 +324,7 @@ "ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్‌ల గురించిన డేటాతో సహా మీ టాబ్లెట్ యొక్క కాల్ లాగ్‌ను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ కాల్ లాగ్‌ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు." "ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్‌లకు సంబంధించిన డేటాతో సహా మీ టీవీ కాల్ లాగ్‌ను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ కాల్ లాగ్‌ను తీసివేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు." "ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్‌ల గురించిన డేటాతో సహా మీ ఫోన్ యొక్క కాల్ లాగ్‌ను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ కాల్ లాగ్‌ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు." - "శరీర సెన్సార్‌లు (హృదయ స్పందన మానిటర్‌లు వంటివి)" + "శరీర సెన్సార్‌లను (గుండె స్పందన రేటు మానిటర్‌ల వంటివి) ప్రాప్యత చేయడం" "మీ శారీరక పరిస్థితిని అనగా మీ గుండె స్పందన రేటు వంటి వాటిని పర్యవేక్షించే సెన్సార్‌ల నుండి డేటాను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "క్యాలెండర్ ఈవెంట్‌లతో పాటు గోప్యమైన సమాచారాన్ని చదవడం" "స్నేహితులు లేదా సహోద్యోగులకు సంబంధించిన ఈవెంట్‌లతో సహా మీ టాబ్లెట్‌లో నిల్వ చేయబడిన అన్ని క్యాలెండర్ ఈవెంట్‌లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది గోప్యత లేదా తీవ్రతతో సంబంధం లేకుండా మీ క్యాలెండర్ డేటాను భాగస్వామ్యం చేయడానికి లేదా సేవ్ చేయడానికి అనువర్తనాన్ని అనుమతించవచ్చు." @@ -336,15 +336,15 @@ "స్నేహితులు లేదా సహోద్యోగులకు సంబంధించిన ఈవెంట్‌లతో సహా మీరు మీ ఫోన్‌లో సవరించగల ఈవెంట్‌లను జోడించడానికి, తీసివేయడానికి, మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా కనిపించే రీతిలో సందేశాలను పంపడానికి లేదా యజమానికి తెలియకుండానే ఈవెంట్‌లను సవరించడానికి అనువర్తనాన్ని అనుమతించవచ్చు." "అదనపు స్థాన ప్రదాత ఆదేశాలను ప్రాప్యత చేయడం" "అదనపు స్థాన ప్రదాత ఆదేశాలను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది GPS లేదా ఇతర స్థాన మూలాల నిర్వహణలో అనువర్తనం ప్రమేయం ఉండేలా అనుమతించవచ్చు." - "ఖచ్చితమైన స్థానం (GPS మరియు నెట్‌వర్క్-ఆధారితం)" + "ఖచ్చితమైన స్థానాన్ని (GPS మరియు నెట్‌వర్క్-ఆధారితం) ప్రాప్యత చేయడం" "గ్లోబల్ పొజిషనింగ్ సిస్టమ్ (GPS) లేదా సెల్ టవర్‌లు మరియు Wi-Fi వంటి నెట్‌వర్క్ స్థాన మూలాలను ఉపయోగించి మీ ఖచ్చితమైన స్థానాన్ని పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ స్థాన సేవలను అనువర్తనం ఉపయోగించడానికి తప్పనిసరిగా ప్రారంభించబడి ఉండాలి మరియు మీ పరికరానికి అందుబాటులో ఉండాలి. అనువర్తనాలు మీరు ఉన్న ప్రాంతాన్ని కనుగొనడానికి దీన్ని ఉపయోగించవచ్చు మరియు అదనపు బ్యాటరీ శక్తిని వినియోగించవచ్చు." - "సామీప్య స్థానం (నెట్‌వర్క్-ఆధారితం)" + "ఇంచుమించు స్థానాన్ని (నెట్‌వర్క్-ఆధారితం) ప్రాప్యత చేయడం" "మీ సామీప్య స్థానాన్ని పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సెల్ టవర్‌లు మరియు Wi-Fi వంటి నెట్‌వర్క్ స్థాన మూలాలను ఉపయోగించి స్థాన సేవల ద్వారా ఈ స్థానం కనుగొనబడుతుంది. ఈ స్థాన సేవలను అనువర్తనం ఉపయోగించడానికి తప్పనిసరిగా ప్రారంభించబడి ఉండాలి మరియు మీ పరికరానికి అందుబాటులో ఉండాలి. అనువర్తనాలు మీరు ఉన్న ప్రాంతాన్ని సుమారుగా గుర్తించడానికి దీన్ని ఉపయోగించవచ్చు." "మీ ఆడియో సెట్టింగ్‌లను మార్చడం" "వాల్యూమ్ మరియు అవుట్‌పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్‌లను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "ఆడియోను రికార్డ్ చేయడం" "మైక్రోఫోన్‌తో ఆడియోను రికార్డ్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీ నిర్ధారణ లేకుండానే ఎప్పుడైనా ఆడియోను రికార్డ్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." - "సిమ్ కమ్యూనికేషన్" + "SIMకి ఆదేశాలను పంపడం" "సిమ్‌కు ఆదేశాలను పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది చాలా ప్రమాదకరం." "చిత్రాలు మరియు వీడియోలు తీయడం" "కెమెరాతో చిత్రాలు మరియు వీడియోలను తీయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీ నిర్ధారణ లేకుండానే ఎప్పుడైనా కెమెరాను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." @@ -382,7 +382,7 @@ "ఫోన్‌కు తెలిసిన ఖాతాల జాబితాను పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీనిలో మీరు ఇన్‌స్టాల్ చేసిన అనువర్తనాల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు." "నెట్‌వర్క్ కనెక్షన్‌లను వీక్షించడం" "ఏ నెట్‌వర్క్‌లు ఉన్నాయి మరియు కనెక్ట్ చేయబడ్డాయి వంటి నెట్‌వర్క్ కనెక్షన్‌ల గురించి సమాచారాన్ని వీక్షించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." - "పూర్తి నెట్‌వర్క్ ప్రాప్యత" + "పూర్తి నెట్‌వర్క్ ప్రాప్యతను కలిగి ఉండటం" "నెట్‌వర్క్ సాకెట్‌లను సృష్టించడానికి మరియు అనుకూల నెట్‌వర్క్ ప్రోటోకాల్‌లను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. బ్రౌజర్ మరియు ఇతర అనువర్తనాలు ఇంటర్నెట్‌కు డేటా పంపడానికి మార్గాలను అందిస్తాయి, కనుక ఇంటర్నెట్‌కు డేటా పంపడానికి ఈ అనుమతి అవసరం లేదు." "నెట్‌వర్క్ కనెక్టివిటీని మార్చడం" "నెట్‌వర్క్ కనెక్టివిటీ యొక్క స్థితిని మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది." @@ -402,7 +402,7 @@ "స్థానిక బ్లూటూత్ ఫోన్‌ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొనడానికి మరియు జత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "WiMAXకు కనెక్ట్ చేయడం మరియు దాని నుండి డిస్‌కనెక్ట్ చేయడం" "Wi-Fi ప్రారంభించబడిందా, లేదా మరియు కనెక్ట్ చేయబడిన WiMAX నెట్‌వర్క్‌ల గురించి సమాచారాన్ని కనుగొనడానికి అనువర్తనాన్ని అనుమతిస్తుంది." - "WiMAX స్థితిని మార్చండి" + "WiMAX స్థితిని మార్చడం" "WiMAX నెట్‌వర్క్‌లకు టాబ్లెట్‌ను కనెక్ట్ చేయడానికి మరియు వాటి నుండి టాబ్లెట్‌ను డిస్‌కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "టీవీని WiMAX నెట్‌వర్క్‌లకు కనెక్ట్ చేయడానికి మరియు వాటి నుండి టీవీని డిస్‌కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "WiMAX నెట్‌వర్క్‌లకు ఫోన్‌ను కనెక్ట్ చేయడానికి మరియు వాటి నుండి ఫోన్‌ను డిస్‌కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది." @@ -485,7 +485,7 @@ "టచ్ స్క్రీన్ యొక్క క్రమాంకన పరామితులను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు." "DRM ప్రమాణపత్రాలను ప్రాప్యత చేయడం" "DRM ప్రమాణపత్రాలను కేటాయించడానికి మరియు ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు." - "Android Beam బదిలీ స్థితిని స్వీకరించండి" + "Android Beam బదిలీ స్థితిని స్వీకరించడం" "ప్రస్తుత Android Beam బదిలీలకు సంబంధించిన సమాచారాన్ని స్వీకరించడానికి ఈ అనువర్తనాన్ని అనుమతిస్తుంది" "DRM ప్రమాణపత్రాలను తీసివేయడం" "DRM ప్రమాణపత్రాలను తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు." @@ -1091,11 +1091,11 @@ "ఫార్మాట్ చేస్తోంది..." "చొప్పించబడలేదు" "సరిపోలే కార్యాచరణలు కనుగొనబడలేదు." - "ప్రసార మాధ్యమ అవుట్‌పుట్‌ను మళ్లించడం" + "మీడియా అవుట్‌పుట్‌ను మళ్లించడం" "మీడియా అవుట్‌పుట్‌ను ఇతర బాహ్య పరికరాలకు మళ్లించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." - "ఇన్‌స్టాల్ సెషన్‌లను చదవడం" + "ఇన్‌స్టాల్ సెషన్‌లను చదవడం" "ఇన్‌స్టాల్ సెషన్‌లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది సక్రియ ప్యాకేజీ ఇన్‌స్టాలేషన్‌ల గురించి వివరాలను చూడటానికి అనువర్తనాన్ని అనుమతిస్తుంది." - "ఇన్‌స్టాల్ ప్యాకేజీలను అభ్యర్థించడానికి అనుమతి" + "ఇన్‌స్టాల్ ప్యాకేజీలను అభ్యర్థించడం" "ప్యాకేజీల ఇన్‌స్టాలేషన్ అభ్యర్థించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "జూమ్ నియంత్రణ కోసం రెండుసార్లు తాకండి" "విడ్జెట్‌ను జోడించడం సాధ్యపడలేదు." diff --git a/core/res/res/values-th-watch/strings.xml b/core/res/res/values-th-watch/strings.xml index 568b083b02f84..26f1f02d8c11c 100644 --- a/core/res/res/values-th-watch/strings.xml +++ b/core/res/res/values-th-watch/strings.xml @@ -21,4 +21,5 @@ "แอป %1$d จาก %2$d แอป" + "เซ็นเซอร์" diff --git a/core/res/res/values-th/cm_strings.xml b/core/res/res/values-th/cm_strings.xml new file mode 100644 index 0000000000000..cd6f80ec8d093 --- /dev/null +++ b/core/res/res/values-th/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + ถ่ายภาพหน้าจอ + + รับ SMS ที่ได้รับการปกป้อง + + อนุญาตให้แอปรับ SMS ที่ได้รับการปกป้อง + + แก้ไขรายการ SMS ที่ได้รับการปกป้อง + + อนุญาตให้แอปแก้ไขรายการที่อยู่ SMS ที่ได้รับการปกป้อง + + ความปลอดภัย + + สิทธิ์ที่เกี่ยวข้องกับข้อมูลความปลอดภัยของอุปกรณ์ + + อ่านรายชื่อบัญชีดำ + + อนุญาตให้แอปอ่านข้อมูลหมายเลขโทรศัพท์ที่ถูกบล็อคสำหรับสายการโทรเข้าหรือข้อความ + + เปลี่ยนรายชื่อบัญชีดำ + + อนุญาตให้แอปเปลี่ยนหมายเลขที่ถูกบล็อคสำหรับสายการโทรเข้าหรือข้อความ + + ตั้งภาพล็อคหน้าจอ + + อนุญาตให้แอปเปลี่ยนภาพล็อคหน้าจอได้ + + เริ่มระบบใหม่ + + ปัจจุบัน + + + เริ่มระบบใหม่ + + Recovery + + Bootloader + + ดาวน์โหลด + + เริ่มระบบแบบซอฟต์รีบู๊ต + + เริ่มระบบใหม่ + + แท็บเล็ตของคุณจะเริ่มระบบใหม่ + โทรศัพท์ของคุณจะเริ่มระบบใหม่ + + กำลังเริ่มระบบใหม่\u2026 + + ปิดแอป + + ADB บนเครือข่ายถูกเปิดใช้งาน + + ADB บน USB และ & เครือข่ายถูกเปิดใช้งาน + + แตะเพื่อปิดการแก้ไขข้อบกพร่อง + + ADB - %1$s + USB & เครือข่าย + USB + เครือข่าย + + ขัดขวางการเปิดแอป + + %s ไม่ถูกติดตั้ง + + ระดับความสำคัญ + ไม่มี + + ปิดฮอตสปอต Wi-Fi เนื่องจากการเปลี่ยนแปลงการสมัครซิมการ์ด + + ปิด Wi-Fi + + เปิดหรือปิดการป้องกันความเป็นส่วนตัว + อนุญาตให้แอปเปลี่ยนแปลงไม่ว่าแอปอื่นทำงานโดยใช้การป้องกันความเป็นส่วนตัวหรือไม่ก็ตาม เมื่อแอปกำลังทำงานโดยใช้การป้องกันความเป็นส่วนตัว แอปจะไม่สามารถเข้าถึงข้อมูลส่วนบุคคล เช่น รายชื่อติดต่อ ประวัติการโทร หรือข้อความได้ + การป้องกันความเป็นส่วนตัวทำงาน + %1$s จะไม่สามารถเข้าถึงข้อมูลส่วนตัวได้ + รักษาความเป็นส่วนตัว + %1$s ต้องการ %2$s + + จำตัวเลือกของฉัน + + เข้าถึงกล้อง + เข้าถึงตำแหน่งที่ตั้งของคุณ + อ่านการแจ้งเตือน + เปิดใช้งาน VPN + เริ่มเมื่อเปิดเครื่อง + ลบประวัติการโทรของคุณ + ลบรายชื่อติดต่อของคุณ + ลบข้อความ MMS ของคุณ + ลบข้อความ SMS ของคุณ + วาดหน้าต่างทับ + รับสถิติการใช้งานแอป + เปิดจอค้าง + โทรออก + อัปเดตปฏิทิน + อัปเดตประวัติการโทร + ปรับแต่งคลิปบอร์ด + อัปเดตรายชื่อติดต่อ + อัปเดตการตั้งค่าระบบ + ปิด/เปิด ไมโครโฟน + เล่นเสียง + โพสต์การแจ้งเตือน + สื่อโครงการ + อ่านปฏิทิน + อ่านประวัติการโทร + อ่านคลิปบอร์ด + อ่านรายชื่อติดต่อ + อ่านข้อความ MMS + อ่านข้อความ SMS + รับข้อความ SMS + บันทึกเสียง + ส่งข้อความ MMS + ส่งข้อความ SMS + เริ่มเมื่อเปิดเครื่อง + แสดงแถบข้อความ + สลับบลูทูธ + สลับข้อมูลโทรศัพท์มือถือ + สลับ NFC + สลับ WiFi + ควบคุมระดับเสียงนาฬิกาปลุก + ควบคุมการโฟกัสเสียง + ควบคุมระดับเสียงบลูทูธ + ควบคุมระดับเสียงหลัก + ใช้ปุ่มสื่อ + ควบคุมระดับเสียงสื่อ + ควบคุมระดับเสียงแจ้งเตือน + ควบคุมระดับเสียงเรียกเข้า + ใช้สั่นเมื่อแตะ + ควบคุมเสียงสนทนา + เขียนข้อความ MMS + เขียนข้อความ SMS + ใช้ลายนิ้วมือ + เพิ่มการฝากข้อความ + เข้าถึงสถานะโทรศัพท์ + ค้นหาเครือข่าย Wi-Fi + เปลี่ยนรูปพื้นหลัง + ใช้โครงสร้างช่วย + ถ่ายภาพหน้าจอ + ใช้เซนเซอร์ตรวจร่างกาย + อ่านการติดต่อเครือข่าย + จำลองที่ตั้ง + อ่านที่เก็บข้อมูลภายนอก + เขียนที่เก็บข้อมูลภายนอก + เปิดหน้าจอ + เข้าถึงบัญชีของอุปกรณ์ + เปลี่ยนแปลงสถานะ Wi-Fi + รับสิทธิผู้ดูแลระบบ + + เพื่อยกเลิกการปักหมุดหน้าจอนี้ กดปุ่มกลับค้างไว้ + + ไม่มีอุปกรณ์เชื่อมต่อ + %1$s อุปกรณ์เชื่อมต่ออยู่ + %1$s อุปกรณ์เชื่อมต่ออยู่ + + + + การเปิดกิจจรรมถูกบล็อก + %1$s ถูกป้องกันจากการเปิด แตะเพื่อยืนยันและเปิดแอป + + แบตเตอรี่เต็มแล้ว + ถอดอุปกรณ์ของคุณออกจากที่ชาร์จเพื่อเพิ่มอายุการใช้งานของแบตเตอรี่ + + รีเซ็ตสถิติแบตเตอรี่ + + อนุญาตให้แอปพลิเคชันรีเซ็ตข้อมูลการใช้แบตเตอรี่ระดับต่ำในปัจจุบัน + + มีการเปลี่ยนซิมการ์ด + แตะเพื่อตั้งค่าการกำหนดค่าเริ่มต้นของ SIM การ์ด + diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 2db50ee51c7f3..ad847e352cbc3 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -254,7 +254,7 @@ "รวมถึงข้อมูลส่วนบุคคล เช่น หมายเลขบัตรเครดิตและรหัสผ่าน" "ปิดการใช้งานหรือแก้ไขแถบสถานะ" "อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก" - "แถบสถานะ" + "เป็นแถบสถานะ" "อนุญาตให้แอปพลิเคชันเป็นแถบสถานะ" "ขยาย/ยุบแถบสถานะ" "อนุญาตให้แอปพลิเคชันขยายหรือยุบแถบสถานะ" @@ -282,7 +282,7 @@ "อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ WAP การอนุญาตนี้รวมถึงความสามารถในการตรวจสอบหรือลบข้อความที่ส่งมาให้คุณโดยไม่ต้องแสดงให้คุณเห็น" "เรียกแอปพลิเคชันที่ทำงานอยู่" "อนุญาตให้แอปพลิเคชันเรียกดูข้อมูลเกี่ยวกับงานที่ดำเนินการอยู่ในขณะนี้และเมื่อเร็วๆ นี้ ซึ่งอาจทำให้แอปพลิเคชันสามารถค้นข้อมูลได้ว่าอุปกรณ์นี้ใช้แอปพลิเคชันใดบ้าง" - "จัดการเจ้าของโปรไฟล์และอุปกรณ์" + "จัดการเจ้าของโปรไฟล์และอุปกรณ์" "อนุญาตให้แอปตั้งค่าเจ้าของโปรไฟล์และเจ้าของอุปกรณ์" "จัดลำดับแอปพลิเคชันที่ทำงานอยู่ใหม่" "อนุญาตให้แอปพลิเคชันย้ายงานไปยังส่วนหน้าและพื้นหลัง แอปพลิเคชันอาจดำเนินการโดยไม่รอคำสั่งจากคุณ" @@ -324,7 +324,7 @@ "อนุญาตให้แอปแก้ไขประวัติการโทรจากแท็บเล็ตของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อลบหรือแก้ไขประวัติการโทรของคุณ" "อนุญาตให้แอปแก้ไขประวัติการโทรของทีวี รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและโทรออก แอปที่เป็นอันตรายอาจใช้สิทธิ์นี้เพื่อลบหรือแก้ไขประวัติการโทรได้" "อนุญาตให้แอปแก้ไขประวัติการโทรจากโทรศัพท์ของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อลบหรือแก้ไขประวัติการโทรของคุณ" - "เซ็นเซอร์ร่างกาย (เช่น วัดอัตราการเต้นของหัวใจ)" + "เข้าถึงเซ็นเซอร์ร่างกาย (เช่น ตัววัดอัตราการเต้นของหัวใจ)" "อนุญาตให้แอปเข้าถึงข้อมูลจากเซ็นเซอร์ที่ตรวจสอบสภาพทางกายภาพ เช่น อัตราการเต้นของหัวใจ" "อ่านกิจกรรมบนปฏิทินรวมถึงข้อมูลที่เป็นความลับ" "อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในแท็บเล็ตของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแชร์หรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม" @@ -336,15 +336,15 @@ "อนุญาตให้แอปพลิเคชันเพิ่ม ลบ เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในโทรศัพท์ได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ" "เข้าถึงคำสั่งของโปรแกรมแจ้งตำแหน่งพิเศษ" "อนุญาตให้แอปเข้าถึงคำสั่งของผู้ให้บริการตำแหน่งเพิ่มเติม ซึ่งอาจทำให้แอปสามารถแทรกแซงการทำงานของ GPS หรือต้นทางของตำแหน่งอื่นๆ ได้" - "ตำแหน่งที่แม่นยำ (อิงตาม GPS และเครือข่าย)" + "เข้าถึงตำแหน่งที่แม่นยำ (อิงจาก GPS และเครือข่าย)" "อนุญาตให้แอปพลิเคชันรับตำแหน่งที่แม่นยำของคุณโดยใช้ Global Positioning System (GPS) หรือต้นทางของตำแหน่งในเครือข่ายอย่างเช่น เสาสัญญาณมือถือ และ WiFi บริการตำแหน่งเหล่านี้จะต้องถูกเปิดใช้งานอยู่สำหรับอุปกรณ์ของคุณเพื่อให้แอปพลิเคชันสามารถใช้งานได้ แอปพลิเคชันสามารถใช้บริการตำแหน่งนี้เพื่อตัดสินว่าคุณอยู่ ณ จุดใด และอาจใช้พลังงานแบตเตอรี่มากกว่าปกติ" - "ตำแหน่งโดยประมาณ (อิงตามเครือข่าย)" + "เข้าถึงตำแหน่งโดยประมาณ (อิงจากเครือข่าย)" "อนุญาตให้แอปพลิเคชันรับตำแหน่งโดยประมาณของคุณ บริการตำแหน่งจะดึงตำแหน่งขึ้นมาโดยใช้ต้นทางของตำแหน่งอย่างเช่น เสาสัญญาณมือถือ และ WiFi บริการตำแหน่งเหล่านี้จะต้องถูกเปิดใช้งานอยู่สำหรับอุปกรณ์ของคุณเพื่อให้แอปพลิเคชันสามารถใช้งานได้ แอปพลิเคชันสามารถใช้บริการตำแหน่งนี้เพื่อตัดสินอย่างคร่าวๆ ว่าคุณอยู่ ณ จุดใด" "เปลี่ยนการตั้งค่าเสียงของคุณ" "อนุญาตให้แอปพลิเคชันปรับเปลี่ยนการตั้งค่าเสียงทั้งหมดได้ เช่น ระดับเสียงและลำโพงที่จะใช้งาน" "บันทึกเสียง" "อนุญาตให้แอปพลิเคชันบันทึกเสียงด้วยไมโครโฟน การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกเสียงได้ทุกเมื่อโดยไม่ต้องรอการยืนยันจากคุณ" - "การสื่อสารกับ SIM" + "ส่งคำสั่งไปยังซิม" "อนุญาตให้แอปส่งคำสั่งไปยัง SIM ซึ่งอันตรายมาก" "ถ่ายภาพและวิดีโอ" "อนุญาตให้แอปพลิเคชันถ่ายภาพและวิดีโอด้วยกล้องถ่ายรูปนี้ การอนุญาตนี้จะทำให้แอปพลิเคชันสามารถใช้กล้องถ่ายรูปได้ทุกเมื่อโดยไม่ต้องรอการยืนยันจากคุณ" @@ -382,7 +382,7 @@ "อนุญาตให้แอปพลิเคชันรับรายการบัญชีที่โทรศัพท์รู้จัก ซึ่งอาจรวมถึงบัญชีใดๆ ก็ตามที่แอปพลิเคชันซึ่งคุณติดตั้งไว้ได้สร้างขึ้น" "ดูการเชื่อมต่อเครือข่าย" "อนุญาตให้แอปพลิเคชันดูข้อมูลเกี่ยวกับการเชื่อมต่อเครือข่าย เช่น มีเครือข่ายใดอยู่บ้าง และมีการเชื่อมต่อเครือข่ายใด" - "การเข้าถึงเครือข่ายเต็มรูปแบบ" + "มีสิทธิ์เข้าถึงเครือข่ายเต็มรูปแบบ" "อนุญาตให้แอปพลิเคชันสร้างซ็อกเก็ตเครือข่ายและใช้โปรโตคอลเครือข่ายที่กำหนดเอง เบราว์เซอร์และแอปพลิเคชันอื่นๆ ให้วิธีการในการส่งข้อมูลไปยังอินเทอร์เน็ต จึงไม่จำเป็นต้องได้รับการอนุญาตนี้เพื่อที่จะส่งข้อมูลไปยังอินเทอร์เน็ต" "เปลี่ยนการเชื่อมต่อเครือข่าย" "อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงสถานะการเชื่อมต่อของเครือข่าย" @@ -402,7 +402,7 @@ "อนุญาตให้แอปพลิเคชันกำหนดค่าโทรศัพท์บลูทูธในตัวเครื่อง ตลอดจนค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล" "เชื่อมต่อและเลิกเชื่อมต่อจาก WiMAX" "อนุญาตให้แอปพลิเคชันตรวจสอบว่า WiMAX เปิดใช้งานอยู่หรือไม่และข้อมูลเกี่ยวกับเครือข่าย WiMAX ใดๆ ที่เชื่อมต่ออยู่" - "เปลี่ยนสถานะของ WiMAX" + "เปลี่ยนสถานะของ WiMAX" "อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อแท็บเล็ตกับเครือข่าย WiMAX" "อนุญาตให้แอปเชื่อมต่อทีวีและยกเลิกการเชื่อมต่อทีวีจากเครือข่าย WiMAX" "อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อโทรศัพท์กับเครือข่าย WiMAX" @@ -485,7 +485,7 @@ "อนุญาตให้แอปสามารถปรับพารามิเตอร์การเทียบมาตรฐานของหน้าจอสัมผัส ไม่ควรใช้สำหรับแอปทั่วไป" "เข้าถึงใบรับรอง DRM" "ช่วยให้แอปพลิเคชันสามารถจัดสรรและใช้ใบรับรอง DRM ได้ ไม่จำเป็นสำหรับแอปปกติทั่วไป" - "รับสถานะการโอน Android Beam" + "รับสถานะการโอน Android Beam" "อนุญาตให้แอปพลิเคชันนี้รับข้อมูลเกี่ยวกับการโอน Android Beam ปัจจุบัน" "นำใบรับรอง DRM ออก" "อนุญาตให้แอปพลิเคชันนำใบรับรอง DRM ออก แอปทั่วไปไม่จำเป็นต้องใช้" @@ -1091,11 +1091,11 @@ "กำลังฟอร์แมต…" "ไม่ได้ใส่ไว้" "ไม่พบกิจกรรมที่ตรงกัน" - "กำหนดเส้นทางเอาต์พุตของสื่อ" + "กำหนดเส้นทางเอาต์พุตของสื่อ" "อนุญาตให้แอปพลิเคชันกำหนดเส้นทางเอาต์พุตของสื่อไปยังอุปกรณ์ภายนอกอื่นๆ" - "อ่านเซสชันการติดตั้ง" + "อ่านเซสชันการติดตั้ง" "อนุญาตให้แอปพลิเคชันอ่านเซสชันการติดตั้ง ซึ่งจะอนุญาตให้อ่านรายละเอียดเกี่ยวกับการติดตั้งแพ็กเกจที่ใช้งาน" - "ขอติดตั้งแพ็กเกจ" + "ขอติดตั้งแพ็กเกจ" "อนุญาตให้แอปพลิเคชันขอการติดตั้งแพ็กเกจ" "แตะสองครั้งเพื่อควบคุมการซูม" "ไม่สามารถเพิ่มวิดเจ็ต" diff --git a/core/res/res/values-tl-watch/strings.xml b/core/res/res/values-tl-watch/strings.xml index bb0dc4bd8cb03..e15d77d077aa6 100644 --- a/core/res/res/values-tl-watch/strings.xml +++ b/core/res/res/values-tl-watch/strings.xml @@ -21,4 +21,5 @@ "App %1$d ng %2$d." + "Mga Sensor" diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 27cd5bb74d498..d9f78d5832e8e 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -254,7 +254,7 @@ "May kasamang personal na data tulad ng mga numero ng credit card at password." "huwag paganahin o baguhin ang status bar" "Pinapayagan ang app na huwag paganahin ang status bar o magdagdag at mag-alis ng mga icon ng system." - "status bar" + "maging status bar" "Pinapayagan ang app na maging status bar." "palawakin/tiklupin ang status bar" "Pinapayagan ang app na palawakin o tiklupin ang status bar." @@ -282,7 +282,7 @@ "Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng WAP. Kabilang sa pahintulot na ito ang kakayahang sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyo nang hindi ipinapakita ang mga ito sa iyo." "bawiin ang tumatakbong apps" "Pinapayagan ang app na kumuha ng impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaari nitong payagan ang app na tumuklas ng impormasyon tungkol sa kung aling mga application ang ginagamit sa device." - "Pamahalaan ang mga may-ari ng profile at device" + "pamahalaan ang mga may-ari ng profile at device" "Nagbibigay-daan sa mga app na itakda ang mga may-ari ng profile at ang may-ari ng device." "muling isaayos ang tumatakbong apps" "Pinapayagan ang app na maglipat ng mga gawain sa foreground at background. Maaari itong gawin ng app nang wala ng iyong input." @@ -324,7 +324,7 @@ "Binibigyan-daan ang app na baguhin ang log ng tawag ng iyong tablet, kabilang ang data tungkol sa mga paparating at papalabas na tawag. Maaari itong gamitin ng nakakahamak na apps upang burahin o baguhin ang iyong log ng tawag." "Binibigyan-daan ang app na baguhin ang log ng tawag ng iyong TV, kabilang ang data tungkol sa mga paparating at papalabas na tawag. Maaari itong gamitin ng mga nakakahamak na app upang burahin o baguhin ang iyong log ng tawag." "Binibigyan-daan ang app na baguhin ang log ng tawag ng iyong telepono, kabilang ang data tungkol sa mga paparating at papalabas na tawag. Maaari itong gamitin ng nakakahamak na apps upang burahin o baguhin ang iyong log ng tawag." - "mga sensor sa katawan (gaya ng mga heart rate monitor)" + "i-access ang mga sensor sa katawan (tulad ng mga monitor ng bilis ng tibok ng puso)" "Pinapayagan ang app na i-access ang data mula sa mga sensor na sumusubaybay sa iyong pisikal na kundisyon, tulad ng iyong heart rate." "magbasa ng mga kaganapan sa kalendaryo kasama ang kumpedensyal na impormasyon" "Pinapayagan ang app na basahin ang lahat ng kaganapan sa kalendaryo na naka-imbak sa iyong tablet, kabilang iyong sa mga kaibigan o katrabaho. Maaari nitong payagan ang app na ibahagi o i-save ang data ng iyong kalendaryo, ano pa man ang katayuan ng pagiging kumpedensyal o sensitibo nito." @@ -336,15 +336,15 @@ "Pinapayagan ang app na magdagdag, mag-alis, magbago ng mga kaganapang maaari mong baguhin sa iyong telepono, kabilang iyong sa mga kaibigan o katrabaho. Maaari nitong payagan ang app na magpadala ng mga mensaheng lumililitaw na mula sa mga may-ari ng kalendaryo, o magbago ng mga kaganapan nang hindi nalalaman ng mga may-ari." "i-access ang mga dagdag na command ng provider ng lokasyon" "Nagbibigay-daan sa app na mag-access ng mga karagdagang command ng provider ng lokasyon. Maaari nitong bigyang-daan ang app na gambalain ang pagpapatakbo ng GPS o ng iba pang mga pinagmulan ng lokasyon." - "tumpak na lokasyon (batay sa GPS at network)" + "i-access ang tumpak na lokasyon (batay sa GPS at network)" "Binibigyang-daan ang app na makuha ang iyong tumpak na lokasyon gamit ang Global Positioning System (GPS) o network ng mga pinagmulan ng lokasyon gaya ng mga cell tower at Wi-Fi. Dapat ay naka-on ang mga serbisyo ng lokasyon na ito at available sa iyong device upang magamit ng app ang mga ito. Maaaring gamitin ito ng apps upang matukoy kung nasaan ka, at maaaring gumamit ng karagdagang power ng baterya." - "tinatayang lokasyon (batay sa network)" + "i-access ang tinatantyang lokasyon (batay sa network)" "Binibigyang-daan ang app na makuha ang iyong tinatayang lokasyon. Ang lokasyong ito ay nagmula ng mga serbisyo ng lokasyon na gumagamit ng network ng mga pinagmulan ng lokasyon gaya ng mga cell tower at Wi-Fi. Dapat ay naka-on ang mga serbisyo ng lokasyon na ito at available sa iyong device upang magamit ng app ang mga ito. Maaaring gamitin ito ng apps upang matukoy ang tinatayang lokasyon na kinaroroonan mo." "baguhin ang mga setting ng iyong audio" "Pinapayagan ang app na baguhin ang mga pandaigdigang setting ng audio gaya ng volume at kung aling speaker ang ginagamit para sa output." "mag-record ng audio" "Pinapayagan ang app na mag-record ng audio gamit ang mikropono. Pinapayagan ng pahintulot na ito ang app na mag-record ng audio anumang oras nang wala ng iyong kumpirmasyon." - "pag-uusap sa sim" + "magpadala ng mga command sa SIM" "Pinapahintulutang magpadala ang app ng mga command sa SIM. Napakapanganib nito." "kumuha ng mga larawan at video" "Pinapayagan ang app na kumuha ng mga larawan at video gamit ang camera. Pinapayagan ng pahintulot na ito ang app na gamitin ang camera anumang oras nang wala ng iyong kumpirmasyon." @@ -382,7 +382,7 @@ "Pinapayagan ang app na kunin ang listahan ng mga account na alam ng telepono. Maaari itong kabilangan ng anumang mga account na nililikha ng mga application na iyong na-install." "tingnan ang mga koneksyon sa network" "Pinapayagan ang app na tumingin ng impormasyon tungkol sa mga koneksyon ng network gaya ng kung aling mga network ang umiiral at nakakonekta." - "ganap na access sa network" + "magkaroon ng ganap na access sa network" "Pinapayagan ang app na lumikha ng mga network socket at gumamit ng mga custom na network protocol. Nagbibigay ang browser at iba pang mga application ng mga paraan ng pagpapadala ng data sa internet, kaya hindi kinakailangan ang pahintulot na ito upang magpadala ng data sa internet." "baguhin ang pagkakakonekta ng network" "Pinapayagan ang app na baguhin ang katayuan ng pagkakakonekta ng network." @@ -402,7 +402,7 @@ "Pinapayagan ang app na i-configure ang lokal na Bluetooth na telepono, at tumuklas ng at ipares sa mga malayuang device." "kumonekta at magdiskonekta mula sa WiMAX" "Pinapayagan ang app na tukuyin kung pinapagana ang WiMAX at impormasyon tungkol sa anumang mga WiMAX network na nakakonekta." - "Baguhin ang katayuan ng WiMAX" + "baguhin ang katayuan ng WiMAX" "Pinapayagan ang app na ikonekta ang tablet at idiskonekta ang tablet mula sa mga WiMAX network." "Nagbibigay-daan sa app na ikonekta ang TV sa at putulin ang koneksyon ng TV mula sa mga WiMAX network." "Pinapayagan ang app na ikonekta ang telepono at idiskonekta ang telepono mula sa mga WiMAX network." @@ -485,7 +485,7 @@ "Pinapayagan ang app na baguhin ang mga parameter sa pag-calibrate ng touch screen. Hindi dapat kailanganin sa normal na apps." "access sa Mga DRM certificate" "Nagbibigay-daan sa isang application na makapagbigay at gumamit ng mga DRM certficate. Hindi dapat kailanman kailanganin para sa mga normal na app." - "Tanggapin ang status ng paglilipat ng Android Beam" + "tanggapin ang status ng paglilipat ng Android Beam" "Pinapayagan ang application na ito na tumanggap ng impormasyon tungkol sa mga kasalukuyang paglilipat ng Android Beam" "alisin ang mga DRM certificate" "Nagbibigay-daan sa isang application na alisin ang mga DRM certficate. Hindi dapat kailanman kailanganin para sa karaniwang apps." @@ -1091,11 +1091,11 @@ "Fino-format…" "Hindi nakapasok" "Walang nahanap na mga tumutugmang aktibidad." - "I-route ang output ng media" + "iruta ang output ng media" "Pinapayagan ang application na mag-route ng output ng media sa iba pang mga panlabas na device." - "Basahin ang mga session ng pag-install" + "basahin ang mga session ng pag-install" "Pinapayagan ang isang application na magbasa ng mga session ng pag-install. Nagbibigay-daan ito upang makita ang mga detalye tungkol sa mga aktibong pag-install ng package." - "Humiling ng mga package sa pag-install" + "humiling ng mga package sa pag-install" "Pinapayagan ang isang application na hilingin ang pag-install ng mga package." "Pindutin nang dalawang beses para sa pagkontrol ng zoom" "Hindi maidagdag ang widget." diff --git a/core/res/res/values-tr-watch/strings.xml b/core/res/res/values-tr-watch/strings.xml index d9c3923840a42..665268aefa8cb 100644 --- a/core/res/res/values-tr-watch/strings.xml +++ b/core/res/res/values-tr-watch/strings.xml @@ -21,4 +21,5 @@ "Uygulama %1$d / %2$d." + "Sensörler" diff --git a/core/res/res/values-tr/cm_strings.xml b/core/res/res/values-tr/cm_strings.xml new file mode 100644 index 0000000000000..7e315851dda8c --- /dev/null +++ b/core/res/res/values-tr/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Ekran görüntüsü + + korumalı SMS al + + Uygulamaya korumalı bir SMS alma izni verir. + + korumalı SMS listesini değiştir + + Uygulamaya korumalı SMS adres listesini değiştirme izni verir. + + Güvenlik + + Cihaz güvenlik bilgisi ile ilgili izinler. + + telefon kara listesini oku + + Bir uygulamanın gelen çağrıları ya da mesajları engellenmiş telefon numaralarını okumasına izin verir. + + telefon kara listesini değiştir + + Bir uygulamanın gelen çağrıları ya da mesajları engellenmiş telefon numaralarını değiştirmesine izin verir. + + tuş kilidi duvar kağıdını ayarla + + Bir uygulamanın kilit ekranı duvar kağıdını değiştirmesine izin verir. + + Yeniden başlat + + Şimdiki + + + Yeniden başlat + + Kurtarma modu (Recovery) + + Ön yükleyici (Bootloader) + + İndir + + Yazılımsal yeniden başlatma + + Yeniden Başlat + + Tabletiniz yeniden başlatılacak. + Telefonunuz yeniden başlatılacak. + + Yeniden başlatılıyor\u2026 + + Uyg. sonlandırıldı + + Ağ üzerinden ADB etkin + + USB & Ağ üzerinden ADB etkin + + Hata ayıklamayı devre dışı bırakmak için dokunun. + + ADB - %1$s + USB & ağ + USB + + + uygulama başlangıcını önle + + %s yüklü değil + + Öncelik + Yok + + SIM abonelik değişikliği nedeniyle Wi-Fi internet paylaşımı devre dışı bırakıldı + + Wi-Fi\'yi kapat + + Gizlilik Korumasını etkinleştir ya da devre dışı bırak + Uygulamaya başka bir uygulamanın Gizlilik Korumasını kullanıp kullanamayacağını belirleme olanağı verir. Bir uygulama Gizlilik Koruması ile çalışırken; kişiler, arama kayıtları ya da mesajlar gibi kişisel bilgilere ulaşamaz. + Gizlilik Koruması aktif + %1$s kişisel bilgilere ulaşamayacak + Gizlilik Koruması + %1$s %2$s iznini kullanmak istiyor. + + Seçimimi hatırla + + kameraya eriş + konuma erişim + bildirimleri oku + VPN\'yi etkinleştir + açılışta başla + arama kaydını sil + kişileri sil + MMS mesajlarınızı silin + SMS\'leri sil + pencereleri üstte göster + uyg. kullanım istatistiklerini al + cihazı uyanık tut + telefon görüşmesi yap + takvimini güncelle + arama kaydını güncelle + panoyu değiştir + kişileri güncelle + sistem ayarlarını güncelle + mikrofonu aç/kapa + ses çal + bildirim gönder + ortamı yansıt + takvimi oku + arama kaydını oku + panoyu oku + kişileri oku + MMS mesajlarınızı okuyun + SMS mesajlarını oku + SMS mesajı al + ses kaydet + MMS mesajı gönder + SMS mesajı gönder + açılışta başla + bildirim mesajları göster + Bluetooth\'u açıp kapat + hücresel veriye geçiş + NFC\'yi aç kapa + Wi-Fi aç kapa + alarm sesini kontrol et + ses odağını kontrol et + Bluetooth sesini kontrol et + ana ses düzeyini kontrol et + ortam tuşlarını kullan + ortam sesini kontrol et + bildirim sesini kontrol et + zil sesini kontrol et + dokunmatik geri bildirim kullan + Sesli arama seviyesini kontrol et + MMS mesajı yaz + SMS mesajı yaz + parmak izi kullan + bir sesli mesaj ekle + telefon durumuna eriş + Wi-Fi ağlarını tara + duvar kağıdını değiştir + destek yapısı kullan + ekran görüntüsü al + vücut sensörü kullan + hücre yayınları oku + sahte konum bildir + harici depolamayı oku + harici depolama alanına yaz + ekranı aç + cihaz hesaplarını al + Wi-Fi durumunu değiştir + root erişimi al + + Bu ekranı kaldırmak için Geri tuşuna dokunun ve tutun. + + Bağlı cihaz yok + %1$s cihaz bağlı + %1$s cihaz bağlı + + + + Etkinlik başlatma engellendi + %1$s başlatılmadan önce sistem korumaya alındı. Uygulamayı doğrulamak ve başlatmak için dokunun. + + Batarya tam olarak şarj edildi + Aygıtınızın pil ömrünü artırmak için şarjdan çıkarın. + + pil istatistiklerini sıfırla + + Uygulamaya güncel düşük seviye pil kullanım verisini sıfırlama izni verir. + + SIM kartlar değişti + Varsayılan SIM kart tercihlerini ayarlamak için dokunun + diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 909061be89af6..31eccf7a4ef57 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -254,7 +254,7 @@ "Kredi kartı ve şifre gibi kişisel bilgiler içerir." "durum çubuğunu devre dışı bırak veya değiştir" "Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir." - "durum çubuğu" + "durum çubuğunda olma" "Uygulamaya, durum çubuğu olma izni verir." "durum çubuğunu genişlet/daralt" "Uygulamaya, durum çubuğunu genişletip daraltma izni verir." @@ -282,7 +282,7 @@ "Uygulamaya WAP mesajlarını alma ve işleme izni verir. Buna, size gönderilen mesajları takip edip size göstermeden silebilme izni de dahildir." "çalışan uygulamaları al" "Uygulamaya o anda ve son çalışan görevler hakkında bilgi alma izni verir. Bu izin, uygulamanın cihaz tarafından kullanılan uygulamalar hakkında bilgi elde etmesine olanak sağlayabilir." - "Profil ve cihaz sahiplerini yönetme" + "profili ve cihaz sahiplerini yönetme" "Uygulamaların, profil sahiplerini ve cihaz sahibini ayarlamasına izin verir." "çalışan uygulamaları yeniden sırala" "Uygulamaya, görevleri ön plana ve arka plana taşıma izni verir. Uygulama bunu sizden bir giriş olmadan yapabilir." @@ -324,7 +324,7 @@ "Uygulamaya tabletinizin çağrı günlüğünde (gelen ve giden çağrılarla ilgili veriler dahil olmak üzere) değişiklik yapma izni verir. Kötü amaçlı uygulamalar bu izni kullanarak çağrı günlüğünüzü silebilir veya değiştirebilir." "Uygulamaya, tabletinizin çağrı kaydında (gelen ve giden çağrılarla ilgili veriler dahil olmak üzere) değişiklik yapma izni verir. Kötü amaçlı uygulamalar bu izni kullanarak çağrı kaydınızı silebilir veya değiştirebilir." "Uygulamaya telefonunuzun çağrı günlüğünde (gelen ve giden çağrılarla ilgili veriler dahil olmak üzere) değişiklik yapma izni verir. Kötü amaçlı uygulamalar bu izni kullanarak çağrı günlüğünüzü silebilir veya değiştirebilir." - "vücut sensörleri (kalp atış hızı takip cihazları gibi)" + "vücut sensörlerine erişme (nabız takip cihazları gibi)" "Uygulamanın, nabzınız gibi fiziksel durumunuzu izleyen sensörlerin gönderdiği verilere erişmesine izin verir." "takvim etkinliklerini ve gizli bilgileri oku" "Uygulamaya, arkadaşlarınızın ve iş arkadaşlarınızın etkinlikleri de olmak üzere tabletinizde depolanan tüm takvim etkinliklerini okuma izni verir. Bu izin, uygulamanın takvim verilerinizi gizliliğine ve hassaslığına bakmaksızın paylaşmasına ve kaydetmesine olanak sağlayabilir." @@ -336,15 +336,15 @@ "Uygulamaya, arkadaşlarınızın veya iş arkadaşlarınızın etkinlikleri de dahil olmak üzere telefonunuzda değiştirebileceğiniz etkinlikleri ekleme, kaldırma ve değiştirme izni verir. Bu izin, uygulamanın takvim sahiplerinden geliyormuş gibi görünen iletiler göndermesine veya etkinlikleri sahibinden habersiz olarak değiştirmesine olanak sağlar." "ek konum sağlayıcı komutlarına eriş" "Uygulamanın, ekstra konum sağlayıcı komutlarına erişmesine izin verir. Bu izin, uygulamanın GPS veya diğer konum kaynaklarının çalışmasını kesmesine olanak sağlayabilir." - "hassas konum (GPS ve ağ tabanlı)" + "konum bilgilerine hassas olarak erişme (GPS ve ağ tabanlı)" "Uygulamaya, Küresel Konumlandırma Sistemi (GPS) veya baz istasyonları ve Kablosuz bağlantı gibi ağ konum kaynaklarını kullanarak konumunuzu hassas bir şekilde belirleme izni verir. Uygulamaların bu konum hizmetlerini kullanabilmesi için bunların cihazınızda açık ve kullanılabilir olması gerekir. Uygulamalar bulunduğunuz yeri belirlemek için bu izni kullanabilirler ve bu kullanım fazladan pil tüketimine neden olabilir." - "yaklaşık konum (ağ tabanlı)" + "konum bilgilerine yaklaşık olarak erişme (ağ tabanlı)" "Uygulamaya, yaklaşık konumunuzu belirleme izni verir. Bu konum bilgisi, baz istasyonları ve Kablosuz bağlantı gibi ağ konum kaynaklarını kullanan konum hizmetlerinden elde edilir. Uygulamaların bu konum hizmetlerini kullanabilmesi için bunların cihazınızda açık ve kullanılabilir olması gerekir. Uygulamalar bulunduğunuz yeri yaklaşık olarak belirlemek için bu izni kullanabilirler." "ses ayarlarınızı değiştirin" "Uygulamaya ses düzeyi ve ses çıkışı için kullanılan hoparlör gibi genel ses ayarlarını değiştirme izni verir." "ses kaydet" "Uygulamaya mikrofonla ses kaydetme izni verir. Bu izin, uygulamanın istediği zaman onayınız olmadan ses kaydetmesine olanak sağlar." - "sim iletişimi" + "SIM karta komut gönderme" "Uygulamanın SIM karta komut göndermesine izin verir. Bu izin çok tehlikelidir." "resim çekme ve görüntü kaydetme" "Uygulamaya kamerayla fotoğraf ve video çekme izni verir. Bu izin, uygulamanın sizin onayınız olmadan istediği zaman kamerayı kullanmasına olanak sağlar." @@ -382,7 +382,7 @@ "Uygulamaya telefon tarafından bilinen hesapların listesini alma izni verir. Bu liste, yüklediğiniz uygulamalar tarafından oluşturulan tüm hesapları içerebilir." "ağ bağlantılarını görüntüleme" "Uygulamaya, hangi ağların bulunduğu ve hangilerinin bağlı olduğu gibi ağ bağlantılarıyla ilgili bilgileri görüntüleme izni verir." - "tam ağ erişimi" + "tam ağ erişimine sahip olma" "Uygulamaya ağ yuvaları oluşturma ve özel ağ protokolleri kullanma izni verir. Tarayıcı ve diğer uygulamalar İnternet\'e veri gönderilmesi için araç sağlarlar, bu nedenle bu izin, İnternet\'e veri göndermek için gerekli değildir." "ağ bağlantısını değiştirme" "Uygulamaya, ağ bağlantısının durumunu değiştirme izni verir." @@ -402,7 +402,7 @@ "Uygulamaya, yerel Bluetooth telefonunu yapılandırma ve uzak cihazları keşfedip bunlarla eşleşme izni verir." "WiMAX\'e bağlan veya WiMAX bağlantısını kes" "Uygulamaya, WiMAX\'in etkin olup olmadığını belirleme ve bağlı tüm WiMAX ağlarıyla ilgili bilgilere erişme izni verir." - "WiMAX durumunu değiştir" + "WiMAX durumunu değiştir" "Uygulamaya, tableti WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir." "Uygulamaya TV\'yi WiMAX ağlarına bağlama ve TV\'nin WiMAX ağları ile bağlantısını kesme izni verir." "Uygulamaya, telefonu WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir." @@ -485,7 +485,7 @@ "Uygulamaya, dokunmatik ekranın kalibrasyon parametrelerini değiştirme izni verir. Normal uygulamalar için hiçbir zaman gerekmez." "DRM sertifikalarına eriş" "Bir uygulamanın DRM sertifikaları için temel hazırlık yapmasına ve bunları kullanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekmez." - "Android Beam aktarım durumunu al" + "Android Beam aktarım durumunu alma" "Bu uygulamanın mevcut Android Beam aktarımlarıyla ilgili bilgi almasına izin verir" "DRM sertifikalarını kaldırma" "Uygulamaya, DRM sertifikalarını kaldırma izin verir. Normal uygulamalar için asla gerekmemelidir." @@ -1091,11 +1091,11 @@ "Biçimlendiriliyor..." "Eklenmedi" "Eşleşen hiçbir etkinlik bulunamadı." - "Medya çıktısını yönlendir" + "medya çıkışını yönlendirme" "Uygulamaya medya çıktısını başka harici cihazlara yönlendirme izni verir." - "Yükleme oturumlarını okuma" + "yükleme oturumlarını okuma" "Bir uygulamanın yükleme oturumlarını okumasına izin verir. Bu, etkin paket yüklemeleriyle ilgili ayrıntıların görülmesine olanak tanır." - "Paketleri yükleme isteğinde bulunma" + "paket yükleme isteğinde bulunma" "Uygulamaya, paketleri yükleme isteğinde bulunma izni verir." "Yakınlaştırma denetimi için iki kez dokunun" "Widget eklenemedi." diff --git a/core/res/res/values-ug/cm_strings.xml b/core/res/res/values-ug/cm_strings.xml new file mode 100644 index 0000000000000..c40799cfbfc09 --- /dev/null +++ b/core/res/res/values-ug/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + ئېكراندىن تۇتۇلغان سۈرەت + + قوغدالغان قىسقا ئۇچۇرنى قوبۇل قىلىش + + ئەپنىڭ قوغدالغان قىسقا ئۇچۇرنى قوبۇللىشىغا يول قويىدۇ. + + قوغدالغان قىسقا ئۇچۇر تىزىمىنى ئۆزگەرتىدۇ + + ئەپنىڭ قوغدالغان قىسقا ئۇچۇر ئادرېسىنىڭ تىزىمىنى ئۆزگەرتىشىگە يول قويىدۇ. + + بىخەتەرلىك + + ئۈسكۈنە بىخەتەرلىك ئۇچۇرىغا مۇناسىۋەتلىك ھوقۇقلار. + + تېلېفون قارا تىزىمىنى ئوقۇش + + ئەپنىڭ كەلگەن تېلېفون ياكى ئۇچۇرلارنىڭ چەكلەنگەن تېلېفون نومۇر ئۇچۇرلىرىنى ئوقۇشىغا يول قويىدۇ. + + تېلېفون قارا تىزىمىنى ئۆزگەرتىدۇ + + كەلگەن تېلېفون ياكى ئۇچۇرنىڭ چەكلەنگەن نومۇر ئۇچۇرلىرىنى ئۆزگەرتىشىگە يول قويىدۇ. + + قۇلۇپ ئېكران تام قەغىزىنى تەڭشەيدۇ + + ئەپنىڭ قۇلۇپ ئېكران تام قەغىزىنى ئۆزگەرتىشىگە يول قويىدۇ. + + قايتا قوزغات + + نۆۋەتتىكى + + + قايتا قوزغات + + ئەسلىگە كەلتۈر + + قوزغىتىش يۈكلىگۈچ + + چۈشۈر + + يۇمشاق قايتا قوزغىتىش + + قايتا قوزغات + + تاختا كومپيۇتېرىڭىز قايتا قوزغىلىدۇ. + تېلېفونىڭىز قايتا قوزغىلىدۇ. + + قايتا قوزغىتىۋاتىدۇ\u2026 + + ئەپ ئاخىرلاشتۇرۇلدى + + تور ھالقىغان ADB قوزغىتىلدى + + USB ۋە تور ADB قوزغىتىلدى + + چېكىلسە سازلاشنى چەكلەيدۇ. + + ADB - %1$s + USB & تور + USB + تور + + ئەپ قوزغىتىشنى توسىدۇ + + %s تېخى ئورنىتىلمىغان + + ئالدىنلىق + يوق + + SIM كارتنىڭ مۇشتەرلىكى ئۆزگەرگەنلىكتىن، Wi-Fi قىزىق نوقتىسى چەكلەندى + + Wi-Fi نى تاقاڭ + + شەخسىيەت قوغداشنى قوزغىتىدۇ ياكى چەكلەيدۇ + ئەپنىڭ باشقا ئەپنى شەخسىيەت قوغداش ھالىتىدە ئىجرا قىلىشىغا يول قويىدۇ. ئەپ شەخسىيەت قوغداش ھالىتىدە ئىجرا قىلىنسا، ئۇ ئالاقەداشلار، چاقىرىش خاتىرىسى ياكى ئۇچۇرلارغا ئوخشاش شەخسىي سانلىق مەلۇماتلارنى زىيارەت قىلىش ھوقۇقى بولمايدۇ. + شەخسىيەت قوغداش ئاكتىپ + %1$s شەخسىي سانلىق مەلۇماتلارنى زىيارەت قىلالمايدۇ + شەخسىيەت قوغداش + %1$s نىڭ قىلماقچى بولغىنى %2$s. + + تاللىشىمنى ئەستە تۇت + + كامېراغا ئېرىشىدۇ + ئورنىڭىزغا ئېرىشىدۇ + ئۇقتۇرۇشىڭىزنى ئوقۇيدۇ + بىر VPN نى قوزغىتىدۇ + قوزغالغاندا باشلا + چاقىرىش خاتىرىڭىزنى ئۆچۈرىدۇ + ئالاقەداشلىرىڭىزنى ئۆچۈرىدۇ + سىزنىڭ MMS ئۇچۇرلىرىڭىزنى ئۆچۈرىدۇ + سىزنىڭ قىسقا ئۇچۇرلىرىڭىزنى ئۆچۈرىدۇ + كۆزنەكلەرنى ئۈستىدە كۆرسىتىدۇ + ئەپ ئىشلىتىش ئەھۋالىنىڭ ئىستاتىستىكىسىغا ئېرىشىدۇ + ئۈسكۈنىنى ئويغاق تۇتىدۇ + تېلېفون نومۇر بۇرايدۇ + يىلنامەڭىزنى يېڭىلايدۇ + چاقىرىش خاتىرىڭىزنى يېڭىلايدۇ + چاپلاش تاختىسىنى ئۆزگەرتىدۇ + ئالاقەداشلىرىڭىزنى يېڭىلايدۇ + سىستېما تەڭشەكلىرىنى يېڭىلايدۇ + مىكروفون ئاۋازى ئۈنلۈك/ئۈنسىز + ئۈن چال + ئۇقتۇرۇش يوللايدۇ + ۋاسىتىنى قويىدۇ + يىلنامەڭىزنى ئوقۇيدۇ + چاقىرىش خاتىرىسىنى ئوقۇيدۇ + چاپلاش تاختىسىنى ئوقۇيدۇ + ئالاقەداشلىرىڭىزنى ئوقۇيدۇ + سىزنىڭ MMS ئۇچۇرلىرىڭىزنى ئوقۇيدۇ + قىسقا ئۇچۇرلىرىڭىزنى ئوقۇيدۇ + قىسقا ئۇچۇرلارنى قوبۇللايدۇ + ئۈنگە ئالىدۇ + بىر MMS ئۇچۇرى يوللايدۇ + بىر قىسقا ئۇچۇر يوللايدۇ + قوزغالغاندا باشلايدۇ + قاڭقىش ئۇچۇرىنى كۆرسىتىدۇ + كۆكچىشنى ئاچ تاقا + كۆچمە تورغا ئالماشتۇرۇش + NFC ئاچ تاقا + WiFi نى ئېچىش تاقاش + قوڭغۇراق ئاۋازىنى تىزگىنلەيدۇ + ئاۋاز فوكۇسىنى تىزگىنلەيدۇ + كۆكچىش ئاۋازىنى تىزگىنلەيدۇ + ئاساسىي ئاۋازنى تىزگىنلەش + ۋاسىتە توپچىلىرىنى ئىشلەت + ۋاسىتە ئاۋازىنى تىزگىنلەش + ئۇقتۇرۇش ئاۋازىنى تىزگىنلەش + قوڭغۇراق ئاۋازىنى تىزگىنلەش + سېزىم ئىنكاسىنى ئىشلەت + ئاۋازلىق چاقىرىش ئاۋازىنى تىزگىنلە + MMS ئۇچۇرى ياز + SMS ئۇچۇر ياز + بارماق ئىشلىتىش + ئاۋازلىق ئېلخەت قوشۇش + يانفون ھالىتىنى زىيارەت قىلىش + Wi-Fi تورىنى سىكاننېرلاش + تەگلىك ئالماشتۇرۇش + قوشۇمچە قۇرۇلمىنى ئىشلىتىش + رەسىم تۇتۇش + ئادەم بەدىنى ئىندۇكسىيەسىنى ئىشلىتىش + رايونلۇق رادىئونى ئوقۇش + ساختا ئورۇن ئىشلىتىڭ + سىرتقى ساقلىغۇچنى ئوقۇش + سىرتقى ساقلىغۇچنى يېزىش + ئېكراننى ئېچىش + ئۈسكىنىنىڭ ھېساباتىغا ئېرىشىش + سىمسىز تور ھالىتىنى ئۆزگەرتىش + root ھوقۇقىغا ئېرىشىدۇ + + بۇ مۇقىم ئېكراننى يوق قىلىش ئۈچۈن، قايتىش كۇنۇپكىسىنى بېسىپ تۇرۇڭ. + + ئۇلانغان ئۈسكۈنە يوق + %1$s ئۈسكۈنە ئۇلاندى + %1$s ئۈسكۈنە ئۇلاندى + + + + پائالىيەت توسىۋېلىندى + %1$s قوزغىلىۋاتقاندا ئاللىبۇرۇن قوغدالدى. چىكىپ ئىسپاتلاڭ ھەم بۇ ئەپنى قوزغىتىڭ. + + باتارىيە تۇللۇق توشتى + باتارىيە ئۆمرىنىڭ تېخىمۇ ئۇزۇن بۇلۇشى ئۈچۈن، توك قاچىلىغۇچنى ئۈسكىنىڭىزدىن ئايرىڭ. + + توكدان ئىستاتىستىكىسىنى ئەسلىگە قايتۇرۇڭ + + ئەپنىڭ نۆۋەتتىكى تۆۋەن توك ئىشلىتىش سانلىق مەلۇماتلىرىنى ئەسلىگە قايتۇرۇشىغا يول قويىدۇ. + + SIM كارتا ئالماشتۇرۇلدى + چىكىپ SIM كارتىنىڭ كۆڭۈلدىكى تەڭشىكىگە قايتۇرۇڭ + diff --git a/core/res/res/values-ug/strings.xml b/core/res/res/values-ug/strings.xml new file mode 100644 index 0000000000000..1ca6003954072 --- /dev/null +++ b/core/res/res/values-ug/strings.xml @@ -0,0 +1,2806 @@ + + + + + + B + + KB + + MB + + GB + + TB + + PB + + %1$s %2$s + + %1$d كۈن + + + + + + + + + + + + + <ماۋزۇسىز> + + (تېلېفون نومۇرى يوق) + + + ئۈنخەت + + MSISDN1 + + + + باغلىنىشتا مەسىلە كۆرۈلدى ياكى MMI كودى خاتا. + + پەقەت مۇقىم نومۇرغىلا بۇ مەشغۇلاتنى ئىجرا قىلىدۇ. + + مۇلازىمەت قوزغىتىلدى. + + مۇلازىمەت تۆۋەندىكى تۈر ئۈچۈن قوزغىتىلدى: + + مۇلازىمەت چەكلەندى. + + خەتلەش مۇۋەپپەقىيەتلىك. + + مۇۋەپپەقىيەتلىك ئۆچۈردى. + + ئىم خاتا. + + MMI تاماملاندى. + + سىز كىرگۈزگەن كونا PIN خاتا. + + سىز كىرگۈزگەن PUK خاتا. + + سىز كىرگۈزگەن PIN ماس كەلمىدى. + + 4-8 خانىلىق PIN نى كىرگۈزۈڭ. + + 8 خانە ۋە ئۇنىڭدىن كۆپ PUK2 نى كىرگۈزۈڭ. + + SIM كارتا PUK نۇمۇرىدا قۇلۇپلانغان. ئېچىش ئۈچۈن PUK نۇمۇرىنى كىرگۈزۈڭ. + SIM كارتىنى ئېچىش ئۈچۈن PUK2 نۇمۇرىنى كىرگۈزۈڭ. + + مۇۋەپپەقىيەتلىك بولمىدى. SIM/RUIM قۇلۇپى قوزغىتىلدى. + + + IMEI + + MEID + + كەلگەن تېلېفون نومۇر + + ئۇرۇلغان تېلېفون نومۇر + + + + كەلگەن تېلېفوننى ئۇلاپ يەتكۈزۈش + + چاقىرىشنى كۈتۈش + + چاقىرىشنى چەكلەش + + ئىم ئۆزگەرتىش + + PIN ئۆزگەرت + كەلگەن نومۇرنى كۆرسىتىش + كەلگەن نومۇرنى كۆرسىتىشنى چەكلەش + ئۈچ تەرەپ سۆزلىشىش + ئېلىشنى خالىمايدىغان تېلېفۇنلارنى ئۈزىۋېتىش + چاقىرغان نومۇرنى يەتكۈزۈش + ئاۋارە قىلماڭ + + كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسەتمەيدۇ ئەمما كېيىنكى قېتىملىق سۆزلىشىشتە كۆرسىتىدۇ. + + كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسەتمەيدۇ ئەمما كېيىنكى قېتىملىق سۆزلىشىشتە كۆرسەتمەيدۇ. + + كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسىتىدۇ ئەمما كېيىنكى قېتىملىق سۆزلىشىشتە كۆرسەتمەيدۇ. + + كۆڭۈلدىكى ئەھۋالدا يەرلىك نومۇرنى كۆرسىتىدۇ كېيىنكى قېتىملىق سۆزلىشىشتىمۇ كۆرسىتىدۇ. + + مۇلازىمەت تەمىنلەنمىگەن + + چاقىرغۇچى كىملىك تەڭشىكىنى ئۆزگەرتەلمەيسىز + + زىيارەت چەكلىمىسى ئۆزگەردى + + سانلىق مەلۇمات مۇلازىمىتى چەكلەندى. + + جىددىي مۇلازىمەت چەكلەندى. + + ئاۋاز مۇلازىمىتى چەكلەندى. + + بارلىق ئاۋاز مۇلازىمىتى چەكلەندى. + + قىسقا ئۇچۇر مۇلازىمىتى توختىتىلدى. + + ئاۋاز/سانلىق مەلۇمات مۇلازىمىتى توختىتىلدى. + + ئاۋاز/قىسقا ئۇچۇر مۇلازىمىتى توختىتىلدى. + + بارلىق ئاۋاز/سانلىق مەلۇمات/قىسقا ئۇچۇر مۇلازىمىتى توختىتىلدى. + + + + + ئاۋاز + + سانلىق مەلۇمات + + فاكس + + قىسقا ئۇچۇر + + قەدەمداشسىز + + قەدەمداش + + بوغچا + + PAD + + + + كەزمە كۆرسەتكۈچ ئوچۇق + كەزمە كۆرسەتكۈچ تاقاق + كەزمە كۆرسەتكۈچ چاقناۋاتىدۇ + يېقىن ئەتراپ سىرتىدا + بىنا سىرتىدا + كەزمە - مايىللىق سىستېما + كەزمە - ئىشلىتىلىشچان سىستېما + كەزمە - ئىتتىپاقداش ھەمكارلاشقۇچىلار + كەزمە - ئالىي ھەمكارلاشقۇچىلار + كەزمە - تولۇق مۇلازىمەت ئىقتىدارى + كەزمە - قىسمەن مۇلازىمەت ئىقتىدارى + كەزمە لەۋھە ئوچۇق + كەزمە لەۋھە تاقاق + مۇلازىمەت ئىزدەۋاتىدۇ + + + + + + + + + + + + + + + + {0}:ئۇلاپ يۆتكىيەلمىدى + + {0}{1} + + {0}: {1} دىن {2} سېكۇنت كېيىن + + {0}:ئۇلاپ يۆتكىيەلمىدى + + {0}:ئۇلاپ يۆتكىيەلمىدى + + + + ئىقتىدار كودى تاماملاندى. + + باغلىنىشتا مەسىلە كۆرۈلدى ياكى ئىقتىدار كودى ئىناۋەتسىز. + + + + جەزملە + + تور خاتالىقى كۆرۈلدى. + + بۇ تور ئادرېسىنى تاپالمىدى. + + بۇ تور بېكەتنىڭ سالاھىيەت دەلىللەش لايىھەسىنى قوللىمايدۇ. + + سالاھىيەت دەلىللىيەلمەيدۇ. + + ۋاكالەتچى مۇلازىمېتىر ئارقىلىق سالاھىيەت دەلىللەش مەغلۇپ بولدى. + + مۇلازىمېتىرغا باغلىنالمىدى . + + مۇلازىمىتىر بىلەن ئالاقە قىلالمىدى. سەل تۇرۇپ قايتا سىناڭ. + + مۇلازىمىتىرغا ئۇلىنىش مۆھلىتى ئېشىپ كەتتى. + + بۇ بەتتە نۇرغۇنلىغان مۇلازىمېتىر قايتا نىشانلاش بار. + + بۇ كېلىشىمنى قوللىمايدۇ. + + بىخەتەر باغلىنىش قۇرالمايدۇ. + + تور بەتنى ئاچالمايدۇ چۈنكى تور ئادرېس ئىناۋەتسىز. + + بۇ ھۆججەتنى زىيارەت قىلالمايدۇ. + + ئىلتىماس قىلغان ھۆججەتنى تاپالمىدى. + + بىر تەرەپ قىلىۋاتقان ئىلتىماس بەك كۆپ. سەل تۇرۇپ قايتا سىناڭ. + + + + %1$s نىڭ تىزىمغا كىرىش خاتالىقى + + + + قەدەمداش + + قەدەمداش + + نۇرغۇن %s ئۆچۈرۈش. + + تاختا كومپيۇتېر ساقلىغۇچىسى توشتى. بەزى ھۆججەتلەرنى ئۆچۈرۈپ بوشلۇق بىكارلاڭ. + + + + تېلېفون ساقلىغۇچىسى توشتى. بەزى ھۆججەتلەرنى ئۆچۈرۈپ بوشلۇق بىكارلاڭ. + + + + تور نازارەت قىلىنغان بولۇشى مۇمكىن + + يوچۇن ئۈچىنچى تەرەپنىڭ نازارىتىدە + + + %s نازارىتىدە + + + + + + + + + + + + مەن + + + + تاختا كومپيۇتېر تاللانمىلار + + + تېلېفون تاللانما + + ئۈنسىز ھالەت + + سىمسىز تورنى ئاچ + + سىمسىز تورنى تاقا + + ئېكران قۇلۇپلا + + تاقا + + قوڭغۇراق تاقاق + + قوڭغۇراق تىترەت + + قوڭغۇراق ئوچۇق + + + + تاقاۋاتىدۇ… + + تاختا كومپيۇتېرىڭىز تاقىلىدۇ. + + + + تېلېفونىڭىز تاقىلىدۇ. + + تاقامسىز؟ + + قايتا قوزغىتىپ بىخەتەر ھالەتكە كىرىدۇ + + قايتا قوزغىتىپ بىخەتەر ھالەتكە كىرەمسىز؟ بۇنداق بولغاندا سىز ئورناتقان ئۈچىنچى تەرەپ ئەپلەر توختىتىلىدۇ. قايتا قوزغاتسىڭىز ئاندىن بۇ ئەپلەر ئەسلىگە كېلىدۇ. + + يېقىنقى + + يېقىنقى ئەپلەر يوق + + تاختا كومپيۇتېر تاللانمىلار + + + تېلېفون تاللانما + + ئېكران قۇلۇپلا + + تاقا + + خاتالىق دوكلاتى + + خاتالىق دوكلاتى يوللاش + + نۆۋەتتىكى ئۈسكۈنىڭىزنىڭ ھالىتىگە ئائىت ئۇچۇرلارنى توپلاپ، تورخەت ئۇچۇرى يوللايدۇ. يوللاشقا لازىملىق خاتالىق دوكلاتىنى قوزغىتىپ تەييارلاشقا بىر ئاز ۋاقىت كېتىشى مۇمكىن. سەۋرىچانلىق بىلەن كۈتۈڭ. + + + ئۈنسىز ھالەت + + ئاۋاز تاقاق + + ئاۋاز ئوچۇق + + ئايروپىلان ھالىتى + + ئايروپىلان ھالىتى ئوچۇق + + ئايروپىلان ھالىتى تاقاق + + + + + + 999+ + + بىخەتەر ھالەت + + Android سىستېما + + + + + + + + يىلنامە + + + قىسقا ئۇچۇر + + + ساقلىغۇچ + + + مىكروفون + + ئاۋاز ئېلىش + + كامېرا + + + تېلېفون + + + + + كۆزنەك مەزمۇنىنى ئىزدەيدۇ + + سىز ئۆزئارا تەسىرلىشىۋاتقان كۆزنەكنىڭ مەزمۇنىنى تەكشۈرىدۇ. + + چېكىلگەندىكى كۆرگۈنى قوزغىتىدۇ + + ئۈسكۈنە ئىشلەتكۈچى چەككەندىكى مەزمۇننى ئۈنلۈك ئوقۇيالايدۇ، ئىشلەتكۈچى قول ئىشارىتى ئارقىلىق ئېكرانغا كۆز يۈگۈرتەلەيدۇ. + + تور بەت قوشۇمچە كۈچەيتىلگەن ئىقتىدارنى ئاچ + + ئەپ مەزمۇنىنى زىيارەت قىلىشقا قولايلىق بولۇشى ئۈچۈن قوليازما ئورنىتىدۇ. + + كىرگۈزگەن تېكىستىڭىزنى كۆزىتىدۇ + + ئىناۋەتلىك كارتا نومۇرى ۋە ئىمغا ئوخشاش شەخسىي ئۇچۇرلارنىمۇ ئۆز ئىچىگە ئالىدۇ. + + + ھالەت بالداقنى چەكلەش ياكى ئۆزگەرتىش. + + ئەپنىڭ ھالەت بالداقنى چەكلىشىگە ياكى سىستېما سىنبەلگىسىنى قوشۇش ۋە ئۆچۈرۈشىگە يول قويىدۇ. + + + ئەپنىڭ ھالەت بالداقتا تۇرۇشىغا يول قويىدۇ. + + ھالەت بالداقنى يايىدۇ/قاتلايدۇ + + ئەپنىڭ ھالەت بالداقنى يېيىش ياكى قاتلىشىغا يول قويىدۇ. + + قىسقا يول ئورنىتىش + + ئەپنىڭ ئىشلەتكۈچى ئارىلاشمىغان ئەھۋالدا قىسقا يول قۇرۇشقا يول قويىدۇ. + + قىسقا يول ئۆچۈر + + ئەپنىڭ ئىشلەتكۈچى ئارىلاشمىغان ئەھۋالدا قىسقا يولنى ئۆچۈرۈشىگە يول قويىدۇ. + + سىرتقا نومۇر بۇراشنى قايتا تەڭشەيدۇ + + ئەپنىڭ ئۇرۇلغان تېلېفۇننى بىر تەرەپ قىلىش ۋە نۇمۇرنى ئۆزگەرتىپ ئۇرۇشىغا يول قويىدۇ. بۇ ھوقۇق ئەپنىڭ ئۇرۇلغان تېلېفۇننى كۆزىتىشى، قايتا ئۇرۇشى ھەتتا چەكلەپ قۇيۇشىغا يول قويۇشى مۇمكىن. + + قىسقا ئۇچۇر (SMS) قوبۇللايدۇ + + ئەپنىڭ ئۇچۇر قۇبۇل قىلىشى ۋە بىر تەرەپ قىلىشىغا يول قويىدۇ. بۇ ئىقتىداردا ئەپلەر ئۇچۇرلىرىڭىزنى نازارەت قىلىشى ياكى سىزگە كۆرسەتمەي ئۆچۈرۈۋېتىشى مۇمكىن. + + قىسقا ئۇچۇر (MMS) قوبۇللايدۇ + + ئەپنىڭ كۆپ ۋاستە ئۇچۇر (MMS) قۇبۇل قىلىشى ۋە بىر تەرەپ قىلىشىغا يول قويىدۇ. بۇ ئىقتىداردا ئەپلەر ئۇچۇرلىرىڭىزنى نازارەت قىلىشى ياكى سىزگە كۆرسەتمەي ئۆچۈرۈۋېتىشى مۇمكىن. + + ئىجتىمائى رايون تارقاتقان ئۇچۇرلارنى ئوقۇيدۇ + + + مۇشتەرى بولغان خەۋەر بېتىنى ئوقۇيدۇ + + ئەپنىڭ نۆۋەتتە قەدەمداشلانغان خەۋەر بېتىگە مۇناسىۋەتلىك تەپسىلىي ئۇچۇرىنى ئوقۇشىغا يول قويىدۇ. + + + ئەپنىڭ ئۇچۇر يوللىشىغا يول قويىدۇ. زەھەرخەندە ئەپلەر رۇخسىتىڭىزسىز ئۇچۇر يوللاپ، سىزنى چىقىم قىلدۇرىدۇ. + + تېكىست ئۇچۇرىڭىزنى ئوقۇيدۇ (قىسقا ئۇچۇر ياكى كۆپ ۋاستە ئۇچۇر) + + ئەپنىڭ تاختا كومپيۇتېر ياكى SIM كارتىدىكى ئۇچۇرلارنى ئۇقۇشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ بارلىق قىسقا ئۇچۇرلارنى ئوقۇۋالالايدۇ، قىسقا ئۇچۇر مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ. + + + ئەپنىڭ تېلېفون ياكى SIM كارتىدىكى ئۇچۇرلارنى ئۇقۇشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ بارلىق قىسقا ئۇچۇرلارنى ئوقۇۋالالايدۇ، قىسقا ئۇچۇر مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ. + + تېكىست ئۇچۇر قوبۇللايدۇ (WAP) + + ئەپنىڭ WAP ئۇچۇر قۇبۇل قىلىشى ۋە بىر تەرەپ قىلىشىغا يول قويىدۇ. بۇ ئىقتىداردا ئەپلەر ئۇچۇرلىرىڭىزنى نازارەت قىلىشى ياكى سىزگە كۆرسەتمەي ئۆچۈرۈۋېتىشى مۇمكىن. + + ئىجرا قىلىنىۋاتقان ئەپلەرنى ئىزدەيدۇ + + ئەپنىڭ نۆۋەتتىكى ۋە يىقىنقى ئىجرا قىلىنغان ۋەزىپە ئۇچۇرلىرىنى ئىزدىشىگە يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ بۇ ئۈسكۈنىدە قانداق ئەپلەرنىڭ ئىشلىتىلگەنلىكى ھەققىدىكى ئۇچۇرلارنى بىلەلەيدۇ. + + + + ئىجرا قىلىنىۋاتقان پىروگراممىلارنى قايتا تەرتىپلەيدۇ + + ئەپنىڭ ۋەزىپىنى ئالدى سۇپا ياكى ئارقا سۇپىغا يۆتكىشىگە يول قويىدۇ. بۇ ئەپ سىزدىن بىسوراق مەشغۇلاتنى ئۆز ئالدىغا ئىجرا قىلىدۇ. + + ماشىنىدا يۈرۈش ھالىتىنى قوزغىتىدۇ + + ئەپنىڭ ماشىنىدا يۈرۈش ھالىتىنى قوزغىتىشىغا يول قويىدۇ. + + باشقا ئەپلەرنى تاقايدۇ + + ئەپنىڭ ئارقا سۇپىدا ئىجرا قىلىنىۋاتقان باشقا ئەپلەرنى ئاخىرلاشتۇرۇشىغا يول قويىدۇ. بۇ ھوقۇق باشقا ئەپلەرنىڭ ئىجرا قىلىنىشىنى توختىتىشنى كەلتۈرۈپ چىقىرىدۇ. + + باشقا ئەپلەرنىڭ ئۈستىدە كۆرسىتىدىغان مەزمۇن + + بۇ ئەپنىڭ باشقا ئەپنىڭ ئۈستىدە ياكى ئىشلەتكۈچى ئارايۈزىنىڭ مۇئەييەن بۆلىكىگە سىزىشىغا يول قويىدۇ. بۇنداق بولغاندا بارلىق ئەپلەرنىڭ ئارايۈزىگە كاشىلا قىلىشى ياكى سىز باشقا ئەپلەردە كۆرگەن مەزمۇن ئۆزگىرىپ كېتىشى مۇمكىن. + + ئەپنى ھەمىشە ئىجرا قىلدۇرىدۇ + + ئەپنىڭ مەلۇم بۆلىكىنىڭ ئەسلەكتە داۋاملىق ئىجرا قىلىنىشىغا يول قويىدۇ. بۇنداق بولغاندا باشقا ئەپلەر ئىشلىتىدىغان ئەسلەكنى چەكلەپ، تاختا كومپيۇتېرنىڭ ئىجرا قىلىش سۈرئىتىنى ئاستىلىتىۋېتىدۇ. + + ئەپنىڭ مەلۇم بۆلىكىنىڭ ئەسلەكتە داۋاملىق ئىجرا قىلىنىشىغا يول قويىدۇ. بۇنداق بولغاندا باشقا ئەپلەر ئىشلىتىدىغان ئەسلەكنى چەكلەپ، تېلېفوننىڭ ئىجرا قىلىش سۈرئىتىنى ئاستىلىتىۋېتىدۇ. + + ئەپنىڭ ساقلاش بوشلۇقىنى ھىسابلايدۇ + + ئەپنىڭ ئۆزىنىڭ كودى، سانلىق مەلۇماتى ۋە غەملەك بوشلۇقىنى ئىزدىشىگە يول قويىدۇ. + + سىستېما تەڭشەكلىرىنى ئۆزگەرتىدۇ + + ئەپنىڭ سىستېما تەڭشەك سانلىق مەلۇماتىنى ئۆزگەرتىشىگە يول قويىدۇ. زەھەرخەندە ئەپلەر بۇ ئارقىلىق سىستىما سەپلىمىڭىزنى بۇزىدۇ. + + قوزغالغاندا ئىجرا قىلىدۇ + + ئەپنىڭ سىستېما قوزغىتىلغاندا ئاپتۇماتىك قوزغىلىشىغا يول قويىدۇ. بۇنداق بولغاندا تاختا كومپيۇتېر قوزغىلىش ۋاقتى ئۇزىراپ كېتىدۇ، ئەپ ئوچۇق تۇرغاندا تاختا كومپيۇتېر سۈرئىتىگىمۇ تەسىر يىتىدۇ. + + + ئەپنىڭ سىستېما قوزغىتىلغاندا ئاپتۇماتىك قوزغىلىشىغا يول قويىدۇ. بۇنداق بولغاندا تېلېفون قوزغىلىش ۋاقتى ئۇزىراپ كېتىدۇ، ئەپ ئوچۇق تۇرغاندا تېلېفون سۈرئىتىگىمۇ تەسىر يىتىدۇ. + + مۇقىم ئاڭلىتىشنى يوللايدۇ + + ئەپنىڭ ئاڭلىتىش تۈگىگەندىن كېيىنمۇ ساقلىنىپ قالىدىغان مۇقىم ئاڭلىتىشنى يوللىشىغا يول قويىدۇ. بۇ ئىقتىدارنى كۆپ ئىشلەتكەندە ئەسلەكنى كۆپ ئىگىلىۋېلىپ تاختا كومپيۇتېر سۈرئىتىنى ئاستىلىتىۋېتىدۇ ياكى مۇقىملىقىنى تۆۋەنلىۋېتىدۇ. + + + ئەپنىڭ ئاڭلىتىش تۈگىگەندىن كېيىنمۇ ساقلىنىپ قالىدىغان مۇقىم ئاڭلىتىشنى يوللىشىغا يول قويىدۇ. بۇ ئىقتىدارنى كۆپ ئىشلەتكەندە ئەسلەكنى كۆپ ئىگىلىۋېلىپ تېلېفون سۈرئىتىنى ئاستىلىتىۋېتىدۇ ياكى مۇقىملىقىنى تۆۋەنلىۋېتىدۇ. + + ئالاقەداشلىرىڭىزنى ئوقۇيدۇ + + ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئوقۇشىغا يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا ئالاقەداش سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن.\" + + + ئەپنىڭ تېلېفوندا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئوقۇشىغا يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا ئالاقەداش سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن. + + ئالاقەداشلىرىڭىزنى تەھرىرلەيدۇ + + ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئۆزگەرتىشىگە يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ئۆچۈرۈۋېتەلەيدۇ. + + + ئەپنىڭ تېلېفوندا ساقلانغان ئالاقەداشلىرىڭىزنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى ئۆزگەرتىشىگە يول قويىدۇ، تېلېفون، تورخەت ياكى باشقا ئۇسۇلدا مەلۇم كىشى بىلەن ئالاقە قىلىش چاستوتىڭىزنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر ئالاقەداشلىرىڭىزنىڭ سانلىق مەلۇماتىنى ئۆچۈرۈۋېتەلەيدۇ. + + چاقىرىش خاتىرىسىنى ئوقۇيدۇ + + ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان چاقىرىش خاتىرىسىنى ئوقۇشىغا يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر چاقىرىش خاتىرىسى سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن. + + + ئەپنىڭ تېلېفوندا ساقلانغان چاقىرىش خاتىرىسىنى ئوقۇشىغا يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپلەر چاقىرىش خاتىرىسى سانلىق مەلۇماتىنى ساقلىيالايدۇ، زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىر قىلىۋېتىشى مۇمكىن. + + چاقىرىش خاتىرىسىنى يازىدۇ + + ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان چاقىرىش خاتىرىسىنى ئۆزگەرتىشىگە يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ئۆزگەرتىۋېتىشى مۇمكىن. + + + ئەپنىڭ تېلېفوندا ساقلانغان چاقىرىش خاتىرىسىنى ئۆزگەرتىشىگە يول قويىدۇ، چاقىرغان ۋە چاقىرىلغان تېلېفون ئۇچۇرلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. زەھەرخەندە ئەپلەر سىز بىخەۋەر ھالدا چاقىرىش خاتىرە سانلىق مەلۇماتلىرىڭىزنى ئۆزگەرتىۋېتىشى مۇمكىن. + + + + يىلنامەدىكى پائالىيەت ۋە مەخپىي ئۇچۇرلارنى ئوقۇيدۇ + + ئەپنىڭ تاختا كومپيۇتېردا ساقلانغان يىلنامەدىكى پائالىيەت ئۇچۇرلىرىنى ئۇقۇشىغا يول قويىدۇ، دوست ياكى ئىشداشلىرىڭىزنىڭ پائالىيەتلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ يىنامە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىرلەپ ياكى ساقلىيالايدۇ، بۇ ئۇچۇرلار مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ. + + + ئەپنىڭ تېلېفوندا ساقلانغان يىلنامەدىكى پائالىيەت ئۇچۇرلىرىنى ئۇقۇشىغا يول قويىدۇ، دوست ياكى ئىشداشلىرىڭىزنىڭ پائالىيەتلىرىنىمۇ ئۆز ئىچىگە ئالىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ يىنامە سانلىق مەلۇماتلىرىڭىزنى ھەمبەھىرلەپ ياكى ساقلىيالايدۇ، بۇ ئۇچۇرلار مەزمۇنى ياكى مەخپىيەتلىكنى ئويلاشمايدۇ. + + يىلنامەدىكى پائالىيەتلىرىڭىزنى قوشۇپ ئۆزگەرتىدۇ ھەمدە ئىگىسى خەۋەرسىز ئەھۋالدا قارشى تەرەپنىڭ تورخەت يوللىشىنى ئىلتىماس قىلىدۇ. + + + + + زىيادە ئورۇن ئۇچۇرىغا ئېرىشىش پىروگرامما بۇيرۇق زىيارىتى + + + + ئەپنىڭ يەرشارى ئورۇن بەلگىلەش سىستېمىسى (GPS) ياكى تارقىتىش مۇنارى ۋە Wi-Fi غا ئوخشاش تور ئورنى ئۇچۇر مەنبەسى ئارقىلىق دەل ئورنىڭىزنىڭ ئۇچۇرىغا ئېرىشىشىگە يول قويىدۇ. ئۈسكۈنىدە ئورۇن مۇلازىمىتىنى قوزغاتسىڭىز ئاندىن ئەپ سىزنىڭ ئورۇن ئۇچۇرىڭىزغا ئېرىشەلەيدۇ. ئەپ بۇ خىل مۇلازىمەت ئارقىلىق دەل ئورنىڭىزنى جەزملەيدۇ، بۇنداق بولغاندا ئەپ تېخىمۇ كۆپ توك سەرپ قىلىشى مۇمكىن. + + + ئەپنىڭ تارقىتىش مۇنارى ۋە Wi-Fi غا ئوخشاش تور ئورنى ئۇچۇر مەنبەسى ئارقىلىق تەخمىنىي ئورنىڭىزنىڭ ئۇچۇرىغا ئېرىشىشىگە يول قويىدۇ. ئۈسكۈنىدە ئورۇن مۇلازىمىتىنى قوزغاتسىڭىز ئاندىن ئەپ سىزنىڭ ئورۇن ئۇچۇرىڭىزغا ئېرىشەلەيدۇ. ئەپ بۇ خىل مۇلازىمەت ئارقىلىق تەخمىنىي ئورنىڭىزنى جەزملەيدۇ، بۇنداق بولغاندا ئەپ تېخىمۇ كۆپ توك سەرپ قىلىشى مۇمكىن. + + ئاۋاز تەڭشىكىنى ئۆزگەرتىدۇ + + ئەپنىڭ سىستېمىنىڭ ئاۋاز كۈچى، ئاۋاز چىقىرىدىغان ياڭراتقۇ قاتارلىق بارلىق ئومۇمىيەت ئاۋاز تەڭشىكىنى ئۆزگەرتىشىگە يول قويىدۇ. + + ئاۋاز ئېلىش + + ئەپنىڭ مىكروفون ئارقىلىق ئاۋاز ئېلىشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ سىز جەزملىمەي تۇرۇپلا خالىغان ۋاقىتتا ئاۋاز ئالالايدۇ. + + + + رەسىم تارتىپ ۋە سىنغا ئالىدۇ + + ئەپنىڭ كامېرا ئارقىلىق رەسىم تارتىشى ۋە سىنغا ئېلىشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ سىز جەزملىمەي تۇرۇپلا خالىغان ۋاقىتتا كامېرانى ئىشلىتەلەيدۇ. + + تىترەتكۈچ تىزگىنى + + ئەپنىڭ تىترەتكۈچنى باشقۇرۇشىغا يول قويىدۇ. + + چاقماق چىراغ باشقۇرۇش + + ئەپنىڭ چاقماق چىراغ باشقۇرۇشىغا يول قويىدۇ. + + تېلېفون نۇمۇرىنى بىۋاستە بۇرايدۇ + + ئەپنىڭ سىزنىڭ ۋاسىتىڭىزسىز تېلېفون ئۇرۇشىغا يول قويىدۇ. بۇ ھوقۇق ئارقىلىق ئەپ تېلېفون ئۇرۇشى ياكى تېلېفون ھەققىڭىزنى ئاشۇرۇۋېتىشى مۇمكىن. دىققەت: بۇ ھوقۇق پىروگراممىنىڭ جىددى قۇتقۇزۇش تېلېفۇنى ئۇرۇشىغا رۇخسەت قىلمايدۇ. زەھەرخەندە ئەپلەر سىز جەزملىمەي تۇرۇپمۇ تېلېفون ئۇرۇش ئارقىلىق مۇناسىپ ھەق كەلتۈرۈپ چىقىرىدۇ. + + + + تېلېفوننىڭ ھالىتى ۋە سالاھىيىتىنى ئوقۇيدۇ + + ئەپنىڭ ئۈسكۈنىنىڭ تېلېفون ئىقتىدارىنى زىيارەت قىلىشىغا يول قويىدۇ. ئەپ تېلېفوننىڭ نۇمۇرىنى، رەت نۇمۇرىنى، تېلېفوننىڭ سۆزلىشىشۋاتقانلىقىنى، قارشى تەرەپنىڭ نۇمۇرىنى جەزملەش ھوقۇقى بولىدۇ. + + تاختا كومپيۇتېرنى ئۇيقۇ ھالىتىدىن چەكلەيدۇ + + + تېلېفوننى ئۇيقۇ ھالىتىدىن چەكلەيدۇ + + ئەپنىڭ تاختا كومپيۇتېرنىڭ ئۇيقۇ ھالىتىگە كىرىشىنى چەكلىشىگە يول قويىدۇ. + + + ئەپنىڭ تېلېفوننىڭ ئۇيقۇ ھالىتىگە كىرىشىنى چەكلىشىگە يول قويىدۇ. + + ئىنفرا قىزىل نۇر تارقىتىدۇ + + ئەپنىڭ تاختا كومپيۇتېرنىڭ ئىنفرا قىزىل نۇرلۇق تارقاتقۇچىسىنى ئىشلىتىشىگە يول قويىدۇ. + + + ئەپنىڭ تېلېفوننىڭ ئىنفرا قىزىل نۇرلۇق تارقاتقۇچىسىنى ئىشلىتىشىگە يول قويىدۇ. + + تام قەغەز تەڭشىكى + + ئەپنىڭ سىستېما تام قەغەزنى تەڭشىشىگە يول قويىدۇ. + + تام قەغەز چوڭلۇقىنى تەڭشەيدۇ + + ئەپنىڭ تام قەغەزنىڭ چوڭ-كىچىكلىكىنىڭ ئەسكەرتىشىنى تەڭشىشىگە يول قويىدۇ. + + ۋاقىت رايون تەڭشىكى + + ئەپنىڭ تاختا كومپيۇتېر ۋاقىت رايونىنى ئۆزگەرتىشىگە يول قويىدۇ. + + + ئەپنىڭ تېلېفون ۋاقىت رايونىنى ئۆزگەرتىشىگە يول قويىدۇ. + + ئۈسكۈنىدىكى ھېساباتنى ئىزدەيدۇ + + ئەپنىڭ تاختا كومپيۇتېردا ئەسلى بار بولغان مەلۇملۇق ھىسابات تىزىمىغا ئېرىشىشىگە يول قويىدۇ. ئۇنىڭدا ئورنىتىلغان ئەپلەر قۇرغان بارلىق ھېساباتلار بولۇشى مۇمكىن. + + + ئەپنىڭ تېلېفوندا ئەسلى بار بولغان مەلۇملۇق ھىسابات تىزىمىغا ئېرىشىشىگە يول قويىدۇ. ئۇنىڭدا ئورنىتىلغان ئەپلەر قۇرغان بارلىق ھېساباتلار بولۇشى مۇمكىن. + + تور باغلىنىشىنى كۆرسىتىدۇ + + ئەپنىڭ مەۋجۇت ۋە باغلانغان تورغا ئوخشاش تورغا ئائىت ئۇچۇرلىرىنى كۆرۈشىگە يول قويىدۇ. + + + ئەپنىڭ تور socket قۇرۇپ، ئۆزلەشتۈرگەن تور كېلىشىمى ئىشلىتىشىگە يول قويىدۇ. توركۆرگۈ ۋە باشقا بەزى ئەپلەرگە ئىنتېرنېتقا سانلىق مەلۇمات يوللاش يولى بىلەن تەمىنلەيدۇ شۇڭلاشقا ئەپ بۇ ھوقۇققا ئېرىشمەي تۇتۇپمۇ ئىنتېرنېتقا سانلىق مەلۇمات يوللىيالايدۇ. + + تور باغلىنىشچانلىقىنى ئۆزگەرتىدۇ + + ئەپنىڭ تور باغلىنىش ھالىتىنى ئۆزگەرتىشىگە يول قويىدۇ. + + باغلاقنىڭ ئۇلىنىشىنى ئۆزگەرتىدۇ + + ئەپنىڭ تور باغلىنىش ھالىتىنى ئۆزگەرتىشىگە يول قويىدۇ. + + بۇ Wi-Fi باغلىنىشلىرىنى كۆرسىتىدۇ + + ئەپنىڭ Wi-FI ئۈسكۈنە ئاتى ۋە Wi-FI قوزغالغان ياكى قوزغالمىغانلىقىغا ئوخشاش Wi-FI تورىغا ئائىت ئۇچۇرلىرىنى كۆرۈشىگە يول قويىدۇ. + + بۇ WiFi غا باغلاپ ۋە ئۈزىدۇ + + ئەپنىڭ Wi-Fi ئېغىزىنى ئۇلاش ياكى ئۈزۈش ھەمدە Wi-Fi تورىنىڭ ئۈسكۈنە سەپلىمىسىنى ئۆزگەرتىشىگە يول قويىدۇ. + + Wi-Fi كۆپ قاناللىق ئاڭلىتىشقا يول قويىدۇ + + ئەپنىڭ كۆپ قاناللىق ئاڭلىتىش ئارقىلىق Wi-FI تورىدىكى تاختا كومپيۇتېرىڭىزلا ئەمەس بەلكى ھەممە ئۈسكۈنىلەرنىڭ سانلىق مەلۇمات بوغچىسىنى قوبۇللاپ ۋە يوللاشقا يول قويىدۇ. بۇ مەشغۇلاتنىڭ توك سەرپىياتى كۆپ قاناللىق بولمىغان ئاڭلىتىشنىڭكىدىن يۇقىرى. + + ئەپنىڭ كۆپ قاناللىق ئاڭلىتىش ئارقىلىق Wi-FI تورىدىكى تېلېفونىڭىزلا ئەمەس بەلكى ھەممە ئۈسكۈنىلەرنىڭ سانلىق مەلۇمات بوغچىسىنى قوبۇللاپ ۋە يوللاشقا يول قويىدۇ. بۇ مەشغۇلاتنىڭ توك سەرپىياتى كۆپ قاناللىق بولمىغان ئاڭلىتىشنىڭكىدىن يۇقىرى. + + كۆكچىش تەڭشەك زىيارىتى + + ئەپنىڭ تاختا كومپيۇتېر كۆكچىشنى سەپلىشىگە، قوشنا ئۈسكۈنىلەرنى بايقىشىغا ۋە يىراق مۇساپىلىق پەرلەشكە يول قويىدۇ. + + + ئەپنىڭ تېلېفون كۆكچىشنى سەپلىشىگە، قوشنا ئۈسكۈنىلەرنى بايقىشىغا ۋە يىراق مۇساپىلىق پەرلەشكە يول قويىدۇ. + بۇ WiMAX كە باغلاپ ۋە ئۈزىدۇ + ئەپنىڭ WiMAX قوزغالغان ياكى قوزغالمىغانلىقى ۋە باغلانغان خالىغان WiMAX تورىنىڭ مۇناسىۋەتلىك ئۇچۇرلىرىنى جەزملىشىگە يول قويىدۇ. + ئەپنىڭ تاختا كومپيۇتېرنى WiMAX تورىغا باغلىشى ۋە ئۈزۈشىگە يول قويىدۇ. + ئەپنىڭ تېلېفوننى WiMAX تورىغا باغلىشى ۋە ئۈزۈشىگە يول قويىدۇ. + + كۆكچىش ئۈسكۈنە بىلەن جۈپلىنىدۇ + + ئەپنىڭ تاختا كومپيۇتېر كۆكچىش سەپلىمىسىنى تەكشۈرۈپ كۆرۈپ، چۈپلەنگەن ماس ئۈسكۈنىگە باغلىنىشىغا يول قويىدۇ. + + + ئەپنىڭ تېلېفون كۆكچىش سەپلىمىسىنى تەكشۈرۈپ كۆرۈپ، چۈپلەنگەن ماس ئۈسكۈنىگە باغلىنىشىغا يول قويىدۇ. + + يېقىن دائىرىدىكى ئالاقە تىزگىنى + + ئەپنىڭ يېقىن ئەتراپتىكى ئالاقە(NFC) بەلگە، كارتا ۋە ئوقۇغۇچ بىلەن ئالاقە قىلىشىغا يول قويىدۇ، + + ئېكران قۇلۇپنى چەكلەيدۇ + + ئەپنىڭ كۇنۇپكا قۇلۇپى ۋە ئىم بىلەن باغلانغان بىخەتەرلىك تەڭشىكىنى توختىتىشىغا يول قويىدۇ. مەسىلەن، تېلېفوندا كەلگەندە كۇنۇپكا قۇلۇپىنى توختىتىپ، سۆزلىشىش تاماملانغاندا كۇنۇپكا قۇلۇپىنى قايتا قوزغىتىدۇ. + + + + + + + + + + + + + + + + + + + + + + + + + قەدەمداش تەڭشىكىنى ئوقۇيدۇ + + ئەپنىڭ مەلۇم بىر ھېساباتنىڭ قەدەمداش تەڭشىكىنى ئوقۇشىغا يول قويىدۇ. مەسىلەن، بۇ ھوقۇق ئالاقەداش ئەپنىڭ مەلۇم ھېسابات بىلەن قەدەمداشلانغان ياكى قەدەمداشلانمىغانلىقىنى جەزملەيدۇ. + + قەدەمداشنى ئاچىدۇ ياكى ياپىدۇ + + ئەپنىڭ مەلۇم بىر ھېساباتنىڭ قەدەمداش تەڭشىكىنى ئۆزگەرتىشىگە يول قويىدۇ. مەسىلەن، بۇ ھوقۇق ئالاقەداش ئەپنىڭ مەلۇم ھېسابات بىلەن قەدەمداشلاشنى قوزغىتىشقا ئىشلىتىلىدۇ. + + قەدەمداش سىتاتىستىكا ئۇچۇرىنى ئوقۇيدۇ + + ئەپنىڭ مەلۇم بىر ھېساباتنىڭ قەدەمداش سىتاتىستىكا ئۇچۇرىنى ئوقۇشىغا يول قويىدۇ، ھەرىكەتچان تارىخ خاتىرىسى ۋە قەدەمداش سانلىق مەلۇمات مىقدارىنى قەدەمداشلاشنى ئۆز ئىچىگە ئالىدۇ. + + سىزنىڭ USB ساقلىغۇچىڭىزدىكى مەزمۇنلارنى ئوقۇيدۇ + + سىزنىڭ SD كارتىڭىزدىكى مەزمۇنلارنى ئوقۇيدۇ + + ئەپنىڭ USB ساقلىغۇچىڭىزدىكى مەزمۇنلارنى ئوقۇشىغا يول قويىدۇ. + + ئەپنىڭ SD كارتىڭىزدىكى مەزمۇنلارنى ئوقۇشىغا يول قويىدۇ. + + USB ساقلىغۇچىڭىزدىكى مەزمۇنلارنى ئۆزگەرتىدۇ ياكى ئۆچۈرىدۇ. + + SD كارتىڭىزدىكى مەزمۇنلارنى ئۆزگەرتىدۇ ياكى ئۆچۈرىدۇ. + + ئەپنىڭ USB ساقلىغۇچقا يېزىشىغا يول قويىدۇ. + + ئەپنىڭ SD كارتىغا يېزىشىغا يول قويىدۇ. + + + + + + + + + + + + + + + + تور ئىشلىتىش ئەھۋالىنىڭ تارىخىنى ئوقۇيدۇ + + ئەپنىڭ مۇئەييەن تور ۋە ئەپنىڭ تور ئىشلىتىش ئەھۋالىنىڭ تارىخىنى ئوقۇشىغا يول قويىدۇ. + + تور تەدبىرىنى باشقۇرىدۇ + + ئەپنىڭ تور تەدبىرىنى باشقۇرۇشىغا ۋە ئەپكە قارىتىلغان قائىدە بەلگىلىشىگە يول قويىدۇ. + + تور ئىشلىتىش ئەھۋالىنىڭ تارىخىنى خاتىرىلەش ئۇسۇلىنى ئۆزگەرتىدۇ + + ئەپكە نىسبەتەن تور ئىشلىتىش ئەھۋالىنى خاتىرىلەش ئۇسۇلىنى ئۆزگەرتىشكە يول قويىدۇ. ئادەتتىكى پىروگراممىلار بۇ ھوقۇقنى ئىشلىتەلمەيدۇ. + + زىيارەت ئۇقتۇرۇشى + + بۇ ئەپنىڭ باشقا ئەپلەر تارقاتقان ئۇقتۇرۇشلارنى ئۆز ئىچىگە ئالغان ئۇقتۇرۇشلارنى ئىزدەش، تەكشۈرۈش ھەمدە تازىلىشىغا يول قويىدۇ. + + ئۇقتۇرۇش تىڭشاش مۇلازىمىتىگە باغلايدۇ + + ئىشلەتكۈچىنىڭ ئۇقتۇرۇش تىڭشاش مۇلازىمىتىنى يۇقىرى قاتلام ئېغىزىغا باغلىشىغا يول قويىدۇ. ئادەتتىكى ئەپلەر بۇ ھوقۇققا موھتاج بولمايدۇ. + + + + + + مۇلازىمەت تەمىنلىگۈچى سەپلىگەن ئەپنى يۆتكەپ ئىشلىتىدۇ + + ئەپنىڭ مۇلازىمەت تەمىنلىگۈچى سەپلىگەن ئەپنى يۆتكەپ ئىشلىتىشىگە يول قويىدۇ. ئادەتتىكى ئەپلەر بۇ ھوقۇققا مۇھتاج بولمايدۇ. + + تور ئەھۋالىنىڭ تەكشۈرۈش ئۇچۇرىنى تىڭشايدۇ + + ئەپنىڭ تور ئەھۋالىنىڭ تەكشۈرۈش ئۇچۇرىنى تىڭشىشىغا يول قويىدۇ. ئادەتتىكى ئەپلەر بۇ ھوقۇققا مۇھتاج بولمايدۇ. + + + + + + + + + + + + + + ئىم قائىدە تەڭشىكى + + + ئېكران قۇلۇپىنى ئېچىشنى سىناش قېتىم سانى نازارەتچىسى + + ئېكراننى قۇلۇپلاشتىن ئىلگىرى ئىم كىرگۈزۈش قېتىم سانىنى نازارەت قىلىدۇ؛ ئەگەر ئىم كىرگۈزۈش قېتىم سانى بەك كۆپ بولۇپ كەتسە تاختا كومپيۇتېرنى قۇلۇپلايدۇ ياكى تاختا كومپيۇتېردىكى ھەممە سانلىق مەلۇماتلارنى ئۆچۈرىدۇ. + + + ئېكراننى قۇلۇپلاشتىن ئىلگىرى ئىم كىرگۈزۈش قېتىم سانىنى نازارەت قىلىدۇ؛ ئەگەر ئىم كىرگۈزۈش قېتىم سانى بەك كۆپ بولۇپ كەتسە تېلېفوننى قۇلۇپلايدۇ ياكى تېلېفوندىكى ھەممە سانلىق مەلۇماتلارنى ئۆچۈرىدۇ. + + + + ئېكراننى قۇلۇپلايدۇ + + ئېكران قۇلۇپلاش ئۇسۇلى ۋە ۋاقىت تىزگىنى + + ھەممە سانلىق مەلۇماتنى ئۆچۈرىدۇ + + تاختا كومپيۇتېرنىڭ سانلىق مەلۇماتلىرىنى ئاگاھلاندۇرمايلا ئۆچۈرىدۇ، خۇددى زاۋۇت تەڭشىكىنى ئەسلىگە قايتۇرغان مەشغۇلاتتەك. + + + تېلېفوننىڭ سانلىق مەلۇماتلىرىنى ئاگاھلاندۇرمايلا ئۆچۈرىدۇ، خۇددى زاۋۇت تەڭشىكىنى ئەسلىگە قايتۇرغان مەشغۇلاتتەك. + + + + + + ئۈسكۈنىنىڭ ئومۇمىيەت ۋاكالەتچى تەڭشىكى + + + + + ساقلىغۇچ شىفىرلاش تەڭشىكى + + لازىملىق ساقلايدىغان ئەپ سانلىق مەلۇماتلىرىنى شىفىرلايدۇ + + كامېرانى چەكلە + + ھەممە ئۈسكۈنە كامېراسىنى ئىشلىتىشنى چەكلەيدۇ + + + + + + + ئۆي + كۆچمە + ئىش + ئىش فاكىس + ئوي فاكىس + چاقىرغۇ + باشقا + ئىختىيارىي + + + + + + ئۆي + ئىش + باشقا + ئىختىيارىي + + + + + + ئۆي + ئىش + باشقا + ئىختىيارىي + + + + + + ئۆي + ئىش + باشقا + ئىختىيارىي + + + + + + ئىش + باشقا + ئىختىيارىي + + + + + + AIM + Windows Live + Yahoo + Skype + QQ + Google Talk + ICQ + Jabber + + + ئىختىيارىيي + + ئۆي + + كۆچمە + + ئىش + + ئىش فاكىس + + ئوي فاكىس + + چاقىرغۇ + + باشقا + + قايتۇرما چاقىرىق + + ماشىنا + + شىركەت باش ئاپپاراتى + + ISDN + + ئاساسىي تىزىملىك + + باشقا فاكىس + + سىمسىز ئالاقە + + تېلېگرامما + + TTY/TDD + + خىزمەت تېلېفونى + + خىزمەت چاقىرغۇ + + ياردەمچى + + MMS + + ئىختىيارىيلاشقان + + تۇغۇلغان كۈن + + يىللىق خاتىرە كۈن + + باشقا + + ئىختىيارىي + + ئۆي + + ئىش + + باشقا + + كۆچمە + + ئىختىيارىي + + ئۆي + + ئىش + + باشقا + + ئىختىيارىي + + ئۆي + + ئىش + + باشقا + + ئىختىيارىي + + AIM + + Windows Live + + Yahoo + + Skype + + QQ + + Hangouts + + ICQ + + Jabber + + تور يېغىنى + + ئىش + + باشقا + + ئىختىيارىي + + ئىختىيارىيلاشقان + + ياردەمچى + + قېرىنداش + + بالا + + ئۆيداش + + ئاتا + + دوست + + باشقۇرغۇچى + + ئانا + + ئاتا-ئانا + + ھەمراھ + + تونۇشتۇرغۇچى + + نىسپىي + + ئاچا-سىڭىل + + جورا + + ئىختىيارىيلاشقان + + ئۆي + + ئىش + + باشقا + + بۇ مەزمۇننى كۆرسىتىدىغان ئەپ تېپىلمىدى. + + PIN كودىنى كىرگۈزۈڭ + + PUK ۋە يېڭى PIN كودىنى كىرگۈزۈڭ + + PUK كودى + + يېڭى PIN كودى + + \"بۇ جاينى چېكىپ ئىم كىرگۈزۈڭ\" + + قۇلۇپ ئېچىش ئۈچۈن ئىم كىرگۈزۈڭ + + PIN كىرگۈزۈپ قۇلۇپ ئېچىڭ + + PIN كودى خاتا. + + قۇلۇپ ئېچىشتا، ئاۋۋال Menu نى بېسىپ ئاندىن 0 نى بېسىڭ. + + جىددىي قۇتقۇزۇش ياكى ساقچىغا مەلۇم قىلىش تېلېفۇنى + + + + مۇلازىمەت يوق + + ئىكران قۇلۇپلانغان. + + Menu نى بېسىپ قۇلۇپ ئېچىڭ ياكى جىددىي قۇتقۇزۇشنى چاقىرىڭ. + + Menu نى بېسىپ قۇلۇپنى ئېچىڭ. + + قۇلۇپ ئېچىش ئەندىزىسىنى سىزىڭ + + + چاقىرىشقا قايتىش + + توغرا! + + قايتا سىنا + + قايتا سىنا + + چىرايدا قۇلۇپ ئاچقۇچنى سىناش قېتىم سانىنىڭ يۇقىرى چېكىدىن ئېشىپ كەتتى + + SIM كارتا يوق + + تاختا كومپيۇتېردا SIM كارتا يوق. + + + تېلېفوندا SIM كارتا يوق. + + SIM كارتا قىستۇرۇڭ. + + SIM كارتا يوقالغان ياكى ئوقۇغىلى بولمايدۇ. SIM كارتا قىستۇرۇڭ. + + SIM كارتىنى ئىشلەتكىلى بولمايدۇ. + + سىزنىڭ SIM كارتىڭىز مەڭگۈلۈك توختىتىلدى.\nسىمسىز تور مۇلازىمىتى تەمىنلىگۈچىڭىز بىلەن ئالاقە قىلىپ، يېڭىدىن بىر SIM كارتىغا ئېرىشىڭ. + + + + + + + + + جىددىي تېلېفونلا ئۇرغىلى بولىدۇ + + تور قۇلۇپلانغان + + SIM كارتا PUK نۇمۇر ئارقىلىق قۇلۇپلانغان. + + ئىشلەتكۈچىلەر قوللانمىسىنى كۆرۈڭ ياكى مۇلازىمەتچى بىلەن ئالاقىلىشىڭ. + + + SIM كارتا قۇلۇپىنى ئېچىۋاتىدۇ… + + سىز قۇلۇپ ئېچىش ئەندىزىسىنى %d قېتىم خاتا سىزدىڭىز.\n\n %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + سىز قۇلۇپ ئېچىش ئىمنى %d قېتىم خاتا كىرگۈزدىڭىز.\n\n %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + سىز PIN نى %d قېتىم خاتا كىرگۈزدىڭىز.\n\n %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + سىز قۇلۇپ ئېچىش ئەندىزىسىنى %d قېتىم خاتا سىزدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما Google ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ. "\n\n "يەنە %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + + سىز قۇلۇپ ئېچىش ئەندىزىسىنى %d قېتىم خاتا سىزدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما Google ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تېلېفون قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ."\n\n" يەنە %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تاختا كومپيۇتېرنى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ. + + + سىز تېلېفون قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تېلېفوننى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ. + + سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. تاختا كومپيۇتېر زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، + + + سىز تېلېفون قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. تېلېفون زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، + + %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + ئەندىزىنى ئۇنتۇپسىزمۇ؟ + + ھىسابات قۇلۇپى ئېچىلدى + + ئەندىزىسىنى سىناش قېتىم سانى بەك كۆپ بولۇپ كەتتى + + قۇلۇپ ئېچىشتا، Google ھېساباتىڭىزدا تىزىمغا كىرىڭ + + ئىشلەتكۈچى ئاتى(تورخەت) + + ئىم + + تىزىمغا كىر + + ئىشلەتكۈچى ئاتى ۋە ياكى ئىم خاتا. + + \"ئىشلەتكۈچى ئاتىڭىز ياكى ئىمنى ئۇنۇتتىڭىزمۇ؟\"\n\"google.com/accounts/recovery زىيارەت قىلىڭ.\" + + تەكشۈرۈۋاتىدۇ… + + قۇلۇپ ئاچ + + ئاۋاز ئوچۇق + + ئاۋاز تاقاق + + ئەندىزە سىزىڭ + + ئەندىزە تازىلاندى + + كاتەكچە قوشۇلدى + + + ئەندىزە تامام + + ئەندىزە دائىرىسى. + + %1$s. %3$d نىڭ ئەپچىسى %2$d. + + ئەپچە قوش + + بوش + + قۇلۇپ ئېچىش رايونى يېيىلدى. + + قۇلۇپ ئېچىش رايونى قاتلاندى. + + %1$s ئەپچە. + + ئىشلەتكۈچى تاللىغۇچ + + ھالەت + + كامېرا + + ۋاستە تىزگىنلەر + + ئەپچە قايتا تەرتىپلەش باشلاندى. + + ئەپچە قايتا تەرتىپلەش ئاخىرلاشتى. + + %1$s ئۆچۈرۈلگەن ئەپچە . + + قۇلۇپ ئېچىش دائىرىسىنى يايىدۇ. + + سۈرۈلسە قۇلۇپ ئاچىدۇ. + + ئەدىزەدە قۇلۇپ ئاچىدۇ. + + چىرايدا قۇلۇپ ئاچىدۇ. + + بۇ Pin دا قۇلۇپ ئاچىدۇ. + + ئىمدا قۇلۇپ ئاچىدۇ. + + ئەندىزە دائىرىسى. + + سۈرۈش دائىرىسى + + + + \?123 + + ABC + + ALT + + ھەرپ + + سۆز + + ئۇلانما + + سىزىق + + "%P %-l" + + "%p %-l" + + زاۋۇتتىن چىقىش سىنىقى مەغلۇب بولدى. + + پەقەت \system\app گە ئورنىتىلغان بوغچىلارلا FACTORY-TEST مەشقۇلاتىنى قوللايدۇ. + + FACTORY_TEST مەشغۇلاتىنى قوللايدىغان بوغچا تېپىلمىدى. + + قايتا قوزغات + + + + مەزكۇر %S بەتتە دېيىلگىنى: + + JavaScript + + يېتەكلەشنى جەزملە + + بۇ بەتتىن ئايرىل + + بۇ بەتتە تۇرۇپ تۇر + + %s\"\n\n\"راستلا بۇ بەتتىن ئايرىلامسىز؟ + + جەزملە + + ئەسكەرتىش: قوش چەكسىڭىز چوڭىيىدۇ ۋە كىچىكلەيدۇ. + + ئۆزلۈكىدىن تولدۇر + + ئۆزلۈكىدىن تولدۇرۇش تەڭشىكى + + + $1$2$3 + + « ،» + + $1$2$3 + + attention|attn + + province|region|other|provincia|bairro|suburb + + company|business|organization|organisation|department|firma|firmenname|empresa|societe|société|ragione.?sociale|会社|название.?компании|单位|公司 + + address.?line|address1|addr1|street|strasse|straße|hausnummer|housenumber|house.?name|direccion|dirección|adresse|indirizzo|住所1|morada|endereço|Адрес|地址 + + address|adresse|indirizzo|住所|地址 + + address.?line2|address2|addr2|street|suite|unit|adresszusatz|ergänzende.?angaben|direccion2|colonia|adicional|addresssuppl|complementnom|appartement|indirizzo2|住所2 + + address.?line3|address3|addr3|street|line3|municipio|batiment|residence|indirizzo3 + + country|location|国|国家 + + zip|postal|post code|pcode|^1z$|postleitzahl|cp|cdp|cap|郵便番号|codigo|codpos|cep|Почтовый.?Индекс|邮政编码|邮编|郵遞區號 + + zip|^-$|post2|codpos2 + + city|town|ort|stadt|suburb|ciudad|provincia|localidad|poblacion|ville|commune|localita|市区町村|cidade|Город|市|分區 + + state|county|region|province|land|county|principality|都道府県|estado|provincia|область|省|地區 + + ئوخشاش + + مېنىڭكىنى + + ھېسابات + + پاراخوت + + e.?mail|メールアドレス|Электронной.?Почты|邮件|邮箱|電郵地址 + + user.?name|user.?id|vollständiger.?name|用户名 + + ^name|full.?name|your.?name|customer.?name|firstandlastname|nombre.*y.*apellidos|^nom|お名前|氏名|^nome|姓名 + + ^name|^nom|^nome + + irst.*name|initials|fname|first$|vorname|nombre|forename|prénom|prenom|名|nome|Имя + + middle.*initial|m\\.i\\.|mi$ + + middle.*name|mname|middle$|apellido.?materno|lastlastname + + last.*name|lname|surname|last$|nachname|apellidos|famille|^nom|cognome|姓|morada|apelidos|surename|sobrenome|Фамилия + + phone|telefonnummer|telefono|teléfono|telfixe|電話|telefone|telemovel|телефон|电话 + + area.*code|acode|area + + prefix|preselection|ddd + + suffix + + ext|ramal + + card.?holder|name.?on.?card|ccname|owner|karteninhaber|nombre.*tarjeta|nom.*carte|nome.*cart|名前|Имя.*карты|信用卡开户名|开户名|持卡人姓名|持卡人姓名 + + ئىسىم + + verification|card identification|cvn|security code|cvv code|cvc + + number|card.?#|card.?no|ccnum|nummer|credito|numero|número|numéro|カード番号|Номер.*карты|信用卡号|信用卡号码|信用卡卡號 + + expir|exp.*month|exp.*date|ccmonth|gueltig|gültig|monat|fecha|date.*exp|scadenza|有効期限|validade|Срок действия карты|月 + + exp|^/|year|ablaufdatum|gueltig|gültig|yahr|fecha|scadenza|有効期限|validade|Срок действия карты|年|有效期 + + ^card + + fax|télécopie|telecopie|ファックス|факс|传真|傳真 + + country.*code|ccode|_cc + + ^\\($ + + ^-$|^\\)$ + + ^-$ + + ئۆلكە + + پوچتا نومۇر + + ئۆلكە + + پوچتا نومۇرى + + دۆلەت + + ئارال + + رايون + + تارماق + + تەۋە رايون + + مەمۇرىي رايون + + دائىرە + + خەلىپەلىك + + تور خەتكۈچى ۋە تارىخ خاتىرىڭىزنى ئوقۇيدۇ + + ئەپنىڭ توركۆرگۈدىكى بارلىق ئادرېس ۋە خەتكۈچلەرنى ئوقۇشىغا يول قويىدۇ. دىققەت: بۇ ھوقۇق ئۈچىنچى تەرەپ توركۆرگۈ ياكى تور بەت كۆرۈش ئىقتىدارى بار باشقا ئەپكە ماس كەلمەسلىكى مۇمكىن + + تور خەتكۈچى ۋە تارىخ خاتىرىسى يازىدۇ + + + + + قوڭغۇراق تەڭشەك + + + ئۈنخەت قوش + + ئەپنىڭ ئۈنخەت ساندۇقىڭىزنىڭ قوبۇللاش ساندۇقىغا ئۇچۇر قوشۇشىغا يول قويىدۇ. + + توركۆرگۈنىڭ جۇغراپىيەلىك ئورۇن ھوقۇقىنى ئۆزگەرت + + ئەپنىڭ توركۆرگۈنىڭ جۇغراپىيەلىك ئورۇن ھوقۇقىنى ئۆزگەرتىشىگە يول قويىدۇ. زەھەرخەندە ئەپلەر بۇ ئارقىلىق توركۆرگۈنىڭ ئورنىنى خالىغان تور بىكەتكە يوللايدۇ. + + توركۆرگۈ ئىمنى ساقلىۋالسۇنمۇ؟ + + ھازىرچە ياق + + ئەستە تۇت + + ھەرگىز + + بۇ بەتنى ئېچىش ھوقۇقىڭىز يوق. + + تېكىست كېسىپ چاپلاش تاختىسىغا كۆچۈرۈلدى. + + تېخىمۇ كۆپ + + Menu+ + + بوشلۇق + + Enter + + ئۆچۈر + + + + ئىزدە + + + ئىزدە + + سۈرۈشتۈرۈش ئىزدە + + سۈرۈشتۈرۈش تازىلا + + سۈرۈشتۈرۈش تاپشۇر + + تاۋۇش ئىزدەش + + چېكىلگەندىكى كۆرگۈنى قوزغىتامدۇ؟ + + %1$s چېكىلگەندىكى كۆرگۈ ئىقتىدارى ئېچىلغاندا، چەككەن مەزمۇننىڭ چۈشەندۈرۈشىنى ئاڭلىيالايسىز ياكى كۆرەلەيسىز. يەنە قول ئىشارىتى مەشغۇلاتى ئارقىلىق تاختا كومپيۇتېر بىلەن ئۆز ئارا تەسىرلىشەلەيسىز. + + %1$s چېكىلگەندىكى كۆرگۈ ئىقتىدارى ئېچىلغاندا، چەككەن مەزمۇننىڭ چۈشەندۈرۈشىنى ئاڭلىيالايسىز ياكى كۆرەلەيسىز. يەنە قول ئىشارىتى مەشغۇلاتى ئارقىلىق تېلېفون بىلەن ئۆز ئارا تەسىرلىشەلەيسىز. + + 1 ئاي ئىلگىرى + + 1 + + + ئالدىنقى ئاي + + كونىراق + + %s دىكى + + %s دا + + %s دا + + كۈن + + كۈن + + سائەت + + سائەت + + مىنۇت + + مىنۇت + + سېكۇنت + + سېكۇنت + + ھەپتە + + ھەپتە + + يىل + + يىل + + + 1 سېكۇنت + + + + 1 مىنۇت + + + + 1 سائەت + + + سىن مەسىلىسى + + كەچۈرۈڭ، بۇ سىننى مەزكۇر ئۈسكۈنىدە قويۇشقا ماس كەلمەيدۇ. + + سىننى قويالمايدۇ + + جەزملە + + "%1$s%2$s" + + "چۈش" + + "چۈش" + + "يېرىم كېچە" + + "يېرىم كېچە" + + %1$02d:%2$02d + + %1$d:%2$02d:%3$02d + + ھەممىنى تاللا + + كەس + + كۆچۈر + + چاپلا + + ئالماشتۇر… + + ئۆچۈر + + تور ئادرېس كۆچۈر + + تېكىست تاللا + + تېكىست تاللاش + + لۇغەتكە قوش + + ئۆچۈر + + كىرگۈزگۈچ + + تېكىست مەشغۇلاتى + + ساقلىغۇچ تۈگەي دەپ قالدى + + سىستېمىنىڭ بەزى ئىقتىدارلىرى ئىشلىمەسلىكى مۇمكىن + + + %1$s ئىجرا قىلىنىۋاتىدۇ. + + چېكىلسە تەپسىلاتىنى بىلگىلى بولىدۇ ياكى ئەپنى توختىتىدۇ. + + جەزملە + + ۋاز كەچ + + جەزملە + + ۋاز كەچ + + دىققەت + + يۈكلەۋاتىدۇ… + + ئوچۇق + + تاقاق + + ئىشلىتىدىغان ئەپنى تاللاڭ + + + + + + + + + + + كۆڭۈلدىكى ئەھۋالدا مۇشۇ خىل ئۇسۇلنى ئىشلىتىدۇ. + + + سىستېما تەڭشەكلەر > ئەپلەر > چۈشۈرگەنلەردىن كۆڭۈلدىكى تەڭشەكنى تازىلايدۇ. + + مەشغۇلات تاللاڭ + + بۇ USB ئۈسكۈنە ئۈچۈن ئەپ تاللاڭ + + بۇ مەشغۇلاتنى ئىجرا قىلىدىغان ئەپ يوق. + + + + ناھايىتى ئەپسۇس، %1$s توختىدى. + + ناھايىتى ئەپسۇس، %1$s جەريان توختىدى. + + + + %2$s ئىنكاس يوق.\n\nئۇنى تاقامسىز؟ + + %1$s پائالىيەتتە ئىنكاس يوق.\n\nئۇنى تاقامسىز؟ + + %1$s ئىنكاس يوق. ئۇنى تاقامسىز؟ + + %1$s جەرياندا ئىنكاس يوق.\n\nئۇنى تاقامسىز؟ + + جەزملە + + دوكلات + + كۈت + + بۇ بەتنىڭ ئىنكاسى ئاستىلاپ كەتتى.\n\nئۇنى تاقامسىز؟ + + ئەپ قايتا نىشانلاندى + + %1$s ئىجرا قىلىنىۋاتىدۇ. + + %1$s قوزغىتىلدى. + + نىسبىتى + + ھەمىشە كۆرسەت + + سىستېما تەڭشەكلەر > ئەپلەر > چۈشۈرگەنلەردىن بۇ ھالەتنى قايتا قوزغىتىدۇ. + + %1$s ئەپ (جەريان: %2$s) ئۆزلۈكىدىن ئىجرا قىلىدىغان مەجبۇرىي ھالەت تەدبىرىگە خىلاپلىق قىلدى. + + %1$s جەريان ئۆزلۈكىدىن ئىجرا قىلىدىغان مەجبۇرىي ھالەت تەدبىرىگە خىلاپلىق قىلدى + + Android يۈكسىلىۋاتىدۇ… + + + + %2$d ئەپتىن %1$d نى ئەلالاشتۇرۇۋاتىدۇ. + + + ئەپنى قوزغىتىۋاتىدۇ. + + قوزغىتىشنى تاماملاۋاتىدۇ. + + %1$s ئىجرا قىلىنىۋاتىدۇ + + چېكىلسە ئەپكە ئالمىشىدۇ + + ئەپ ئالماشتۇرامدۇ؟ + + باشقا بىر ئەپ ئىجرا قىلىنىۋاتىدۇ، يېڭى ئەپ ئىجرا قىلىش ئۈچۈن شۇ ئەپنى توختىتىشىڭىز كېرەك. + %1$s غا قايت + يېڭى ئەپنى قوزغاتما. + %1$s نى قوزغات + كونا ئەپنى ساقلىمايلا توختات. + + + + + + تېكىستكە ئېلىپ بېرىلىدىغان مەشغۇلاتنى تاللاڭ + + قوڭغۇراق ئاۋازى + + ۋاسىتە ئاۋازى + + كۆكچىشتا قويۇۋاتىدۇ + + ئۈنسىز قوڭغۇراق تەڭشىكى + + سۆزلىشىش ئاۋازى + + كۆكچىش ئىشلەتكەندىكى سۆزلىشىش ئاۋازى + + قوڭغۇراق ئاۋازى + + ئۇقتۇرۇش ئاۋازى + + ئاۋاز مىقدارى + + كۆكچىش ئاۋازى + + قوڭغۇراق ئاۋازى + + چاقىرىش ئاۋازى + + ۋاسىتە ئاۋازى + + ئۇقتۇرۇش ئاۋازى + + + + كۆڭۈلدىكى قوڭغۇراق ئاۋازى + + كۆڭۈلدىكى قوڭغۇراق ئاۋازى (%1$s) + + يوق + + قوڭغۇراق ئاۋازى + + نامەلۇم قوڭغۇراق ئاۋازى + + + ئىشلىتىلىشچان Wi-Fi تورى بار + + + + ئىشلىتىلىشچان Wi-Fi تورىنى ئاچ + + + + + %1$s + + + + Wi-Fi تورىغا باغلىنالمايدۇ + + ئىنتېرنېت باغلىنىشى ناچار + + + + + + Wi-Fi Direct + Wi-Fi Direct مەشغۇلاتىنى قوزغات. بۇ مەشغۇلات Wi-Fi خېرىدارى/قىزىق نۇقتا مەشغۇلاتىنى تاقايدۇ. + Wi-Fi Direct نى قوزغىتالمايدۇ + Wi-Fi Direct ئوچۇق + چېكىلسە تەڭشەيدۇ + قوشۇل + قوشۇلما + تەكلىپ يوللاندى + باغلىنىش تەكلىپى + يوللىغۇچى: + تاپشۇرۇپ ئالغۇچى: + لازىملىق PIN نى كىرگۈزۈڭ + PIN: + تاختا كومپيۇتېر %1$s غا باغلانغاندا Wi-FI باغلىنىشىنى ۋاقىتلىق ئۈزىدۇ + تېلېفون %1$s غا باغلانغاندا Wi-FI باغلىنىشىنى ۋاقىتلىق ئۈزىدۇ + + ھەرپ قىستۇر + + + + قىسقا ئۇچۇر يوللاۋاتىدۇ + + <b>%1$s</b> كۆپ مىقداردا قىسقا ئۇچۇر يوللاۋاتىدۇ. بۇ ئەپنىڭ قىسقا ئۇچۇر يوللاشنى داۋاملاشتۇرۇشىغا يول قويامسىز؟ + + يول قوي + + رەت قىل + + + + بىر ئۇچۇرنى <b>%1$s</b> ئۆزى <b>%2$s</b> غا يوللىماقچى. + + + + يوللا + + ۋاز كەچ + + تاللىشىمنى ئەستە تۇت + + كېيىن بۇنى تەڭشەكلەر › ئەپلەردىن ئۆزگەرتەلەيسىز + + ھەمىشە يول قوي* + + ھەرگىز يول قويما + + + + SIM كارتا چىقىرىۋېتىلدى + + + تامام + + SIM كارتا قوشۇلدى + + + قايتا قوزغات + + + ۋاقىت تەڭشەك + + چېسلا تەڭشەك + + تەڭشەك + + تامام + + + \"يېڭى: \" + + تەمىنلىگۈچى %1$s. + + ھىچقانداق ھوقۇق كېرەك ئەمەس + + بۇنىڭغا چىقىم پەيدا بولۇشى مۇمكىن + + + يۇقىرى سىغىملىق USB ساقلىغۇچ + + USB ئۇلاندى + + سىز USB ئارقىلىق كومپيۇتېرنى ئۇلىدىڭىز. كومپيۇتېر بىلەن ئاندىرويىد USB ساقلىغۇچ ئارىسىدا ھۆججەت كۆچۈرمەكچى بولسىڭىز، تۆۋەندىكى توپچىنى بېسىڭ. + + سىز USB ئارقىلىق كومپيۇتېرنى ئۇلىدىڭىز. كومپيۇتېر بىلەن ئاندىرويىد SD كارتا ئارىسىدا ھۆججەت كۆچۈرمەكچى بولسىڭىز، تۆۋەندىكى توپچىنى بېسىڭ. + + USB ساقلىغۇچنى ئاچ + + USB ساقلىغۇچنى USB ساقلىغۇچ سۈپىتىدە ئاچقاندا مەسىلە كۆرۈلدى. + + SD كارتىڭىزنى USB ساقلىغۇچ سۈپىتىدە ئاچقاندا مەسىلە كۆرۈلدى. + + USB ئۇلاندى + + ھۆججەتنى كومپيۇتېرغا كۆچۈرۈش ياكى كومپيۇتېردىن ساقلىغۇچقا كۆچۈرۈشنى تاللاڭ. + + USB ساقلىغۇچنى تاقا + + چېكىسلە USB ساقلىغۇچنى تاقايدۇ. + + + + USB ساقلىغۇچ ئىشلىتىلىۋاتىدۇ + + USB ساقلىغۇچنى تاقاشتىن ئىلگىرى، كومپيۇتېردىن Android نىڭ USB ساقلىغۇچنى ئېگەرسىزلەپ (\"قاڭقىت\")قانلىقىڭىزنى تەكشۈرۈڭ. + + USB ساقلىغۇچنى تاقاشتىن ئىلگىرى، كومپيۇتېردىن Android نىڭ SD ساقلىغۇچىسىنى ئېگەرسىزلەپ (\"قاڭقىت\")قانلىقىڭىزنى تەكشۈرۈڭ. + + USB ساقلىغۇچنى تاقا + + USB ساقلىغۇچنى تاقاشتا مەسىلە كۆرۈلدى. USB نى چىقىرىۋەتكەنلىكىڭىزنى تەكشۈرۈپ، قايتا سىناڭ. + + USB ساقلىغۇچنى تاقا + + ئەگەر سىز USB ساقلىغۇچنى ئاچسىڭىز، ئىشلىتىلىۋاتقان پىروگراممىلار ئىشتىن توختايدۇ ھەم USB نى تاقىغاندىن كېيىن ئاندىن قايتا ئىشلەيدۇ. + + USB مەشغۇلاتى مەغلۇب بولدى. + + جەزملە + + + + + + USB زاپچاس سۈپىتىدە باغلاندى + + + USB سازلاش ئۇلاندى + + چېكىلسە USB سازلاش چەكلىنىدۇ. + + + + + + + + + + قاتتىق دېتال + + ھەرپتاختا ئورۇنلاشتۇرۇشىنى تاللاڭ. + + چېكىپ ھەرپتاختا ئورۇنلاشتۇرۇلۇشىدىن بىرنى تاللاڭ. + ABCDEFGHIJKLMNOPQRSTUVWXYZ + 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ + "نامزات" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + تەكشۈرۈۋاتىدۇ… + + + + + + + + + + ماس كەلگۈدەك پائالىيەت تاپالمىدى + + + ئەپنىڭ ۋاستە چىقىرىش يولىنى ئۆزگەرتىپ باشقا سىرتقى ئۈسكۈنىگە چىقىرىشىغا يول قويىدۇ. + + + + + + قوش چىكىپ يىراق-يېقىنلىقىنى باشقۇرغىلى بولىدۇ. + + ئەپچە قوشالمىدى + + يۆتكەل + + ئىزدە + + يوللا + + كېيىنكى + + تامام + + ئالدىنقى + + ئىجرا قىل + + + + %s دا نومۇر بۇرا + + %s دا ئالاقەداش قۇر + + + + تۆۋەندىكى بىر ياكى بىرقانچە ئەپ سىزنىڭ ھىساباتىڭىزنى زىيارەت قىلىش ھوقۇقىنى تەلەپ قىلىۋاتىدۇ. + بۇ ئىلتىماسقا يول قويامسىز؟ + ئىلتىماسقا يول قوي + يول قوي + رەت قىل + ئىلتىماس قىلغان ھوقۇق + %s ھېساباتقا\nھوقۇق ئىلتىماس قىلدى. + + + + كىرگۈزگۈچ + + قەدەمداش + + قوشۇمچە ئىقتىدار + + تام قەغىزى + + تام قەغەز ئۆزگەرت + + ئۇقتۇرۇش تىڭشىغۇچ + + + + VPN ئاكتىپلاندى + + VPN نى %s ئاكتىپلىدى + + چېكىلسە تورنى باشقۇرىدۇ. + + %s غا باغلاندى. چېكىلسە تورنى باشقۇرىدۇ. + + ھەمىشە ئوچۇق VPN غا باغلىنىۋاتىدۇ… + + ھەمىشە ئوچۇق VPN غا باغلاندى + + ھەمىشە ئوچۇق VPN خاتالىقى + + چېكىلسە سەپلەيدۇ + + + ھۆججەت تاللاڭ + + ھۆججەت تاللانمىغان + + ئەسلىگە قايتۇر + + تاپشۇر + + + ماشىنا ھالىتى قوزغىتىلدى + چېكىلسە ماشىنا ھالىتىدىن چېكىنىدۇ. + + + USB غا باغلاش ياكى قىزىق نۇقتىنى قوزغىتىش + چېكىسلە تەڭشەيدۇ. + + قايت + كېيىنكى + + ئاتلا + + ماس كەلگىنى يوق + + بەتتىن ئىزدە + + + + + ماس كەلگىنى 1 + + + تامام + + + USB ساقلىغۇچنى ئۆچۈرۈۋاتىدۇ… + + SD كارتىنى ئۆچۈرۈۋاتىدۇ… + + + ھەمبەھىر + + ئىزدە + + توردىن ئىزدە + + كېيىنكىنى ئىزدە + + ئالدىنقىنى ئىزدە + + %s نىڭ ئورۇن ئىلتىماسى + + ئورۇن ئىلتىماسى + + ئىلتىماس قىلغۇچى %1$s (%2$s) + + ھەئە + + ياق + + ئۆچۈرۈش چېكىدىن ئېشىپ كەتتى + + ھېسابات %3$s نىڭ %1$d دانە %2$s غا ئائىت ئۆچۈرۈلگەن تۈرى بار. قانداق مەشغۇلات قىلىسىز؟ + + تۈرلەرنى ئۆچۈر. + + ئۆچۈرۈشتىن يېنىۋال. + + ھازىر ھېچقانداق مەشغۇلات قىلما. + + بىر ھېسابات تاللاڭ + "بىر ھېسابات قوش" + + ھېسابات قوش + + + چوڭايت + + كىچىكلەت + + %s نى چېكىپ بېسىڭ. + + ئۈستىگە سۈرۈلسە قىممىتى ئاشىدۇ، ئاستىغا سۈرۈلسە قىممىتى كېمىيىدۇ. + + + مىنۇت ئاشىدۇ + + مىنۇت كېمىيىدۇ + + سائەت ئاشىدۇ + + سائەت كېمىيىدۇ + + چ ك تەڭشەك + + چ ب تەڭشەك + + + ئاي ئاشىدۇ + + ئاي كېمىيىدۇ + + كۈن ئاشىدۇ + + كۈن كېمىيىدۇ + + يىل ئاشىدۇ + + يىل كېمىيىدۇ + + + + + Alt + + ۋاز كەچ + + ئۆچۈر + + تامام + + ھالەت ئۆزگەرت + + Shift + + Enter + + + ئەپ تاللاڭ + + قوزغىتالمايدىغىنى %s + + + ھەمبەھىر + + %s ئىلە ھەمبەھىر + + + "تۇتقۇچنى سۈرۈڭ. چېكىپ بېسىڭ." + + سۈرۈلسە قۇلۇپ ئاچىدۇ. + + قۇلاقلىق قىستۇرۇلغاندىلا ئاندىن ئىم ئاۋازىنى ئاڭلىغىلى بولىدۇ. + + چېكىت + + يولباشچى باش بەت + + ئۈستىگە يولباشچى + + تېخىمۇ كۆپ تاللانما + + %1$s, %2$s + + %1$s, %2$s, %3$s + + ئىچىدىكى ساقلىغۇچ + + SD كارتا + + + + + USB ساقلىغۇچ + + سانلىق مەلۇمات ئىشلىتىش ئاگاھلاندۇرۇشى + + چېكىلسە ئىشلىتىلىشى ۋە تەڭشەكلەرنى كۆرسىتىدۇ + + + + + + + 2G-3G سانلىق مەلۇمات ئېقىمىدىن ئېشىپ كەتتى + + 4G سانلىق مەلۇمات ئېقىمىدىن ئېشىپ كەتتى + + + Wi-Fi سانلىق مەلۇمات ئېقىمىدىن ئېشىپ كەتتى + + %s بەلگىلەنگەن چەكتىن ئېشىپ كەتتى + + تەگلىك سانلىق مەلۇماتى چەكلىمىگە ئۇچرايدۇ + + چېكىلسە چەكلىمە چىقىرىۋېتىلىدۇ. + + + بىخەتەرلىك گۇۋاھنامىسى + + بۇ گۇۋاھنامە كۈچكە ئىگە. + + تارقىتىلغۇچى: + + ئورتاق ئات: + + تەشكىل: + + تەشكىل بىرلىكى: + + تارقاتقۇچى: + + ئۈنۈملۈكلۈكى: + + تارقاتقان ۋاقىت: + + توشىدىغان ۋاقىت: + + تەرتىپ نومۇرى: + + بارماق ئىزى: + + SHA-256 بارماق ئىزى + + SHA-1 بارماق ئىزى + + ھەممىنى كۆرسەت + + پائالىيەت تاللاڭ + + ھەمبەھىر + + "« ،»" + + يوللاۋاتىدۇ… + + توركۆرگۈ قوزغىتامدۇ؟ + + چاقىرىشنى قوبۇللامسىز؟ + + ھەمىشە + + بىر قېتىملا + + + تاختا كومپيۇتېر + + + تېلېفون + + تىڭشىغۇچ + + لەڭگەر ياڭراتقۇ + + HDMI + + سىستېما + + كۆكچىش ئاۋازى + + سىمسىز كۆرسەتكۈچ + + + ئۈسكۈنىگە باغلىنىدۇ + + ئالمىشىش ئېكرانىدىن ئۈسكۈنىگە + + ئۈسكۈنىلەرنى ئىزدەۋاتىدۇ\u2026 + + تەڭشەكلەر + + ئۈز + + تەكشۈرۈۋاتىدۇ… + + باغلىنىۋاتىدۇ… + + ئىشلىتىلىشچان + + ئىشلەتكىلى بولمايدۇ + + ئىشلىتىلىۋاتىدۇ + + + ئىچكى ئېكران + + بۇ HDMI ئېكران + + دەستىلەنمە ئېكران #%1$d + + %1$s%2$dx%3$d%4$d dpi + + ، بىخەتەرلىك + + + ئەندىزە ئۇنتۇلغان + + ئەندىزە خاتا + + ئىم خاتا + + بۇ PIN خاتا + + %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + قۇلۇپ ئاچىدىغان ئەندىزە سىزىڭ + + كىرگۈزىدىغىنىڭىز SIM PIN + + كىرگۈزىدىغىنىڭىز PIN + + ئىم كىرگۈزۈڭ + + بۇ SIM كارتا توختىتىلغان. PUK كودى كىرگۈزۈلگەندىلا ئاندىن ئىشلەتكىلى بولىدۇ. مۇناسىۋەتلىك تەپسىلاتلار ئۈچۈن مۇلازىمەت تەمىنلىگۈچىڭىز بىلەن ئالاقە قىلىڭ. + + لازىملىق PIN كودىنى كىرگۈزۈڭ + + لازىملىق PIN كودىنى جەزملەڭ + + SIM كارتا قۇلۇپىنى ئېچىۋاتىدۇ… + + PIN كودى خاتا. + + 4-8 خانىلىق PIN نى كىرگۈزۈڭ. + + + توغرا PUK كودىنى قايتا كىرگۈزۈڭ. ئەگەر خاتا كىرگۈزۈشنىڭ قېتىم سانى بەك كۆپ بولۇپ كەتسە SIM كارتا مەڭگۈلۈك توختىتىلىدۇ. + + بۇ PIN كودى ماسلاشمىدى + + ئەندىزىسىنى سىناش قېتىم سانى بەك كۆپ بولۇپ كەتتى + + قۇلۇپ ئېچىشتا، Google ھېساباتىڭىزدا تىزىمغا كىرىڭ + + ئىشلەتكۈچى ئاتى(تورخەت) + + ئىم + + تىزىمغا كىر + + ئىشلەتكۈچى ئاتى ۋە ياكى ئىم خاتا. + + ئىشلەتكۈچى ئاتىڭىز ياكى ئىمنى ئۇنۇتتىڭىزمۇ؟\n\""google.com/accounts/recovery"\" زىيارەت قىلىڭ. + + ھېساباتنى تەكشۈرۈۋاتىدۇ… + + سىز PIN نى %d قېتىم خاتا كىرگۈزدىڭىز.\n\n %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + سىز قۇلۇپ ئېچىش ئىمنى %d قېتىم خاتا كىرگۈزدىڭىز.\n\n %d سېكۇنتتىن كېيىن قايتا سىناڭ. + سىز قۇلۇپ ئېچىش ئەندىزىسىنى %d قېتىم خاتا سىزدىڭىز.\n\n %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تاختا كومپيۇتېرنى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ. + + + سىز تېلېفون قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، تېلېفوننى زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتۇرىدۇ، ھەممە ئىشلەتكۈچى سانلىق مەلۇماتلىرى يوقىلىدۇ. + + سىز تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. تاختا كومپيۇتېر زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، + + + سىز تېلېفون قۇلۇپىنى ئېچىشنى %d قېتىم خاتا سىنىدىڭىز. تېلېفون زاۋۇتتىن چىققان ھالەتكە ئەسلىگە قايتىدۇ، + + سىز قۇلۇپ ئېچىش ئەندىزىسىنى %d قېتىم خاتا سىزدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما تورخەت ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تاختا كومپيۇتېر قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ.\n\nيەنە %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + + سىز قۇلۇپ ئېچىش ئەندىزىسىنى %d قېتىم خاتا سىزدىڭىز. ئەگەر %d قېتىم سىناپمۇ مۇۋەپپەقىيەتلىك بولمىسا، سىستېما تورخەت ھېساباتىڭىزدىكى تىزىمغا كىرىش ئۇچۇرى بىلەن تېلېفون قۇلۇپىنى ئېچىشنى تەلەپ قىلىدۇ.\n\nيەنە %d سېكۇنتتىن كېيىن قايتا سىناڭ. + + " — " + + چىقىرىۋەت + + + ئىككى بارماقنى بېسىپ تۇرغاندا قوشۇمچە ئىقتىدارنى قوزغىتىدۇ. + + قوشۇمچە ئىقتىدار قوزغىتىلدى. + + قوشۇمچە ئىقتىدار بىكار قىلىندى. + + نۆۋەتتىكى ئىشلەتكۈچى %1$s. + + + ئىگىدار + + خاتالىق + + + بۇ مەشغۇلاتنى بىر تەرەپ قىلىدىغان ئەپ يوق + قايتۇرۇۋال + + + ISO A0 + + ISO A1 + + ISO A2 + + ISO A3 + + ISO A4 + + ISO A5 + + ISO A6 + + ISO A7 + + ISO A8 + + ISO A9 + + ISO A10 + + ISO B0 + + ISO B1 + + ISO B2 + + ISO B3 + + ISO B4 + + ISO B5 + + ISO B6 + + ISO B7 + + ISO B8 + + ISO B9 + + ISO B10 + + ISO C0 + + ISO C1 + + ISO C2 + + ISO C3 + + ISO C4 + + ISO C5 + + ISO C6 + + ISO C7 + + ISO C8 + + ISO C9 + + ISO C10 + + خەت-چەك + + ھۆكۈمەت خەت-چەك + + Legal + + Junior Legal + + Ledger + + Tabloid + + Index Card 3 x 5 + + Index Card 4 x 6 + + Index Card 5 x 8 + + Monarch + + Quarto + + Foolscap + + ROC 8K + + ROC 16K + + PRC 1 + + PRC 2 + + PRC 3 + + PRC 4 + + PRC 5 + + PRC 6 + + PRC 7 + + PRC 8 + + PRC 9 + + PRC 10 + + PRC 16K + + 8 كەسلەم + + چوڭ 8 كەسلەم + + 16 كەسلەم + + JIS B10 + + JIS B9 + + JIS B8 + + JIS B7 + + JIS B6 + + JIS B5 + + JIS B4 + + JIS B3 + + JIS B2 + + JIS B1 + + JIS B0 + + JIS Exec + + Chou4 + + Chou3 + + Chou2 + + Hagaki + + Oufuku + + Kahu + + Kaku2 + + You4 + + يوچۇن بويىغا + + يوچۇن توغرىسىغا + + ۋاز كەچتى + + مەزمۇن يازغاندا خاتالىق كۆرۈلدى + + يوچۇن + + بېسىش مۇلازىمىتى قوزغىتىلمىغان + + %s مۇلازىمىتى ئورنىتىلدى + + چېكىلسە قوزغىتىدۇ + + باشقۇرغۇچى PIN نى كىرگۈزۈڭ + + كىرگۈزىدىغىنىڭىز PIN + + خاتا + + نۆۋەتتىكى PIN: + + يېڭى PIN + + يېڭى PIN جەزملە + + بىر PIN كودى قۇرۇپ، باشقىلارنىڭ ئۆزگەرتىشىنى چەكلەيدۇ + + PIN ماس كەلمىدى، قايتا سىناڭ. + + PIN بەك قىسقا. ئاز دېگەندە 4 خانە سان بولۇشى كېرەك. + + + + 1 سېكۇنتتىن كېيىن قايتا سىناڭ + + + سەل تۇرۇپ قايتا سىناڭ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ئاۋارە قىلماڭ + + + + + + + + + + + + + + + تېخىمۇ كۆپ تاللانما + + + + + + diff --git a/core/res/res/values-uk-watch/strings.xml b/core/res/res/values-uk-watch/strings.xml index 02e64664a7755..62d23d9cb6c91 100644 --- a/core/res/res/values-uk-watch/strings.xml +++ b/core/res/res/values-uk-watch/strings.xml @@ -21,4 +21,5 @@ "Додаток %1$d з %2$d." + "Датчики" diff --git a/core/res/res/values-uk/cm_strings.xml b/core/res/res/values-uk/cm_strings.xml new file mode 100644 index 0000000000000..03b49d785215e --- /dev/null +++ b/core/res/res/values-uk/cm_strings.xml @@ -0,0 +1,191 @@ + + + + + + Скріншот + + отримувати захищені SMS + + Дозволяє програмі отримувати захищені SMS. + + змінювати список захищених SMS + + Дозволяє програмі змінювати список адрес захищених SMS. + + Безпека + + Дозволи, пов\'язані з безпекою даних на пристрії. + + перегляд чорного списку + + Дозволяє програмі читати інформацію про список абонентів, від яких заблоковані вхідні дзвінки або повідомлення. + + зміна чорного списку + + Дозволяє програмі змінювати список абонентів, від яких заблоковані вхідні дзвінки або повідомлення. + + встановлення шпалер екрану блокування + + Дозволяє програмі міняти шпалери екрану блокування. + + Перезавантаження + + Поточний + + + Перезавантаження + + Recovery + + Bootloader + + Download + + Швидке перезавантаження + + Перезавантаження + + Ваш планшет перезавантажиться. + Ваш телефон перезавантажиться. + + Перезавантаження\u2026 + + Програму закрито + + ADB по мережі увімкнено + + ADB по USB та мережі увімкнено + + Торкніться, аби вимкнути налагодження. + + ADB - %1$s + USB та мережі + USB + Мережа + + Перехоплення запуску додатку + + %s не встановлено + + Пріоритет + Немає + + Точку доступу Wi-Fi вимкнено через зміну SIM-картки + + Вимкнути Wi-Fi + + увімк. або вимк. Сторожа Приватності + Програма може вибрати, чи буде друга програма працювати в захищеному режимі. Коли програму запущено в захищеному режимі, вона не отримає доступ до персональних даних, таких як контакти, повідомлення чи журнал дзвінків. + Сторож Приватності активний + %1$s буде заборонено доступ до персональних даних + Сторож Приватності + %1$s намагається %2$s. + + Запам\'ятати мій вибір + + доступ до камери + доступ до місцезнаходження + читати ваші сповіщення + активувати VPN + запуск при включені пристрою + видалити журнал викликів + видалити контакти + видалити MMS-повідомлення + видалити SMS-повідомлення + показувати вікна поверх + отримувати статистику використання програм + заборонити пристрою переходити в сплячий режим + робити телефонні дзвінки + змінювати дані календаря + змінювати дані списку дзвінків + змінювати вміст буфера обміну + змінювати дані контактів + змінювати системні налаштування + вимк./увімк. мікрофон + відтворювати аудіо + виводити сповіщення + project media + читати дані календаря + читати журнал дзвінків + читати буфер обміну + читати дані ваших контактів + читати ваші MMS-повідомлення + читати ваші SMS-повідомлення + отримувати SMS-повідомлення + запис аудіо + надсилати MMS-повідомлення + надсилати SMS-повідомлення + запуск при включені пристрою + показувати спливаючі сповіщення + увімк. або вимк. Bluetooth + Мобільні дані + увімк. вимк. NFC + Переключити Wi-Fi + керування гучністю будильника + керування аудіо-фокусом + керування гучністю Bluetooth + керування загальною гучністю + використовувати кнопки мультимедіа + керування гучністю медіа + керування гучністю сповіщень + керування гучністю дзвінка + використовувати вібровідгук + отримати управління гучністю при розмові + створити MMS-повідомлення + створити SMS-повідомлення + використовувати відбитки пальців + Додати голосове повідомлення + Доступ до стану телефону + Сканувати Wi-Fi мережі + зміна шпалер + Використовувати допоміжну структуру + Скріншот + Використовувати датчики + Широкомовні повідомлення + Фіктивне місцезнаходження + Зчитати дані з карти пам\'яті + Записати дані на карту пам\'яті + Увімкнути екран + Отримати інформацію про акаунти + Змінити стан Wi-Fi + отримати root-доступ + + Щоб відкріпити цей екран, торкніться й утримуйте кнопку назад. + + Немає під\'єднаного пристрою + %1$s підключений пристрій + %1$s підключених пристроїв + + + + Запуск програми заборонений + Запуск %1$s заблоковано. Натисніть, щоб ввести пароль і запустити програму. + + Батарея повністю заряджена + Від’єднайте зарядку задля покращення витривалості батареї. + + скинути статистику акумулятора + + Дозволити програмі скидати дані про використання акумулятора. + + diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index aee730df0c087..4c0c747636fc4 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -256,7 +256,7 @@ "Включає особисті дані, як-от номери кредитних карток і паролі." "вимикати чи змін. рядок стану" "Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи." - "рядок стану" + "відображатися як рядок стану" "Дозволяє програмі бути рядком стану." "розгорнути/згорн. рядок стану" "Дозволяє програмі розгортати чи згортати рядок стану." @@ -284,7 +284,7 @@ "Дозволяє програмі отримувати й обробляти WAP-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам." "отримувати запущені програми" "Дозволяє програмі отримувати інформацію про поточні й останні запущені завдання. Це може дозволити програмі виявляти інформацію про програми, які використовуються на пристрої." - "Керування власниками профілю та пристрою" + "керувати власниками профілів і пристроїв" "Додатки можуть вибирати власника профілю та пристрою." "змінювати порядок запущених програм" "Дозволяє програмі переміщувати завдання в активні чи фонові вікна. Програма може робити це без вашого відома." @@ -326,7 +326,7 @@ "Дозволяє програмі змінювати журнал викликів вашого планшетного ПК, включно з даними про вхідні та вихідні дзвінки. Шкідливі програми можуть використовувати це для стирання або зміни вашого журналу викликів." "Додаток може змінювати журнал викликів телевізора, зокрема дані про вхідні та вихідні дзвінки. Шкідливі додатки можуть використовувати це, щоб стирати чи змінювати ваш журнал викликів." "Дозволяє програмі змінювати журнал викликів вашого телефону, включно з даними про вхідні та вихідні дзвінки. Шкідливі програми можуть використовувати це для стирання або зміни вашого журналу викликів." - "датчики на тілі (як-от пульсометр)" + "отримувати дані з датчиків на тілі (наприклад, з пульсометра)" "Додаток має доступ до даних із датчиків, які відстежують фізичний стан, зокрема пульс." "читати події календаря, а також конфіденційну інформацію" "Дозволяє програмі читати всі події календаря, збережені в планшетному ПК, включно з подіями друзів або співробітників. Це може дозволити програмі надсилати або зберігати дані календаря, незалежно від конфіденційності або закритості." @@ -338,15 +338,15 @@ "Дозволяє програмі додавати, видаляти та змінювати події, які можна редагувати на телефоні, включно з подіями друзів або співробітників. Це може дозволити програмі надсилати повідомлення, які надходитимуть ніби від власників календарів, або змінювати події без відома власників." "отр. дост. до додат. команд пров. місцезн." "Додаток отримуватиме доступ до додаткових команд постачальника геоданих. Можливе втручання додатка в роботу GPS чи інших джерел геоданих." - "точне місцезнаходження (на основі GPS і мережі)" + "отримувати дані про точне місцезнаходження (на основі GPS і мережі)" "Дозволяє програмі дізнатися ваше точне місцезнаходження за допомогою системи глобального позиціонування (GPS) або мережевих джерел даних про місцезнаходження, як-от антен мобільного зв’язку та Wi-Fi. Щоб програма могла використовувати служби локації, вони мають бути ввімкнені та доступні для вашого пристрою. Програми можуть використовувати це, щоб визначити ваше приблизне місцезнаходження, і додатково споживати заряд акумулятора." - "приблизне місцезнаходження (на основі мережі)" + "отримувати дані про приблизне місцезнаходження (на основі мережі)" "Дозволяє програмі дізнатися ваше приблизне місцезнаходження. Місцезнаходження визначається службами локації за допомогою мережевих джерел даних про місцезнаходження, як-от антен мобільного зв’язку та Wi-Fi. Щоб програма могла використовувати служби локації, вони мають бути ввімкнені та доступні для вашого пристрою. Програми можуть використовувати це, щоб визначити ваше приблизне місцезнаходження." "змінювати налаштув-ня звуку" "Дозволяє програмі змінювати загальні налаштування звуку, як-от гучність і динамік, який використовується для виводу сигналу." "запис-ти аудіо" "Дозволяє програмі записувати звук за допомогою мікрофона. Такий дозвіл дає програмі змогу будь-коли записувати звук без вашого підтвердження." - "комунікація із SIM-картою" + "надсилати команди на SIM-карту" "Дозволяє програмі надсилати команди на SIM-карту. Це дуже небезпечно." "фотограф. та знімати відео" "Дозволяє програмі фотографувати та знімати відео за допомогою камери. Такий дозвіл дає програмі змогу будь-коли використовувати камеру без вашого підтвердження." @@ -384,7 +384,7 @@ "Дозволяє програмі отримувати список облікових записів, відомих телефону. Він може включати всі облікові записи, створені встановленими програмами." "переглядати мережеві з’єднання" "Дозволяє програмі переглядати інформацію про з’єднання з мережами, як-от дані про наявні та під’єднані мережі." - "повний доступ до мережі" + "отримувати повний доступ до мережі" "Додаток може створювати сокети мережі та використовувати спеціальні мережеві протоколи. Оскільки веб-переглядач та інші додатки самостійно реалізують функції надсилання даних в Інтернет, цей дозвіл надавати не обов’язково." "змінюв. підключення до мережі" "Дозволяє програмі змінювати стан під’єднання до мережі." @@ -404,7 +404,7 @@ "Дозволяє програмі налаштовувати телефон із локальним Bluetooth, а також знаходити віддалені пристрої та створювати з ними пару." "під’єднуватися та від’єднуватися від WiMAX" "Дозволяє програмі визначати, чи ввімкнено WiMAX, а також переглядати інформацію про будь-які під’єднані мережі WiMAX." - "Змінити стан WiMAX" + "змінювати стан WiMAX" "Дозволяє програмі під’єднувати планшетний ПК до мереж WiMAX і від’єднувати його від них." "Додаток може під’єднувати телевізор до мереж WiMAX і від’єднувати його від них." "Дозволяє програмі під’єднувати телефон до мереж WiMAX і від’єднувати його від них." @@ -487,7 +487,7 @@ "Програма може змінювати параметри калібрування сенсорного екрана. Ніколи не застосовується для звичайних програм." "отримувати доступ до сертифікатів DRM" "Дозволяє додатку надавати та використовувати сертифікати DRM. Ніколи не застосовується для звичайних додатків." - "Отримувати інформацію про стан функції Передавання даних Android." + "отримувати дані про стан функції Передавання даних Android" "Додаток може отримувати інформацію про поточне передавання даних за допомогою функції Передавання даних Android" "видаляти сертифікати DRM" "Власник може видаляти сертифікати DRM. Ніколи не застосовується для звичайних додатків." @@ -1105,11 +1105,11 @@ "Форматування…" "Не вставлено" "Відповідні дії не знайдено." - "Скеровувати вивід медіа-даних" + "вибирати маршрути виводу медіа-вмісту" "Дозволяє програмі скеровувати вивід медіа-даних на інші зовнішні пристрої." - "Зчитувати дані сеансів встановлення" + "отримувати дані про сеанси встановлення" "Дозволяє додатку читати дані сеансів встановлення. Додаток може бачити деталі про активні встановлення пакетів." - "Надсилання запитів на встановлення пакетів" + "запитувати дані про пакети встановлення" "Додаток зможе надсилати запити на встановлення пакетів." "Двічі торкніться, щоб керувати масштабом" "Не вдалося додати віджет." diff --git a/core/res/res/values-ur-rPK-watch/strings.xml b/core/res/res/values-ur-rPK-watch/strings.xml index 0fd24c9986023..6aea67aa38678 100644 --- a/core/res/res/values-ur-rPK-watch/strings.xml +++ b/core/res/res/values-ur-rPK-watch/strings.xml @@ -21,4 +21,5 @@ "ایپ %1$d از %2$d۔" + "سینسرز" diff --git a/core/res/res/values-ur-rPK/cm_strings.xml b/core/res/res/values-ur-rPK/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-ur-rPK/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml index 4e4d069b489ba..07cbfab1f022f 100644 --- a/core/res/res/values-ur-rPK/strings.xml +++ b/core/res/res/values-ur-rPK/strings.xml @@ -254,7 +254,7 @@ "اس میں ذاتی ڈیٹا جیسے کریڈٹ کارڈ نمبرز اور پاس ورڈز شامل ہیں۔" "اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں" "ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔" - "حیثیت بار" + "بطور اسٹیٹس بار کام لیں" "ایپ کو اسٹیٹس بار بننے کی اجازت دیتا ہے۔" "حیثیت بار پھیلائیں/سکیڑیں" "ایپ کو اسٹیٹس بار پھیلانے یا سکیڑنے کی اجازت دیتا ہے۔" @@ -282,7 +282,7 @@ "‏ایپ کو WAP پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس اجازت میں آپ کو مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھنے یا انہیں حذف کرنے کی اہلیت شامل ہے۔" "چل رہی ایپس کی بازیافت کریں" "ایپ کو موجودہ اور حالیہ چل رہے ٹاسکس کے بارے میں معلومات بازیافت کرنے کی اجازت دیتا ہے۔ یہ ایپ کو اس بارے میں معلومات دریافت کرنے کی اجازت دے سکتا ہے کہ آلہ پر کون سی ایپلیکیشنز استعمال کی جاتی ہیں۔" - "پروفائل اور آلہ کے مالکان کا نظم کریں" + "پروفائل اور آلہ کے مالکان کا نظم کریں" "ایپس کو پروفائل کے مالکان اور آلہ کے مالک کو سیٹ کرنے کی اجازت دیتا ہے۔" "چل رہی ایپس کو دوبارہ ترتیب دیں" "ایپ کو پیش منظر یا پس منظر میں ٹاسکس کو منتقل کرنے کی اجازت دیتا ہے۔ ایپ آپ کے ان پٹ کے بغیر یہ کام کرسکتی ہے۔" @@ -324,7 +324,7 @@ "ایپ کو آپ کے ٹیبلٹ کی کال لاگ، بشمول آنے والی اور باہر جانے والی کالوں کے بارے میں ڈیٹا میں ترمیم کرنے کی اجازت دیتا ہے۔ نقصان دہ ایپس آپ کی کال لاگ مٹانے یا اس میں ترمیم کرنے کیلئے اسے استعمال کرسکتی ہیں۔" "‏انکمنگ اور آؤٹ گوئنگ کالز کے بارے میں ڈیٹا سمیت، ایپ کو آپ کے TV کے کال لاگ میں ترمیم کرنے کی اجازت دیتا ہے۔ نقصان دہ ایپس آپ کی کال لاگ مٹانے یا اس میں ترمیم کرنے کیلئے اسے استعمال کرسکتی ہیں۔" "ایپ کو آپ کے فون کی کال لاگ، بشمول آنے والی اور باہر جانے والی کالوں کے بارے میں ڈیٹا میں ترمیم کرنے کی اجازت دیتا ہے۔ نقصان دہ ایپس آپ کی کال لاگ مٹانے یا اس میں ترمیم کرنے کیلئے اسے استعمال کرسکتی ہیں۔" - "باڈی سینسرز (جیسے دل کی دھڑکن کے مانیٹرز)" + "باڈی سینسرز تک رسائی حاصل کریں (جیسے حرکت قلب شرح مانیٹرز)" "ان سینسرز سے ڈیٹا تک رسائی حاصل کرنے کی اجازت دیتی ہے جو آپ کی حرکت قلب کی شرح جیسی آپ کی فزیکل صورتحال کو مانیٹر کرتے ہیں۔" "کیلنڈر ایونٹس کے ساتھ رازداری کی معلومات پڑھیں" "ایپ کو آپ کے، بشمول آپ کے دوستوں یا ساتھی کارکنان کے ٹیبلٹ پر اسٹور کردہ سبھی کیلنڈر ایونٹس کو پڑھنے کی اجازت دیتا ہے۔ یہ ایپ کو رازداری یا حساسیت سے قطع نظر آپ کے کیلنڈر ڈیٹا کا اشتراک یا اسے محفوظ کرنے کی اجازت دیتا ہے۔" @@ -336,15 +336,15 @@ "ایپ کو وہ ایونٹس جن میں آپ اپنے فون پر ترمیم کرسکتے ہیں، بشمول دوسروں یا ساتھی کارکنوں کے ایونٹس شامل کرنے، ہٹانے، تبدیل کرنے کی اجازت دیتا ہے۔ یہ ایپ کو ایسے پیغامات بھیجنے کی جو کیلنڈر مالکان کی جانب سے آئے ہوئے معلوم پڑتے ہیں یا مالکان کی جانکاری کے بغیر ایونٹس میں ترمیم کرنے کی اجازت دے سکتا ہے۔" "اضافی مقام فراہم کنندہ کی کمانڈز تک رسائی حاصل کریں" "‏ایپ کو اضافی مقام فراہم کنندہ کی کمانڈز تک رسائی حاصل کرنے کی اجازت دیتی ہے۔ یہ ایپ کو GPS یا دوسرے مقام کے مآخذ کے عمل کے ساتھ مداخلت کرنے کی اجازت دے سکتی ہے۔" - "‏قطعی مقام (GPS اور نیٹ ورک پر مبنی)" + "‏قطعی مقام تک رسائی حاصل کریں (GPS اور نیٹ ورک پر مبنی)" "‏ایپ کو گلوبل پوزیشننگ سسٹم (GPS) یا نیٹ ورک کے مقام کے مآخذ جیسے سیل ٹاورز اور Wi-Fi کا استعمال کرکے آپ کا درست مقام حاصل کرنے کی اجازت دیتا ہے۔ ان مقام کی سروسز کا آن ہونا اور ایپ کو انہیں استعمال کرنے کیلئے آپ کے آلے پر دستیاب ہونا ضروری ہے۔ ایپس تخمینی طور پر آپ کے محل وقوع کا تعین کرنے کیلئے اسے استعمال کرسکتی ہیں اور بیٹری کی اضافی قوت صرف کرسکتی ہیں۔" - "تخمینی مقام (نیٹ ورک پر مبنی)" + "تخمینی مقام تک رسائی حاصل کریں (نیٹ ورک پر مبنی)" "‏ایپ کو آپ کا تخمینی مقام حاصل کرنے کی اجازت دیتا ہے۔ یہ مقام نیٹ ورک کے مقام کے مآخذ جیسے سیل ٹاورز اور Wi-Fi کا استعمال کرکے مقام کی سروسز کے ذریعہ اخذ کیا جاتا ہے۔ ان مقام کی سروسز کا آن ہونا اور آپ کے آلے پر دستیاب ہونا ضروری ہے تاکہ ایپ انہیں استعمال کرسکے۔ ایپس تخمینی طور پر آپ کے محل وقوع کا تعین کرنے کیلئے اسے استعمال کر سکتی ہیں۔" "اپنے آڈیو کی ترتیبات کو تبدیل کریں" "ایپ کو مجموعی آڈیو ترتیبات جیسے والیوم اور آؤٹ پٹ کیلئے جو اسپیکر استعمال ہوتا ہے اس میں ترمیم کرنے کی اجازت دیتا ہے۔" "آڈیو ریکارڈ کریں" "ایپ کو مائکرو فون سے آڈیو ریکارڈ کرنے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو کسی بھی وقت آپ کی تصدیق کے بغیر آڈیو ریکارڈ کرنے کی اجازت دیتی ہے۔" - "سم مواصلت" + "‏SIM کو ہدایات بھیجیں" "‏ایپ کو SIM کو کمانڈز بھیجنے کی اجازت دیتا ہے۔ یہ بہت خطرناک ہے۔" "تصاویر لیں اور ویڈیوز بنائیں" "ایپ کو کیمرے سے تصویریں لینے اور ویڈیوز بنانے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو آپ کی تصدیق کے بغیر کسی بھی وقت کیمرا استعمال کرنے کی اجازت دیتی ہے۔" @@ -382,7 +382,7 @@ "ایپ کو فون کو معلوم اکاؤنٹس کی فہرست حاصل کرنے کی اجازت دیتا ہے۔ اس میں آپ کی انسٹال کردہ ایپلیکیشنز کے ذریعہ بنائے گئے کوئی بھی اکاؤنٹس شامل ہوسکتے ہیں۔" "نیٹ ورک کنکشنز دیکھیں" "ایپ کو نیٹ ورک کنکشنز کے بارے میں معلومات دیکھنے کی اجازت دیتا ہے جیسے کون سے نیٹ ورکس موجود اور مربوط ہیں۔" - "پورے نیٹ ورک تک رسائی" + "پورے نیٹ ورک تک رسائی حاصل کریں" "ایپ کو نیٹ ورک ساکیٹس بنانے اور حسب ضرورت نیٹ ورک پروٹوکولز استعمال کرنے کی اجازت دیتا ہے۔ براؤزر اور دوسری ایپلیکیشنز انٹرنیٹ کو ڈیٹا بھیجنے کا ذریعہ فراہم کرتے ہیں، لہذا انٹرنیٹ کو ڈیٹا بھیجنے کیلئے یہ اجازت درکار نہیں ہوتی ہے۔" "نیٹ ورک کنیکٹوٹی تبدیل کریں" "ایپ کو نیٹ ورک کنیکٹوٹی کی حالت تبدیل کرنے کی اجازت دیتا ہے۔" @@ -402,7 +402,7 @@ "ایپ کو مقامی بلوٹوتھ فون کنفیگر کرنے اور ریموٹ آلات دریافت کرنے اور ان کے ساتھ جوڑا بنانے کی اجازت دیتا ہے۔" "‏WiMAX سے مربوط اور غیر مربوط کریں" "‏ایپ کو یہ تعین کرنے کی کہ آیا WiMAX فعال ہے اور کسی مربوط WiMAX نیٹ ورکس کے بارے میں معلومات کا تعین کرنے کی اجازت دیتا ہے۔" - "‏WiMAX کی حیثیت تبدیل کریں" + "‏WiMAX کی حیثیت تبدیل کریں" "‏ایپ کو WiMAX نیٹ ورکس سے ٹیبلٹ کو مربوط اور ٹیبلٹ کو منقطع کرنے کی اجازت دیتا ہے۔" "‏ایپ کو WiMAX نیٹ ورکس سے TV کو منسلک اور TV کو غیر منسلک کرنے کی اجازت دیتا ہے۔" "‏ایپ کو WiMAX نیٹ ورکس سے فون کو مربوط اور فون کو منقطع کرنے کی اجازت دیتا ہے۔" @@ -485,7 +485,7 @@ "ایپ کو ٹچ اسکرین کے کیلیبریشن پیرامیٹرز میں ترمیم کرنے کی اجازت دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہيں ہونی چاہئے۔" "‏DRM سرٹیفکیٹس تک رسائی حاصل کریں" "‏ایک ایپ کو DRM سرٹیفکیٹس فراہم کرنے اور ان کا استعمال کرنے کی اجازت دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہیں ہوتی ہے۔" - "‏Android Beam منتقلی کی صورت حال موصول کریں" + "‏Android Beam منتقلی کی صورت حال موصول کریں" "‏اس ایپلیکیشن کو Android Beam کی حالیہ منتقلیوں کے بارے میں معلومات موصول کرنے کی اجازت دیتا ہے" "‏DRM سرٹیفکیٹس کو ہٹائیں" "‏ایک ایپلیکیشن کو DRM سرٹیفکیٹس کو ہٹانے کی اجازت دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہیں ہونی چاہیے۔" @@ -1091,11 +1091,11 @@ "فارمیٹ کیا جا رہا ہے…" "دلچسپی نہیں ہے" "کوئی مماثل سرگرمیاں نہیں ملیں۔" - "میڈیا آؤٹ پٹ کی سمت طے کریں" + "میڈیا آؤٹ پٹ کی سمت طے کریں" "کسی ایپلیکیشن کو دوسرے خارجی آلات تک میڈیا آؤٹ پٹ کا راستہ بنانے کی اجازت دیتا ہے۔" - "انسٹال سیشنز پڑھیں" + "انسٹال سیشنز پڑھیں" "ایک ایپلیکیشن کو انسٹال سیشنز پڑھنے کی اجازت دیتا ہے۔ یہ اسے فعال پیکیج انسٹالیشنز کے بارے میں تفصیلات دیکھنے کی اجازت دیتا ہے۔" - "پیکجز انسٹال کرنے کی درخواست کریں" + "پیکجز انسٹال کرنے کی درخواست کریں" "ایک ایپلیکیشن کو پیکجز انسٹال کرنے کی اجازت دیتی ہے۔" "زوم کے کنٹرول کیلئے دو بار ٹچ کریں" "ویجٹس کو شامل نہیں کرسکا۔" diff --git a/core/res/res/values-uz-rUZ-watch/strings.xml b/core/res/res/values-uz-rUZ-watch/strings.xml index 7abd603e029e1..4b633e871ef27 100644 --- a/core/res/res/values-uz-rUZ-watch/strings.xml +++ b/core/res/res/values-uz-rUZ-watch/strings.xml @@ -21,4 +21,5 @@ "%2$ddan %1$d ilova." + "Sensorlar" diff --git a/core/res/res/values-uz-rUZ/cm_strings.xml b/core/res/res/values-uz-rUZ/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-uz-rUZ/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml index 45ebbf363b62d..2f07347178a66 100644 --- a/core/res/res/values-uz-rUZ/strings.xml +++ b/core/res/res/values-uz-rUZ/strings.xml @@ -62,8 +62,8 @@ "SIM kartani blokdan chiqarish uchun PUK2 raqamini kiriting." "Ishlamadi, SIM/RUIM qulfni yoqish." - Yana %d ta muvaffaqiyatsiz urinishdan so‘ng SIM-karta qulflanadi. - Yana %d ta muvaffaqiyatsiz urinishdan so‘ng SIM-karta qulflanadi. + Yana %d ta muvaffaqiyatsiz urinishdan so‘ng SIM karta qulflanadi. + Yana %d ta muvaffaqiyatsiz urinishdan so‘ng SIM karta qulflanadi. "IMEI" "MEID" @@ -254,7 +254,7 @@ "Bunga kredit karta raqamlari va parollar kabi shaxsiy ma’lumotlar kiradi." "holat panelini o‘zgartirish yoki o‘chirish" "Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin." - "holat paneli" + "holat qatorida ko‘rinishi" "Ilova holat qatorining o‘rnini egallashi mumkin." "holat panelini yoyish/yig‘ish" "Ilova holat panelini yoyishi va yig‘ishi mumkin." @@ -282,7 +282,7 @@ "Ilovaga WAP xabarlarni qabul qilish va ularni qayta ishlash uchun ruxsat beradi. Ushbu huquq sizga ko‘rsatmasdan sizga yuborilgan xabarlarni kuzatish yoki o‘chirish xususiyatiga ham ega." "ishlab turgan ilovalar to‘g‘risida ma’lumot olish" "Ilovaga hozirda va so‘nggi ishga tushirilgan vazifalar haqida to‘liq ma’lumot olishiga ruxsat beradi. Bu ilovaga qurilmadagi ishlatilayotgan ilovalar haqidagi ma’lumotlarga ega bo‘lishiga ruxsat berishi mumkin." - "Profil va qurilma egalarini boshqarish" + "profil va qurilma egalarini boshqarish" "Ilovaga profil egalari va qurilma egalarini aniqlash uchun ruxsat beradi." "ishlab turgan ilovalarni qayta tartiblash" "Ilovalarga vazifalarni old va orqa fonga o‘tkazish uchun ruxsat beradi. Ilova buni sizning yordamingizsiz bajarishi mumkin." @@ -324,7 +324,7 @@ "Ilovaga planshetingizdagi qo‘ng‘iroq jurnallari, kiruvchi va chiquvchi qo‘ng‘rioqlar haqidagi ma’lumotlarni o‘zgartirishga ruxsat beradi. Zararli ilovalar bundan qo‘ng‘iroqlar jurnalini o‘zgartirish yoki o‘chirish uchun foydalanishi mumkin." "Ilovaga televizoringizdagi qo‘ng‘iroqlar jurnali, kirish va chiqish qo‘ng‘rioqlari haqidagi ma’lumotlarni o‘zgartirish huquqini beradi. Zararli ilovalar undan qo‘ng‘iroqlar jurnalini o‘zgartirish yoki o‘chirish uchun foydalanishi mumkin." "Ilovaga telefoningizdagi qo‘ng‘iroq jurnallari, kiruvchi va chiquvchi qo‘ng‘rioqlar haqidagi ma’lumotlarni o‘zgartirishga ruxsat beradi. Zararli ilovalar bundan qo‘ng‘iroqlar jurnalini o‘zgartirish yoki o‘chirish uchun foydalanishi mumkin." - "sezgichlar (m-n, yurak urishi)" + "tana sezgichlari (m-n, yurak urishi sensori) ma’lumotlaridan foydalanishga ruxsat" "Ilovaga sezgichlardan olingan jismoniy holatingiz haqidagi ma’lumotlarni, masalan, yurak urishini kuzatish uchun ruxsat beradi." "taqvimdagi tadbirlarni maxfiy ma’lumotlari bilan birga o‘qish" "Ilovaga planshetingizda joylashgan va do‘stlaringiz yoki hamkasblaringiz tomonidan qo‘shilgan barcha taqvim tadbirlarini o‘qishga ruxsat beradi. Bu ilovaga maxfiyligi va muhimligidan qat’iy nazar taqvim ma’lumotlaringizni ulashish yoki saqlashga ruxsat berishi mumkin." @@ -336,15 +336,15 @@ "Ilovaga telefoningizda o‘zgartirishingiz mumkin bo‘lgan, shuningdek, do‘stlaringiz va hamkasblaringizning tadbirlarini qo‘shish, o‘chirish va o‘zgartirish uchun ruxsat beradi. Bu ilovaga go‘yoki taqvim egalari nomidan kelgan xabarlarni jo‘natishga yoki egasiga bildirmasdan tadbirlarni o‘zgartirishga ruxsat berishi mumkin." "qo‘shimcha manzillarga kirish buyruqlari" "Ilovaga qo‘shimcha joylashuv xizmati buyruqlaridan foydalanishga ruxsat beradi. Uning yordamida ilova GPS yoki boshqa joylashuv ma’lumoti manbalarining ishlashiga xalaqit qilishi mumkin." - "aniq joylashuv (GPS va tarmoqqa asoslanib)" + "aniq joylashuv (GPS va tarmoqqa asoslanib) ma’lumotlaridan foydalanishga ruxsat" "Ilovaga global joylashuvni aniqlash tizimi (GPS) yoki Wi-Fi va uyali tarmoq antennalari kabi tarmoq joylashuv manbalaridan foydalanib, aniq joylashuvingizni topishga ruxsat beradi. Ushbu joylashuv xizmatlari yoqib qo‘yilgan bo‘lishi va qurilmangizdagi ilovaga ulardan foydalanish uchun mavjud bo‘lishi kerak. Ilovalar bundan foydalanib, sizning joylashuvingizni aniqlaydi. Bu batareya quvvatini ko‘proq sarflaydi." - "yaqin manzil (tarmoq)" + "taxminiy joylashuv (tarmoq asosida) ma’lumotlaridan foydalanishga ruxsat" "Ilovaga sizning taxminiy joylashuvingizni topishga ruxsat beradi. Ushbu joylashuv Wi-Fi va uyali tarmoq antennalari kabi tarmoq joylashuv manbalaridan foydlanuvchi joylashuv xizmatlari orqali aniqlanadi. Ushbu joylashuv xizmatlari yoqib qo‘yilgan bo‘lishi va qurilmangizdagi ilovaga ulardan foydalanish uchun mavjud bo‘lishi kerak. Ilovalar bundan foydalanib, sizning taxminiy joylashuvingizni aniqlaydi." "audio sozlamalaringizni o‘zgartirish" "Ilovalarga tovush va ovoz chiqarish uchun foydalaniladigan karnay kabi global audio sozlamalarini o‘zgartirish uchun ruxsat beradi." "ovoz yozib olish" "Ilovaga mikrofon yordamida audio yozish uchun ruxsat beradi. Bu huquq ilovaga ruxsatingizsiz audio fayllarni yozib olishga ruxsat beradi." - "sim orqali ulanish" + "SIM kartaga buyruqlar yuborish" "Dasturga SIM kartaga buyruqlar jo‘natishga ruxsat beradi. Bu juda ham xavfli." "rasmga tushirish va videoga olish" "Ilovaga kameradan foydalanib rasm va videoga olishga ruxsat beradi. Bu ruxsat ilovaga sizdan tasdiqlashni so‘ramasdan kameradan foydalanishga imkon beradi." @@ -382,7 +382,7 @@ "Ilovaga telefondagi hisoblar ro‘yxatini olishga ruxsat beradi. Bunga siz o‘rnatgan ilovalar tomonidan yaratilgan har qanday hisoblar kirishi mumkin." "tarmoq ulanishlarini ko‘rish" "Ilovaga mavjud va ulangan tarmoqlar kabi tarmoqqa ulanishlar haqidagi ma’lumotni ko‘rish imkonini beradi." - "butun tarmoqqa ruxsat" + "to‘liq tarmoqdan foydalanish ruxsatiga ega" "Ilovaga tarmoq ulagichlarini yaratish va odatdagi tarmoq protokollaridan foydalanishga ruxsat beradi. Brauzer va boshqa ilovalar internetga ma’lumot jo‘natish uchun imkoniyat yaratadi. Natijada, internetga ma’lumot jo‘natish uchun bu ruxsat talab qilinmaydi." "tarmoqqa ulanishni o‘zgartirish" "Ilova tarmoqqa ulanish holatini o‘zgartirishi mumkin." @@ -402,7 +402,7 @@ "Ilova Bluetooth funksiyali mahalliy telefon sozlamalarini sozlashi hamda masofadan turib qurilmalarni aniqlash va ular bilan juftlashishni amalga oshirishi mumkin." "WiMAX’ga ulanish va uzish" "Ilovaga har qanday ulangan WiMAX tarmoqlari haqida va yoqilgan WiMAX tarmoqlarini aniqlashga ruxsat beradi." - "WiMAX holatini o‘zgartirish" + "WiMAX holatini o‘zgartirish" "Ilovaga planshetni WiMAX tarmoqlariga ulashga va ulardan uzishga ruxsat beradi." "Ilovaga televizorni WiMAX tarmoqlariga ulash va ulardan uzish huquqini beradi." "Ilovaga telefonni WiMAX tarmoqlariga ulashga va ulardan uzishga ruxsat beradi." @@ -485,7 +485,7 @@ "Ilova sensorli ekranning muvozanat ko‘rsatkichlarini o‘zgartirishi mumkin. Oddiy ilovalar uchun talab qilinmaydi." "DRM sertifikatlariga kirish" "Ilova DRM sertifikatlarini sinxronlashi va ulardan foydalanishi mumkin. Ushbu ruxsatnoma faqat maxsus ilovalar uchun talab qilinadi." - "Android Beam uzatish holatini olish" + "Android Beam o‘tkazmasi holati haqidagi ma’lumotlarni olish" "Ushbu ilovaga joriy Android Beam uzatishlari haqida ma\'lumotlarni olish ruxsati berilsin." "DRM sertifikatlarini o‘chirib tashlash" "Ilovaga DRM sertifikatlarini o‘chirib tashlash uchun ruxsat beradi. Oddiy ilovalar uchun talab qilinmaydi." @@ -661,14 +661,14 @@ "Qaytadan urining" "Qaytadan urining" "Yuzni tanitib qulfni ochishga urinish miqdoridan oshib ketdi" - "SIM-karta yo‘q" - "Planshetingizga SIM-karta yo‘q." - "Televizorda SIM-karta yo‘q." - "Telefoningizga SIM-karta yo‘q." + "SIM karta yo‘q" + "Planshetingizga SIM karta yo‘q." + "Televizorda SIM karta yo‘q." + "Telefoningizda SIM karta yo‘q." "SIM kartani soling." - "SIM-karta solinmagan yoki uni o‘qib bo‘lmaydi. SIM-kartani soling." - "Foydalanib bo‘lmaydigan SIM-karta." - "SIM-kartangiz butunlay bloklab qo‘yilgan.\n Yangi SIM-karta olish uchun aloqa operatoringiz bilan bog‘laning." + "SIM karta solinmagan yoki uni o‘qib bo‘lmaydi. SIM kartani soling." + "Foydalanib bo‘lmaydigan SIM karta." + "SIM kartangiz butunlay bloklab qo‘yilgan.\n Yangi SIM karta olish uchun aloqa operatoringiz bilan bog‘laning." "Avvalgi musiqa" "Keyingi musiqa" "To‘xtatib turish" @@ -678,10 +678,10 @@ "Oldinga o‘tkazish" "Faqat favqulodda qo‘ng‘iroqlar" "Tarmoq qulflangan" - "SIM-karta PUK kod bilan qulflangan." + "SIM karta PUK kod bilan qulflangan." "Foydalanuvchi qo‘llanmasiga qarang yoki Abonentlarni qo‘llab-quvvatlash markaziga murojaat qiling." - "SIM-karta qulflangan." - "SIM-karta qulfdan chiqarilmoqda…" + "SIM karta qulflangan." + "SIM karta qulfdan chiqarilmoqda…" "Siz chizmali kalitni %d marta noto‘g‘ri kiritdingiz. \n\n%d soniyadan so‘ng qayta urining." "Siz parolni %d marta noto‘g‘ri kiritdingiz. \n\n %d soniyadan so‘ng qayta urining." "Siz PIN-kodni %d marta noto‘g‘ri kiritdingiz. \n\n %d soniyadan so‘ng qayta urining." @@ -1003,10 +1003,10 @@ "Siz buni keyinroq sozlamalar > ilovalar menusidan o‘zgartirishingiz mumkin" "Doimo ruxsat berilsin" "Hech qachon ruxsat berilmasin" - "SIM-karta olib tashlandi" + "SIM karta olib tashlandi" "Mobil tarmoqqa ulanish uchun faol SIM kartani joylang va qurilmani o‘chirib yoqing." "Tayyor" - "SIM-karta qo‘shildi" + "SIM karta qo‘shildi" "Mobil tarmoqqa ulanish uchun qurilmangizni o‘chirib yoqing." "O‘chirib-yoqish" "Vaqtni o‘rnatish" @@ -1091,11 +1091,11 @@ "Formatlanmoqda…" "Kiritilmagan" "Hech qanday mos faoliyat topilmadi." - "Media chiqishni yo‘naltirish" + "media chiqishni yo‘naltirish" "Ilovaga media chiqish ovozini boshqa tashqi qurilmalarga yo‘naltirish uchun ruxsat beradi." - "O‘rnatilgan seanslarni o‘qish" + "o‘rnatish seansi ma’lumotlarini o‘qish" "Ilovaga o‘rnatilgan seanslarni o‘qish uchun ruxsat beradi. Bu unga faol paket o‘rnatmalari haqidagi ma’lumotlarni ko‘rish imkonini beradi." - "Paketlarni o‘rnatish so‘rovini yuborish" + "paketlarni o‘rnatish so‘rovini yuborish" "Ilovaga paketlarni o‘rnatish so‘rovini yuborish imkonini beradi." "Masshtabni o‘zgartirish uchun ikki marta bosing" "Vidjet qo‘shilmadi." @@ -1209,8 +1209,8 @@ "%1$s, %2$s" "%1$s, %2$s, %3$s" "Ichki xotira" - "SD-karta" - "%s SD-kartasi" + "SD karta" + "%s SD kartasi" "USB xotira" "%s USB xotira qurilmasi" "USB xotira" @@ -1286,10 +1286,10 @@ "SIM kartaning PIN kodini kiriting" "PIN kodni tering" "Parol kiriting" - "SIM-karta hozir o‘chirilgan. Davom etish uchun PUK kodni kiriting. To‘liqroq ma’lumot olish uchun tarmoq operatori bilan bog‘laning." + "SIM karta hozir o‘chirilgan. Davom etish uchun PUK kodni kiriting. To‘liqroq ma’lumot olish uchun tarmoq operatori bilan bog‘laning." "So‘ralgan PIN kodni kiriting" "So‘ralgan PIN kodni tasdiqlang" - "SIM-karta qulfi ochilmoqda…" + "SIM karta qulfi ochilmoqda…" "Xato PIN kodi." "4 tadan 8 ta raqamgacha bo‘lgan PIN kodni kiriting." "PUK kod 8 ta raqam bo‘lishi shart." diff --git a/core/res/res/values-vi-watch/strings.xml b/core/res/res/values-vi-watch/strings.xml index f419bdf86a78a..f6c970de53cc8 100644 --- a/core/res/res/values-vi-watch/strings.xml +++ b/core/res/res/values-vi-watch/strings.xml @@ -21,4 +21,5 @@ "Ứng dụng %1$d / %2$d." + "Cảm biến" diff --git a/core/res/res/values-vi/cm_strings.xml b/core/res/res/values-vi/cm_strings.xml new file mode 100644 index 0000000000000..035cb15691428 --- /dev/null +++ b/core/res/res/values-vi/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + Ảnh chụp màn hình + + nhận SMS được bảo vệ + + Cho phép ứng dụng nhận tin nhắn SMS đến được bảo vệ. + + thay đổi danh sách SMS được bảo vệ + + Cho phép ứng dụng sửa đổi danh sách địa chỉ SMS được bảo vệ. + + Bảo mật + + Quyền liên quan đến thông tin bảo mật của thiết bị. + + đọc danh sách đen của điện thoại + + Cho phép ứng dụng đọc thông tin về các số điện thoại bị chặn cuộc gọi hoặc tin nhắn đến. + + thay đổi danh sách đen của điện thoại + + Cho phép ứng dụng thay đổi số điện thoại bị chặn cuộc gọi hoặc tin nhắn đến. + + thiết lập hình nền bảo vệ phím + + Cho phép ứng dụng thay đổi hình nền màn hình khoá. + + Khởi động lại + + Hiện tại + + + Khởi động lại + + Phục hồi + + Trình nạp khởi động + + Tải về + + Khởi động lại nhanh + + Khởi động lại + + Máy tính bảng của bạn sẽ khởi động lại. + Điện thoại của bạn sẽ khởi động lại. + + Đang khởi động lại\u2026 + + Ứng dụng đã tắt + + Đã bật ADB qua mạng + + Đã kích hoạt ADB qua USB & mạng + + Chạm để tắt gỡ lỗi. + + ADB - %1$s + USB & mạng + USB + Mạng + + chặn ứng dụng khởi chạy + + %s chưa được cài đặt + + Ưu tiên + Không có + + Đã vô hiệu hóa điểm truy cập WiFi vì thay đổi đăng ký SIM + + Tắt WiFi + + bật hoặc tắt Bảo vệ quyền riêng tư + Cho phép ứng dụng thay đổi ứng dụng khác chạy với Bảo vệ quyền riêng tư. Khi một ứng dụng chạy với Bảo vệ quyền riêng tư, nó sẽ không có quyền truy cập dữ liệu cá nhân như số liên lạc, nhật ký cuộc gọi hoặc tin nhắn. + Bảo vệ quyền riêng tư đang hoạt động + %1$s sẽ không thể truy cập dữ liệu cá nhân + Bảo vệ quyền riêng tư + %1$s muốn %2$s. + + Nhớ lựa chọn của tôi + + truy cập máy ảnh + truy cập vị trí của bạn + đọc thông báo của bạn + kích hoạt VPN + chạy lúc khởi động + xóa nhật ký cuộc gọi của bạn + xóa danh bạ của bạn + xoá tin nhắn MMS của bạn + xoá tin nhắn SMS của bạn + hiện cửa sổ trên cùng + lấy thống kê sử dụng ứng dụng + giữ thiết bị của bạn sáng + thực hiện cuộc gọi điện thoại + cập nhật lịch của bạn + cập nhật nhật kí cuộc gọi + sửa đổi bảng tạm + cập nhật danh bạ của bạn + cập nhật thiết lập hệ thống + tắt/bật tiếng micro + phát âm thanh + gửi thông báo + chiếu đa phương tiện + đọc lịch của bạn + đọc nhật kí cuộc gọi + đọc bảng tạm + đọc danh bạ của bạn + đọc tin nhắn MMS của bạn + đọc tin nhắn SMS của bạn + nhận tin nhắn SMS + ghi âm + gửi tin nhắn MMS + gửi tin nhắn SMS + chạy lúc khởi động + hiện thông báo nhanh + bật/tắt Bluetooth + bật/tắt dữ liệu di động + bật/tắt NFC + bật/tắt WiFi + điều khiển âm lượng báo thức + điều khiển trọng tâm âm thanh + điều khiển âm lượng Bluetooth + điều khiển âm lượng tổng thể + sử dụng nút phương tiện + điều khiển âm lượng đa phương tiện + điều khiển âm lượng thông báo + điều khiển âm lượng nhạc chuông + dùng phản hồi xúc giác + điều khiển âm lượng cuộc gọi thoại + soạn tin nhắn MMS + soạn tin nhắn SMS + sử dụng vân tay + thêm một thư thoại + truy nhập tình trạng điện thoại + quét mạng Wi-Fi + thay đổi hình nền + sử dụng cấu trúc hỗ trợ + chụp ảnh màn hình + sử dụng cảm biến cơ thể + đọc tin nhắn quảng bá + giả vị trí của bạn + đọc bộ nhớ ngoài + ghi bộ nhớ ngoài + bật màn hình + lấy thông tin tài khoản thiết bị + thay đổi tình trạng Wi-Fi + lấy quyền truy cập root + + Để bỏ ghim màn hình này, hãy chạm và giữ phím Quay lại. + + Không có thiết bị kết nối + %1$s thiết bị đã kết nối + %1$s thiết bị đã kết nối + + + + Đã chặn khởi chạy hoạt động + %1$s được bảo vệ ngăn không khởi chạy. Chạm để xác thực và khởi chạy ứng dụng. + + Pin đã được sạc đầy + Rút cáp sạc ra khỏi thiết bị của bạn để cải thiện tuổi thọ pin. + + đặt lại thống kê pin + + Cho phép ứng dụng thiết lập lại dữ liệu cấp thấp của mức tiêu thụ pin hiện tại. + + Thẻ SIM đã thay đổi + Chạm để thiết lập các ưu tiên mặc định cho thẻ SIM + diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index b2a66082b387b..b4536abc46542 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -254,7 +254,7 @@ "Bao gồm dữ liệu cá nhân chẳng hạn như số thẻ tín dụng và mật khẩu." "vô hiệu hóa hoặc sửa đổi thanh trạng thái" "Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống." - "thanh trạng thái" + "trở thành thanh trạng thái" "Cho phép ứng dụng trở thành thanh trạng thái." "mở rộng/thu gọn thanh trạng thái" "Cho phép ứng dụng mở rộng hoặc thu gọn thanh trạng thái." @@ -282,7 +282,7 @@ "Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Quyền này bao gồm khả năng giám sát hoặc xóa tin nhắn được gửi cho bạn mà không hiển thị chúng cho bạn." "truy xuất các ứng dụng đang chạy" "Cho phép ứng dụng truy xuất thông tin về các công việc đã và đang chạy gần đây. Việc này có thể cho phép ứng dụng phát hiện thông tin về những ứng dụng nào đã được sử dụng trên thiết bị." - "Quản lý chủ sở hữu thiết bị và hồ sơ" + "quản lý chủ sở hữu thiết bị và hồ sơ" "Cho phép ứng dụng đặt chủ sở hữu hồ sơ và chủ sở hữu thiết bị." "sắp xếp lại những ứng dụng đang chạy" "Cho phép ứng dụng di chuyển công việc sang nền trước và nền sau. Ứng dụng có thể thực hiện việc này mà không cần bạn nhập." @@ -324,7 +324,7 @@ "Cho phép ứng dụng sửa đổi nhật ký cuộc gọi trên máy tính bảng của bạn, bao gồm dữ liệu về các cuộc gọi đến và gọi đi. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi nhật ký cuộc gọi của bạn." "Cho phép ứng dụng sửa đổi nhật ký cuộc gọi trên TV của bạn, bao gồm dữ liệu về các cuộc gọi đến và gọi đi. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi nhật ký cuộc gọi của bạn." "Cho phép ứng dụng sửa đổi nhật ký cuộc gọi trên điện thoại của bạn, bao gồm dữ liệu về các cuộc gọi đến và gọi đi. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi nhật ký cuộc gọi của bạn." - "cảm biến cơ thể (như máy đo nhịp tim)" + "truy cập cảm biến cơ thể (như máy đo nhịp tim)" "Cho phép ứng dụng truy cập dữ liệu từ bộ cảm biến giám sát tình trạng sức khỏe của bạn, ví dụ như nhịp tim." "đọc các sự kiện lịch và thông tin bí mật" "Cho phép ứng dụng đọc tất cả các sự kiện trên lịch được lưu trữ trên máy tính bảng của bạn, bao gồm các sự kiện trên lịch của bạn bè hoặc đồng nghiệp. Việc này có thể cho phép ứng dụng chia sẻ hoặc lưu dữ liệu lịch của bạn, bất kể tính bí mật hay tính nhạy cảm là gì." @@ -336,15 +336,15 @@ "Cho phép ứng dụng thêm, xóa, thay đổi các sự kiện mà bạn có thể sửa đổi trên điện thoại của mình, bao gồm những sự kiện của bạn bè hoặc đồng nghiệp. Việc này có thể cho phép ứng dụng gửi tin nhắn dường như đến từ chủ sở hữu lịch hoặc sửa đổi các sự kiện mà chủ sở hữu không biết." "truy cập vào các lệnh của nhà cung cấp vị trí bổ sung" "Cho phép ứng dụng truy cập vào các lệnh của nhà cung cấp vị trí bổ sung. Điều này có thể cho phép ứng dụng can thiệp vào hoạt động của Hệ thống định vị toàn cầu (GPS) hoặc các nguồn vị trí khác." - "vị trí chính xác (dựa vào mạng và GPS)" + "truy cập vị trí chính xác (dựa vào mạng và GPS)" "Cho phép ứng dụng nhận vị trí chính xác của bạn bằng cách sử dụng Hệ thống định vị toàn cầu (GPS) hoặc các nguồn vị trí mạng chẳng hạn như tháp điện thoại di động và Wi-Fi. Các dịch vụ vị trí này phải được bật và có sẵn cho thiết bị của bạn để ứng dụng sử dụng chúng. Ứng dụng có thể sử dụng dịch vụ vị trí này để xác định vị trí của bạn và có thể tiêu hao thêm nguồn pin." - "vị trí gần đúng (dựa vào mạng)" + "truy cập vị trí gần đúng (dựa vào mạng)" "Cho phép ứng dụng nhận vị trí gần đúng của bạn. Vị trí này có được là do dịch vụ vị trí sử dụng các nguồn vị trí mạng chẳng hạn như tháp điện thoại di động và Wi-Fi. Các dịch vụ vị trí này phải được bật và có sẵn cho thiết bị của bạn để ứng dụng sử dụng chúng. Ứng dụng có thể sử dụng dịch vụ vị trí này để xác định vị trí gần đúng của bạn." "thay đổi cài đặt âm thanh của bạn" "Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và loa nào được sử dụng cho thiết bị ra." "ghi âm" "Cho phép ứng dụng ghi âm bằng micrô. Quyền này cho phép ứng dụng ghi âm bất kỳ lúc nào mà không cần sự xác nhận của bạn." - "liên lạc qua sim" + "gửi lệnh đến SIM" "Cho phép ứng dụng gửi lệnh đến SIM. Việc này rất nguy hiểm." "chụp ảnh và quay video" "Cho phép ứng dụng chụp ảnh và quay video bằng máy ảnh. Quyền này cho phép ứng dụng sử dụng máy ảnh bất kỳ lúc nào mà không cần sự xác nhận của bạn." @@ -382,7 +382,7 @@ "Cho phép ứng dụng nhận danh sách các tài khoản mà điện thoại biết. Danh sách này có thể bao gồm bất kỳ tài khoản nào được tạo bởi các ứng dụng mà bạn đã cài đặt." "xem kết nối mạng" "Cho phép ứng dụng xem thông tin về các kết nối mạng như mạng nào thoát và mạng nào được kết nối." - "quyền truy cập mạng đầy đủ" + "có quyền truy cập mạng đầy đủ" "Cho phép ứng dụng tạo cổng mạng và sử dụng giao thức mạng tùy chỉnh. Trình duyệt và các ứng dụng khác cung cấp các phương tiện để gửi dữ liệu lên internet do đó không yêu cầu quyền này để gửi dữ liệu lên internet." "thay đổi kết nối mạng" "Cho phép ứng dụng thay đổi trạng thái kết nối mạng." @@ -402,7 +402,7 @@ "Cho phép ứng dụng định cấu hình điện thoại Bluetooth cục bộ cũng như phát hiện và ghép nối với các thiết bị từ xa." "kết nối và ngắt kết nối khỏi WiMAX" "Cho phép ứng dụng xác định liệu WiMAX đã được bật chưa và thông tin về bất kỳ mạng WiMAX nào được kết nối." - "Thay đổi trạng thái WiMAX" + "thay đổi trạng thái WiMAX" "Cho phép ứng dụng kết nối máy tính bảng và ngắt kết nối máy tính bảng khỏi mạng WiMAX." "Cho phép ứng dụng kết nối TV với và ngắt kết nối TV khỏi mạng WiMAX." "Cho phép ứng dụng kết nối điện thoại và ngắt kết nối điện thoại khỏi mạng WiMAX." @@ -485,7 +485,7 @@ "Cho phép ứng dụng sửa đổi các thông số hiệu chỉnh của màn hình cảm ứng. Không cần cho ứng dụng thông thường." "truy cập chứng chỉ DRM" "Cho phép ứng dụng cung cấp và sử dụng chứng chỉ DRM. Không cần thiết cho các ứng dụng thông thường." - "Nhận trạng thái chuyển của Android Beam" + "nhận trạng thái chuyển của Android Beam" "Cho phép ứng dụng này nhận thông tin về các lần chuyển hiện tại của Android Beam" "xóa chứng chỉ DRM" "Cho phép ứng dụng xóa chứng chỉ DRM. Không cần thiết cho các ứng dụng thông thường." @@ -1091,11 +1091,11 @@ "Đang định dạng…" "Chưa được lắp" "Không tìm thấy hoạt động nào phù hợp." - "Định tuyến thiết bị ra phương tiện" + "định tuyến thiết bị ra phương tiện" "Cho phép ứng dụng định tuyến thiết bị ra phương tiện đến các thiết bị bên ngoài khác." - "Đọc phiên cài đặt" + "đọc phiên cài đặt" "Cho phép ứng dụng đọc phiên cài đặt. Thao tác này sẽ cho phép ứng dụng xem chi tiết về gói cài đặt đang hoạt động." - "Yêu cầu gói cài đặt" + "yêu cầu gói cài đặt" "Cho phép ứng dụng yêu cầu cài đặt gói." "Chạm hai lần để kiểm soát thu phóng" "Không thể thêm tiện ích." diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml index 90448023bbf84..919519e5832ae 100644 --- a/core/res/res/values-watch/config.xml +++ b/core/res/res/values-watch/config.xml @@ -51,4 +51,10 @@ 0.1 + + + false + + + true diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml index 4ea2b52c5b4db..dde8b2e3ec508 100644 --- a/core/res/res/values-watch/strings.xml +++ b/core/res/res/values-watch/strings.xml @@ -23,4 +23,7 @@ App %1$d of %2$d. + + + Sensors diff --git a/core/res/res/values-zh-rCN-watch/strings.xml b/core/res/res/values-zh-rCN-watch/strings.xml index 9c9e49d69c0d6..9ab0e3925b1d9 100644 --- a/core/res/res/values-zh-rCN-watch/strings.xml +++ b/core/res/res/values-zh-rCN-watch/strings.xml @@ -21,4 +21,5 @@ "应用:%1$d / %2$d。" + "传感器" diff --git a/core/res/res/values-zh-rCN/cm_strings.xml b/core/res/res/values-zh-rCN/cm_strings.xml new file mode 100644 index 0000000000000..6f522d17b4f17 --- /dev/null +++ b/core/res/res/values-zh-rCN/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + 屏幕截图 + + 接收受保护的短信 + + 允许应用接收受保护的短信。 + + 修改受保护的短信列表 + + 允许应用修改受保护的短信地址列表。 + + 安全 + + 与设备安全信息相关的权限。 + + 读取手机黑名单 + + 允许应用读取有关被阻止来电或信息的电话号码的信息。 + + 更改手机黑名单 + + 允许应用更改被阻止来电或信息的电话号码。 + + 设置锁屏壁纸 + + 允许应用更改锁屏壁纸。 + + 重启 + + 当前 + + + 重启 + + 恢复模式 + + 引导程序 + + 下载模式 + + 软重启 + + 重启 + + 您的平板电脑将会重启。 + 您的手机将会重启。 + + 正在重启\u2026 + + 应用已被终止 + + 网络 ADB 调试已启用 + + USB 和网络 ADB 调试已启用 + + 触摸以禁用调试。 + + ADB - %1$s + USB & 网络 + USB + 网络 + + 拦截应用启动 + + %s 尚未被安装 + + 优先级 + + + 由于 SIM 卡订阅改变,已禁用 Wi-Fi 热点。 + + 关闭 Wi-Fi + + 启用或禁用隐私防护 + 允许应用更改其他应用是否启用隐私防护。当一个应用运行时启用了隐私防护,它将不能访问个人数据,如联系人、通话记录、短信。 + 隐私防护激活 + %1$s 将不能访问个人数据 + 隐私防护 + %1$s 希望 %2$s + + 记住我的选择 + + 存取相机 + 访问你的地理位置信息 + 读取通知 + 激活一个 VPN + 开机自启动 + 删除您的所有通话记录 + 删除您的联系人 + 删除您的彩信 + 删除您的短信 + 在顶部绘制窗口 + 获取应用使用情况统计 + 保持设备唤醒 + 拨打电话 + 更新你的日历 + 更新通话记录 + 修改剪贴板 + 更新你的联系人 + 更新系统设置 + 麦克风静音 / 解除静音 + 播放音频 + 发出通知 + 放映媒体 + 读取你的日历 + 读取你的通话记录 + 读取你的剪贴板 + 读取你的联系人 + 读取你的彩信 + 读取你的短信 + 接收短信 + 录音 + 发送彩信 + 发送短信 + 开机自启动 + 显示提示信息 + 开启蓝牙 + 切换移动数据 + 切换 NFC + 开关 Wi-Fi + 控制闹铃音量 + 控制音频焦点 + 控制蓝牙音量 + 控制主音量 + 使用媒体按钮 + 控制媒体音量 + 控制通知音量 + 控制铃声音量 + 使用触觉反馈 + 控制语音通话音量 + 编写彩信 + 编写短信 + 使用指纹 + 添加语音邮件 + 访问电话状态 + 扫描 Wi-Fi 网络 + 更改壁纸 + 使用协助结构 + 屏幕截图 + 使用身体传感器 + 读取蜂窝广播 + 模拟位置 + 读取外部存储 + 写入外部存储 + 打开屏幕 + 获取设备帐户 + 更改 Wi-Fi 状态 + 获取 Root 权限 + + 要取消固定此屏幕,触摸并按住返回键。 + + 没有已连接设备 + %1$s 个已连接的设备 + %1$s 个已连接的设备 + + + + 已阻止活动启动 + %1$s 正被保护防止启动。点击以认证并启动应用。 + + 电池已完全充满 + 请将您的设备从充电器断开,以便获得更长的电池寿命。 + + 重置电池统计信息 + + 允许应用重置当前低电量电池使用数据。 + + SIM 卡已更换 + 触摸以重置 SIM 卡首选项 + diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 20bff46a05da9..700cbfd7b18f3 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -254,7 +254,7 @@ "包含个人数据,例如信用卡号和密码。" "停用或修改状态栏" "允许应用停用状态栏或者增删系统图标。" - "状态栏" + "用作状态栏" "允许以状态栏形式显示应用。" "展开/收拢状态栏" "允许应用展开或折叠状态栏。" @@ -282,7 +282,7 @@ "允许该应用接收和处理 WAP 消息。此权限包括监视发送给您的消息或删除发送给您的消息而不向您显示的功能。" "检索正在运行的应用" "允许该应用检索近期运行的和当前正在运行的任务的相关信息。此权限可让该应用了解设备上使用了哪些应用。" - "管理个人资料和设备所有者" + "管理个人资料和设备所有者" "允许应用设置个人资料所有者和设备所有者。" "对正在运行的应用重新排序" "允许该应用将任务移动到前台和后台。该应用可能不经您的命令自行执行此操作。" @@ -324,7 +324,7 @@ "允许该应用修改平板电脑的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。" "允许应用修改电视的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。" "允许该应用修改手机的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。" - "人体传感器(如心跳速率检测器)" + "访问身体传感器(如心率监测器)" "允许该应用存取监测您身体状况的传感器所收集的数据,例如您的心率。" "读取日历活动和机密信息" "允许该应用读取您平板电脑上存储的所有日历活动,包括朋友或同事的活动。此权限可让该应用分享或保存您的日历数据,而不论这些数据是否属于机密或敏感内容。" @@ -336,15 +336,15 @@ "允许该应用添加、删除、更改您可在手机上修改的活动,包括朋友或同事的活动。此权限可让该应用冒充日历所有者发送消息,或在所有者不知情的情况下修改活动。" "获取额外的位置信息提供程序命令" "允许该应用使用其他的位置信息提供程序命令。此权限使该应用可以干扰GPS或其他位置信息源的运作。" - "精确位置(基于GPS和网络)" + "访问确切位置信息(以 GPS 和网络为依据)" "允许该应用通过全球定位系统(GPS)或网络位置信息源(例如基站和WLAN)获取您的精确位置信息。您必须在设备上开启这些位置信息服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。" - "大致位置(基于网络)" + "访问大致位置信息(以网络为依据)" "允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和WLAN)的位置信息服务。您必须在设备上开启这些位置信息服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。" "更改您的音频设置" "允许该应用修改全局音频设置,例如音量和用于输出的扬声器。" "录音" "允许该应用使用麦克风录制音频。此权限可让该应用不经您的确认即可随时录制音频。" - "SIM卡通信" + "向 SIM 卡发送命令" "允许应用向SIM卡发送命令(此权限具有很高的危险性)。" "拍摄照片和视频" "允许该应用使用相机拍摄照片和视频。此权限可让该应用随时使用相机,而无需您的确认。" @@ -376,13 +376,13 @@ "允许应用更改平板电脑的时区。" "允许应用更改电视的时区。" "允许应用更改手机的时区。" - "查找设备上的帐户" - "允许该应用获取平板电脑已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。" - "允许应用获取电视已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。" - "允许该应用获取手机已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。" + "查找设备上的帐号" + "允许该应用获取平板电脑已知的帐号列表,其中可能包括由已安装的应用创建的所有帐号。" + "允许应用获取电视已知的帐号列表,其中可能包括由已安装的应用创建的所有帐号。" + "允许该应用获取手机已知的帐号列表,其中可能包括由已安装的应用创建的所有帐号。" "查看网络连接" "允许该应用查看网络连接的相关信息,例如存在和连接的网络。" - "完全的网络访问权限" + "拥有完全的网络访问权限" "允许该应用创建网络套接字和使用自定义网络协议。浏览器和其他某些应用提供了向互联网发送数据的途径,因此应用无需该权限即可向互联网发送数据。" "更改网络连接性" "允许应用更改网络连接的状态。" @@ -402,7 +402,7 @@ "允许应用配置本地蓝牙手机,并允许其查找远程设备且与之配对。" "建立或中断 WiMAX 网络连接" "允许该应用确定是否启用了 WiMAX 以及连接的任何 WiMAX 网络的相关信息。" - "更改 WiMAX 状态" + "更改 WiMAX 状态" "允许该应用建立和断开平板电脑与 WiMAX 网络之间的连接。" "允许应用建立和断开电视与 WiMAX 网络之间的连接。" "允许该应用建立和断开手机与 WiMAX 网络之间的连接。" @@ -436,11 +436,11 @@ "指纹图标" "读取同步设置" - "允许该应用读取某个帐户的同步设置。例如,此权限可确定“联系人”应用是否与某个帐户同步。" + "允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。" "启用和停用同步" - "允许该应用修改某个帐户的同步设置。例如,此权限可用于在“联系人”应用与某个帐户之间启用同步。" + "允许该应用修改某个帐号的同步设置。例如,此权限可用于在“联系人”应用与某个帐号之间启用同步。" "读取同步统计信息" - "允许该应用读取某个帐户的同步统计信息,包括同步活动历史记录和同步数据量。" + "允许该应用读取某个帐号的同步统计信息,包括同步活动历史记录和同步数据量。" "读取您的USB存储设备中的内容" "读取您的SD卡中的内容" "允许应用读取您USB存储设备中的内容。" @@ -485,7 +485,7 @@ "允许应用修改触摸屏的校准参数。普通应用绝不需要此权限。" "访问DRM证书" "允许应用配置和使用DRM证书。普通应用绝不需要此权限。" - "接收Android Beam的传输状态" + "接收 Android Beam 的传输状态" "允许此应用接收Android Beam当前传输内容的相关信息" "移除DRM证书" "允许应用移除DRM证书。普通应用绝不需要此权限。" @@ -696,9 +696,9 @@ "您已经%d次错误地尝试解锁手机。手机现在将恢复为出厂默认设置。" "%d秒后重试。" "忘记了图案?" - "帐户解锁" + "帐号解锁" "图案尝试次数过多" - "要解除锁定,请使用您的Google帐户登录。" + "要解除锁定,请使用您的Google帐号登录。" "用户名(电子邮件)" "密码" "登录" @@ -1091,11 +1091,11 @@ "正在格式化…" "未插入" "未找到匹配的活动。" - "更改媒体输出线路" + "更改媒体输出线路" "允许该应用将媒体输出线路更改到其他外部设备。" - "读取安装会话" + "读取安装会话" "允许应用读取安装会话。这样,应用将可以查看有关当前软件包安装的详情。" - "请求安装文件包" + "请求安装文件包" "允许应用请求安装文件包。" "触摸两次可进行缩放控制" "无法添加小部件。" @@ -1108,13 +1108,13 @@ "执行" "拨打电话\n%s" "创建电话号码为\n%s 的联系人" - "以下一个或多个应用请求获得相应权限,以便在当前和以后访问您的帐户。" + "以下一个或多个应用请求获得相应权限,以便在当前和以后访问您的帐号。" "您是否同意此请求?" "访问权限请求" "允许" "拒绝" "权限请求" - "应用对帐户 %s\n 提出权限请求。" + "应用对帐号 %s\n 提出权限请求。" "您目前是在工作资料之外使用此应用" "您目前是在工作资料内使用此应用" "输入法" @@ -1140,9 +1140,6 @@ "触摸可退出车载模式。" "网络共享或热点已启用" "触摸可进行设置。" - "没有设备已连接。" - ""%1$s"个设备已连接。" - ""%1$s"个设备已连接。" "上一步" "下一步" "跳过" @@ -1166,13 +1163,13 @@ "是" "否" "超出删除限制" - "帐户 %3$s 在进行“%2$s”同步时删除了 %1$d 项内容。您要如何处理这些删除的内容?" + "帐号 %3$s 在进行“%2$s”同步时删除了 %1$d 项内容。您要如何处理这些删除的内容?" "删除这些内容" "撤消删除" "目前不进行任何操作" - "选择帐户" - "添加帐户" - "添加帐户" + "选择帐号" + "添加帐号" + "添加帐号" "增大" "减小" "触摸 %s 次并按住。" @@ -1299,13 +1296,13 @@ "请重新输入正确的PUK码。如果尝试错误次数过多,SIM卡将永久停用。" "PIN码不匹配" "图案尝试次数过多" - "要解锁,请登录您的Google帐户。" + "要解锁,请登录您的Google帐号。" "用户名(电子邮件地址)" "密码" "登录" "用户名或密码无效。" "忘记了用户名或密码?\n请访问 ""google.com/accounts/recovery""。" - "正在检查帐户…" + "正在检查帐号…" "您已经%d次输错了PIN码。\n\n请在%d秒后重试。" "您已连续 %d 次输错密码。\n\n请在 %d 秒后重试。" "您已连续 %d 次画错解锁图案。\n\n请在 %d 秒后重试。" @@ -1315,9 +1312,9 @@ "您已经%d次错误地尝试解锁平板电脑。平板电脑现在将恢复为出厂默认设置。" "您已经 %d 次错误地尝试解锁电视。电视现在将恢复为出厂默认设置。" "您已经%d次错误地尝试解锁手机。手机现在将恢复为出厂默认设置。" - "您已连续 %d 次画错解锁图案。如果再尝试 %d 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。\n\n请在 %d 秒后重试。" - "您已连续 %d 次画错解锁图案。如果再尝试 %d 次后仍不成功,系统就会要求您使用电子邮件帐户解锁电视。\n\n请在 %d 秒后重试。" - "您已连续 %d 次画错解锁图案。如果再尝试 %d 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。\n\n请在 %d 秒后重试。" + "您已连续 %d 次画错解锁图案。如果再尝试 %d 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 %d 秒后重试。" + "您已连续 %d 次画错解锁图案。如果再尝试 %d 次后仍不成功,系统就会要求您使用电子邮件帐号解锁电视。\n\n请在 %d 秒后重试。" + "您已连续 %d 次画错解锁图案。如果再尝试 %d 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 %d 秒后重试。" " — " "删除" "要将音量调高到推荐水平以上吗?\n\n长时间保持高音量可能会损伤听力。" diff --git a/core/res/res/values-zh-rHK-watch/strings.xml b/core/res/res/values-zh-rHK-watch/strings.xml index 3b5fb8ec2e523..72311ff95e558 100644 --- a/core/res/res/values-zh-rHK-watch/strings.xml +++ b/core/res/res/values-zh-rHK-watch/strings.xml @@ -21,4 +21,5 @@ "應用程式 (%1$d/%2$d)" + "感應器" diff --git a/core/res/res/values-zh-rHK/cm_strings.xml b/core/res/res/values-zh-rHK/cm_strings.xml new file mode 100644 index 0000000000000..7a738ea192d81 --- /dev/null +++ b/core/res/res/values-zh-rHK/cm_strings.xml @@ -0,0 +1,149 @@ + + + + + + 螢幕截圖 + + 接收受保護的短訊 + + 允許應用程式接收受保護的短訊 + + 修改受保護的短訊清單 + + + 安全性 + + 與裝置安全性資訊相關的權限。 + + 讀取手機黑名單 + + 允許應用程式讀取關於被封鎖來電或訊息的電話號碼的資訊。 + + 更改手機黑名單 + + 允許應用程式更改被封鎖來電或訊息的電話號碼。 + + 設定鎖定畫面牆紙 + + 允許應用程式更改鎖定畫面牆紙。 + + 重新啟動 + + + + 重新啟動 + + 修復模式 + + 啟動載入程式 (Bootloader) + + 下載 + + 軟重新啟動 + + + 您的平板電腦將重新啟動。 + 您的電話將重新啟動。 + + 正在重新啟動\u2026 + + + 網絡 ADB 偵錯 + + USB & 網絡 ADB 偵錯 + + 觸碰以停用調試。 + + + + 未安裝 %s + + 優先級 + + + + + 啟用或停用私隱守衛 + 允許應用程式變更其他應用程式執行時是否啟用私隱守衛。當應用程式執行時啟用了私隱守衛,應用程式將無法存取個人資料,例如:聯絡人、通話記錄或訊息。 + 私隱守衛啟用 + %1$s 將無法存取個人資料 + 私隱守衛 + %1$s想要%2$s + + 記住我的選擇 + + 存取相機 + 存取您的位置 + 讀取您的通知 + 刪除短訊 + 在頂部拖動視窗 + 獲取應用程式使用狀況統計 + 讓您的裝置保持清醒 + 撥出電話 + 更新您的日曆 + 更新通話記錄 + 修改剪貼簿 + 更新您的聯絡人 + 更新系統設定 + 麥克風靜音/解除靜音 + 播放音頻 + 發出通知 + 媒體投映 + 讀取剪貼簿 + 讀取您的聯絡人 + 讀取您的多媒體短訊 + 讀取您的短訊 + 接收短訊 + 錄音 + 發送多媒體短訊 + 發送短訊 + 開機時啟動 + 顯示彈出訊息 + 切換藍牙 + 切換 NFC + 控制鬧鐘音量 + 控制音訊焦點 + 控制藍牙音量 + 控制主音量 + 使用媒體按鈕 + 控制媒體音量 + 控制通知音量 + 控制鈴聲音量 + 使用觸控震動 + 控制語音通話音量 + 撰寫多媒體短訊 + 編寫短訊 + + 要解鎖此螢幕,觸碰並按住返回鍵。 + + 沒有已連接的裝置 + + + + + + 重設電池統計資訊 + + 允許應用程式重設目前低電量的電池使用數據。 + + diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index ef52d00309647..8b46ae9fb4531 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -254,7 +254,7 @@ "包括個人資料,如信用卡號碼和密碼。" "停用或修改狀態列" "允許應用程式停用狀態列,並可新增或移除系統圖示。" - "狀態列" + "成為狀態列" "允許應用程式以狀態列顯示。" "展開/收合狀態列" "允許應用程式展開或收合狀態列。" @@ -282,7 +282,7 @@ "允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。" "擷取執行中的應用程式" "允許應用程式擷取有關目前和最近執行的工作的資訊。如此一來,應用程式或可找出裝置上所使用應用程式的相關資訊。" - "管理您的設定檔和裝置擁有者" + "管理個人檔案和裝置擁有者" "允許應用程式設定檔案擁有者和裝置擁有者。" "為執行中的應用程式重新排序" "允許應用程式將工作移至前景或背景。應用程式可以自行處理,您無須操作。" @@ -324,7 +324,7 @@ "允許應用程式修改平板電腦的通話記錄,包括來電和已撥電話相關資料。惡意應用程式可能會藉此刪除或修改您的通話記錄。" "允許應用程式修改電視的通話記錄,包括來電和撥出電話的相關資料。惡意應用程式可能會藉此清除或修改您的通話記錄。" "允許應用程式修改手機的通話記錄,包括來電和已撥電話相關資料。惡意應用程式可能會藉此刪除或修改您的通話記錄。" - "身體感應器 (例如心跳監視器)" + "存取身體感應器 (例如心跳監測器)" "允許應用程式存取感應器所收集的資料 (這類感應器可監測您的體能狀態,例如您的心跳速率)。" "讀取日曆活動與機密資訊" "允許應用程式讀取平板電腦上儲存的所有日曆活動,包括好友或同事的活動。如此一來,應用程式或可不論資料是否機密或敏感,自行共用或儲存您的日曆資料。" @@ -336,15 +336,15 @@ "允許應用程式新增、移除及更改您可以在手機上修改的活動,包括好友或同事的活動。如此一來,應用程式或可偽裝日曆擁有者傳送訊息,或在擁有者不知情下擅自修改活動。" "接收額外的位置提供者指令" "允許應用程式存取額外的位置提供者指令。這項設定可能會使應用程式干擾 GPS 或其他位置來源的運作。" - "精確位置 (以 GPS 和網絡為基準)" + "存取精確位置 (根據 GPS 和網絡)" "允許應用程式使用全球衛星定位系統 (GPS) 或網絡位置來源 (例如手機發射塔和 Wi-Fi) 取得您的精確位置。您必須在裝置上開啟這些位置服務供應用程式使用。應用程式可能藉此確定您所在的位置,也可能會耗用更多電量。" - "約略位置 (以網絡為基準)" + "存取約略位置 (根據網絡)" "允許應用程式取得您的約略位置。這些位置資訊由位置服務使用網絡位置來源 (例如手機發射塔和 Wi-Fi) 取得。您必須在裝置上開啟這些位置服務供應用程式使用。應用程式可能藉此確定您的約略位置。" "更改音效設定" "允許應用程式修改全域音頻設定,例如音量和用於輸出的喇叭。" "錄製音效" "允許應用程式使用麥克風錄音。這項權限允許應用程式隨時錄音,而不需經您確認。" - "SIM 卡通訊" + "發送指令至 SIM 卡" "允許應用程式傳送指令到 SIM 卡。這項操作具有高危險性。" "拍照和拍攝影片" "允許應用程式使用相機拍照和錄影。這項權限允許應用程式隨時使用相機,而不需經您確認。" @@ -382,7 +382,7 @@ "允許應用程式取得手機已知的帳戶清單,其中可能包括您安裝的應用程式所建立的任何帳戶。" "查看網絡連線" "允許應用程式查看網絡連線相關資訊,例如有哪些網絡和已連接哪些網絡。" - "全面網絡存取權" + "擁有全面網絡存取權" "允許應用程式建立網絡通訊端及使用自訂的網絡通訊協定。瀏覽器和其他應用程式提供傳送資料至互聯網的途徑,因此不需要這項權限來傳送資料至互聯網。" "更改網絡連線" "允許應用程式更改網絡連線狀態。" @@ -402,7 +402,7 @@ "允許應用程式設定本機藍牙手機,以及與偵測到的遠端裝置配對。" "建立或中斷與 WiMAX 網絡的連線" "允許應用程式確定是否已啟用 WiMAX,以及判斷任何已連接 WiMAX 網絡的相關資訊。" - "更改 WiMAX 狀態" + "變更 WiMAX 狀態" "允許應用程式建立或中斷平板電腦與 WiMAX 網絡的連線。" "允許應用程式連接至電視,並中斷電視與 WiMAX 網絡的連線。" "允許應用程式建立或中斷手機與 WiMAX 網絡的連線。" @@ -485,7 +485,7 @@ "允許應用程式修改觸控式螢幕的校正參數,而一般應用程式並不需要作出類似修改。" "存取 DRM 憑證" "允許應用程式準備和使用 DRM 憑證,但一般應用程式並不需要使用。" - "接收 Android Beam 的傳送狀態" + "接收 Android Beam 的傳送狀態" "允許應用程式接收 Android Beam 目前傳送的資料" "移除 DRM 憑證" "允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。" @@ -1091,11 +1091,11 @@ "正在格式化…" "未插入" "找不到相符的活動。" - "轉送媒體輸出" + "轉送媒體輸出" "允許應用程式將媒體輸出轉送至其他外部裝置。" - "讀取安裝工作階段" + "讀取安裝工作階段" "允許應用程式讀取安裝工作階段。應用程式將可查看目前安裝套裝的詳細資料。" - "要求安裝套件" + "要求安裝套件" "允許應用程式要求安裝套件" "輕觸兩下即可控制縮放" "無法新增小工具。" diff --git a/core/res/res/values-zh-rTW-watch/strings.xml b/core/res/res/values-zh-rTW-watch/strings.xml index 87f3abbeaafeb..1c11f0ebd0f26 100644 --- a/core/res/res/values-zh-rTW-watch/strings.xml +++ b/core/res/res/values-zh-rTW-watch/strings.xml @@ -21,4 +21,5 @@ "應用程式 %1$d/%2$d。" + "感應器" diff --git a/core/res/res/values-zh-rTW/cm_strings.xml b/core/res/res/values-zh-rTW/cm_strings.xml new file mode 100644 index 0000000000000..e9fb31c893eec --- /dev/null +++ b/core/res/res/values-zh-rTW/cm_strings.xml @@ -0,0 +1,193 @@ + + + + + + 螢幕截圖 + + 接收受保護的簡訊 + + 允許應用程式接收受保護的簡訊。 + + 修改受保護的簡訊清單 + + 允許應用程式修改受保護的簡訊地址清單。 + + 安全 + + 與裝置安全資訊相關的權限。 + + 讀取手機黑名單 + + 允許應用程式讀取關於被封鎖來電或訊息的電話號碼的資訊。 + + 更改手機黑名單 + + 允許應用程式更改被封鎖來電或訊息的電話號碼。 + + 設定鎖定螢幕桌布 + + 允許應用程式更改鎖定螢幕桌布。 + + 重新啟動 + + 現在 + + + 重新啟動 + + Recovery + + Bootloader + + Download + + 軟體重新啟動 + + 重新啟動 + + 您的平板電腦將會重新啟動。 + 您的手機將會重新啟動。 + + 正在重新啟動\u2026 + + 已終止應用程式 + + 已啟用網路 ADB + + ADB 透過 USB 和網路已啟用 + + 輕觸即可停用偵錯。 + + ADB - %1$s + USB 和網路 + USB + 網路 + + 限制應用程式執行 + + 未安裝 %s + + 優先度 + + + 由於 SIM 卡資訊更改,已停用 Wi-Fi 熱點 + + 關閉 Wi-Fi + + 啟用或停用隱私守衛 + 允許應用程式更改其他應用程式執行時是否啟用隱私守衛。當應用程式執行時啟用了隱私守衛,它將無法存取個人資料,例如聯絡人、通話記錄或訊息。 + 隱私守衛正在運作 + %1$s」將無法存取個人資料 + 隱私守衛 + %1$s」想要%2$s + + 記住我的選擇 + + 存取相機 + 存取您的位置 + 讀取您的通知 + 啟動 VPN + 開機時啟動 + 刪除您的通話紀錄 + 刪除您的聯絡人 + 刪除您的多媒體訊息 + 刪除您的簡訊 + 在頂層繪製視窗 + 取得應用程式的使用狀況統計 + 讓您的裝置保持清醒 + 撥打電話 + 更新您的日曆 + 更新通話紀錄 + 修改剪貼簿 + 更新您的連絡人資料 + 更新系統設定 + 麥克風靜音/解除靜音 + 播放音訊 + 發佈通知 + 放映媒體 + 讀取您的日曆 + 讀取通話紀錄 + 讀取剪貼簿 + 讀取您的聯絡人資料 + 讀取您的多媒體簡訊 + 讀取您的簡訊 + 接收簡訊 + 錄製音訊 + 傳送多媒體訊息 + 傳送簡訊 + 開機時啟動 + 顯示彈出信息 + 切換至藍牙 + 切換至行動數據 + 開關 NFC + 切換至 Wi-Fi + 控制鬧鐘音量 + 控制音訊焦點 + 控制藍牙音量 + 控制主音量 + 使用媒體鍵 + 控制媒體音量 + 控制通知音量 + 控制鈴聲音量 + 使用觸控震動 + 控制語音通話音量 + 撰寫多媒體訊息 + 撰寫簡訊 + 使用指紋 + 新增語音信箱 + 存取電話狀態 + 掃描 Wi-Fi 網路 + 更改桌布 + 使用協助工具 + 螢幕截圖 + 使用人體感應器 + 讀取區域廣播 + 模擬所在位置 + 讀取外部儲存空間 + 寫入外部儲存空間 + 開啟螢幕 + 取得裝置帳號 + 更改 Wi-Fi 狀態 + 取得 Root 權限 + + 要解鎖此螢幕,觸摸並按住返回鍵。 + + 沒有已連接的裝置 + %1$s 個已連接裝置 + %1$s 個已連接裝置 + + + + 已封鎖啟動活動 + %1$s 正被防止啟動。按一下即可進行身份驗證並啟動應用程式。 + + 電池完全充滿 + 請將裝置與充電線拔除,以提高電池壽命。 + + 重設電池統計資訊 + + 允許應用程式重設目前低電量的電池使用資料。 + + SIM 卡已更改 + 輕觸即可設定 SIM卡 預設首選項 + diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 175f7dc80aa7e..22722b0c22dd8 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -254,7 +254,7 @@ "包括個人資料,如信用卡號碼和密碼。" "停用或變更狀態列" "允許應用程式停用狀態列,並可新增或移除系統圖示。" - "狀態列" + "以狀態列顯示" "允許應用程式以狀態列顯示。" "展開/收攏狀態列" "允許應用程式展開或收合狀態列。" @@ -282,7 +282,7 @@ "允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。" "擷取執行中的應用程式" "允許應用程式擷取最近執行工作的資訊。這項設定可讓應用程式找出裝置所用程式的相關資訊。" - "管理個人資料和裝置擁有者" + "管理個人資料和裝置擁有者" "允許應用程式設定個人資料擁有者和裝置擁有者。" "重新排序正在執行的應用程式" "允許應用程式將工作移至前景或背景。應用程式可以自行處理,不待您操作。" @@ -324,7 +324,7 @@ "允許應用程式修改平板電腦的通話紀錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能刪除或修改您的通話紀錄。" "允許應用程式修改電視的通話紀錄,包括來電和已撥電話相關資料。惡意應用程式可能會藉此清除或修改您的通話紀錄。" "允許應用程式修改手機的通話紀錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能刪除或修改您的通話紀錄。" - "身體感應器 (例如心律監測器)" + "存取身體感應器 (例如心跳速率監測器)" "允許應用程式存取感測器所收集的資料 (這類感測器可監測您的體能狀態,例如您的心跳速率)。" "讀取日曆活動與機密資訊" "允許應用程式讀取平板電腦上儲存的所有日曆活動,包括好友或同事的活動。這項設定會讓應用程式共用或儲存您的日曆資料,甚至包括機密或敏感的資料。" @@ -336,15 +336,15 @@ "允許應用程式新增、移除、變更您可以在手機上修改的活動,包括好友或同事的活動。這項設定可能會讓應用程式偽裝日曆擁有者傳送訊息,或私自修改活動。" "接收額外的位置提供者指令" "允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。" - "精確位置 (以 GPS 和網路為基準)" + "存取精確位置 (以 GPS 和網路為依據)" "允許應用程式使用全球衛星定位系統 (GPS) 或網路位置來源 (例如無線通信基地台和 Wi-Fi) 取得您的精確位置。您必須在裝置上開啟這些定位服務,才能供應用程式使用。應用程式可能藉此判別您的位置,也可能增加額外耗電。" - "概略位置 (以網路為基準)" + "存取概略位置 (以網路為依據)" "允許應用程式取得您的概略位置。這類位置資訊取自使用網路位置來源 (例如無線通信基地台和 Wi-Fi) 的定位服務。您必須在裝置上開啟這些定位服務,才能供應用程式使用。應用程式可能藉此判別您的概略位置。" "變更音訊設定" "允許應用程式修改全域音訊設定,例如音量和用來輸出的喇叭。" "錄製音訊" "允許應用程式使用麥克風錄音。這項權限可讓應用程式隨時錄音,不需經過您的確認。" - "SIM 卡通訊" + "傳送指令到 SIM 卡" "允許應用程式傳送指令到 SIM 卡。這麼做非常危險。" "拍攝相片和影片" "允許應用程式使用相機拍照和錄影。這項權限可讓應用程式隨時使用相機,而不需請求您進行確認。" @@ -382,7 +382,7 @@ "允許應用程式取得手機上所記憶的帳戶清單,其中可能包括您安裝的應用程式所建立的任何帳戶。" "查看網路連線" "允許應用程式查看網路連線相關資訊,例如有哪些網路,以及已連上哪些網路。" - "完整網路存取權" + "擁有完整的網路存取權" "允許應用程式建立網路通訊端及使用自訂網路通訊協定。瀏覽器和其他應用程式會提供將資料傳輸到網際網路的方法,因此不需要這項權限也能將資料傳輸到網際網路。" "變更網路連線" "允許應用程式變更網路連線狀態。" @@ -402,7 +402,7 @@ "允許應用程式設定本機藍牙手機,以及搜尋遠端裝置並配對連線。" "建立或中斷與 WiMAX 網路的連線" "允許應用程式判斷是否已啟用 WiMAX,以及判讀任何已連上 WiMAX 網路的相關資訊。" - "變更 WiMAX 狀態" + "變更 WiMAX 狀態" "允許應用程式建立或中斷平板電腦與 WiMAX 網路的連線。" "允許應用程式建立及中斷電視的 WiMAX 網路連線。" "允許應用程式建立或中斷手機與 WiMAX 網路的連線。" @@ -485,7 +485,7 @@ "允許應用程式修改觸控螢幕的校正參數 (一般應用程式並不需要)。" "存取 DRM 憑證" "允許應用程式佈建及使用 DRM 憑證 (一般應用程式並不需要)。" - "接收 Android Beam 的傳輸狀態" + "接收 Android Beam 的傳輸狀態" "允許應用程式接收 Android Beam 目前傳輸的資訊" "移除 DRM 憑證" "允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。" @@ -1091,11 +1091,11 @@ "正在格式化…" "未插入" "找不到相符的活動。" - "轉送媒體輸出" + "轉送媒體輸出" "允許應用程式將媒體輸出轉送至其他外部裝置。" - "讀取安裝工作階段" + "讀取安裝工作階段" "允許應用程式讀取安裝工作階段。應用程式將可查看目前的套件安裝詳細資料。" - "要求安裝套件" + "要求安裝套件" "允許應用程式要求安裝套件。" "輕觸兩下即可控制縮放" "無法新增小工具。" diff --git a/core/res/res/values-zu-watch/strings.xml b/core/res/res/values-zu-watch/strings.xml index acd153b378944..26f80710ac25c 100644 --- a/core/res/res/values-zu-watch/strings.xml +++ b/core/res/res/values-zu-watch/strings.xml @@ -21,4 +21,5 @@ "Uhlelo lokusebenza olungu-%1$d kokungu-%2$d." + "Izinzwa" diff --git a/core/res/res/values-zu/cm_strings.xml b/core/res/res/values-zu/cm_strings.xml new file mode 100644 index 0000000000000..2ce9b8bbaccd9 --- /dev/null +++ b/core/res/res/values-zu/cm_strings.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 5df33186471e8..881384d157029 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -254,7 +254,7 @@ "Kufaka phakathi idatha yomuntu siqu efana nezinombolo zekhadi lesikweletu namaphasiwedi." "khubaza noma guqula ibha yomumo" "Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo." - "umudwa ochaza ngesimo" + "yiba yibha yesimo" "Ivumela uhlelo lokusebenza ukuthi lube umudwa ochaza ngesimo." "khulisa/nciphisa ibha yomumo" "Ivumela uhlelo lokusebenza ukuthi ikhulise noma inciphise umudwa ochza ngesimo." @@ -282,7 +282,7 @@ "Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-WAP. Le mvume ifaka phakathi amandla okungamela noma okwesusa imilayezo ethunyelwe kuwe ngaphandle kokukubonisa." "thola izinhlelo zokusebenza ezisebenzayo" "Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana nemisebenzi yamanje neyakamuva. Lokhu kungavumela uhlelo lokusebenza ukuthola ulwazi mayelana nokuthi iziphi izinhlelo zokusebenza ezisetshenziswa kudivayisi." - "Phatha iphrofayela nabanikazi bedivayisi" + "phatha iphrofayela nabanikazi bedivayisi" "Ivumela izinhlelo zokusebenza ukuthi zisethe abanikazi bephrofayela nomnikazi wedivayisi." "misa kabusha izinhlelo zokusebenza ezisebenzayo" "Ivumela uhlelo lokusebenza ukugudluza imisebenzi ngaphambili nangasemuva. Uhlelo lokusebenza lungenza lokhu ngaphandle kwakho." @@ -324,7 +324,7 @@ "Ivumela uhlelo lokusebenza ukushintsha ilogi yekholi yethebulethi yakho, kufaka phakathi idatha mayelana namakholi angenayo naphumayo. Izinhlelo zikusebenza ezingalungile zingasebenzisa lokhu ukusula noma ukushintsha irekhodi lwamakholi wakho." "Ivumela uhlelo lokusebenza ukuthi liguqule ilogi yekholi yakho ye-TV, okufaka idatha emayelana namakholi angenayo naphumayo. Izinhlelo zokusebenza ezinobungozi zingasebenzisa lokhu ukususa noma ukuguqula ilogi yakho yekholi." "Ivumela uhlelo lokusebenza ukushintsha irekhodi lamakholi efoni yakho, kufaka phakathi idatha emayelana namakholi angenayo naphumayo. Izinhlelo zikusebenza ezingalungile zingasebenzisa lokhu ukusula noma ukushintsha irekhodi lwamakholi wakho." - "izinzwa zomzimba (njengeziqaphi zokulinganisela inhliziyo)" + "finyelela kuzinzwa zomzimba (ezifana neziqaphi zokulinganisela inhliziyo)" "Ivumela uhlelo lokusebenza ukuthi lufinyelele kudatha kusukela kuzinzwa eziqapha isimo sakho somzimba, esifana nesilinganiso senhliziyo yakho." "funda imicimbi yekhalenda kanye nokwaziswa okuyimfihlo" "Ivumela uhlelo lokusebenza ukufunda zonke izehlakalo zekhalenda ezilondolozwe kuthebhulethi yakho, kufaka phakathi lezo zabangani noma osebenza nabo. Lokhu kungavumela uhlelo lokusebenza ukwabelana noma ukulondoloza idatha yakho yekhalenda, ngaphandle kokugcinwa kuyimfihlo noma ukuzwela." @@ -336,15 +336,15 @@ "Ivumela uhlelo lokusebenza ukungeza, ukususa, ukushintsha izehlakalo ongazishintsha efonini yakho, kufaka phakathi nalezo zabangani noma labo osebenza nabo. Lokhu kungavumela uhlelo lokusebenza ukuthumela imilayezo ebonakala ngathi ivela kubanikazi bekhalenda, noma lishintshe izehlakalo ngaphandle kolwazi labanikazi." "finyelela kweminye imiyalo yokunikeza indawo" "Ivumela uhlelo lokusebenza ukufinyelela imiyalo eyengeziwe yabahlinzeki bendawo. Lokhu kungase kuvumele uhlelo lokusebenza ukuthi liphazamisane nomsebenzi we-GPS noma eminye imithombo yendawo." - "indawo eqondile (kususelwe ku-GPS nakunethiwekhi)" + "finyelela indawo enembile (i-GPS nesuselwa kunethiwekhi)" "Ivumela uhlelo lokusebenza ukuthola indawo yakho uqobo isebenzisa i-Global Positioning System (GPS) noma imithombo yendawo yenethiwekhi njengama-cell tower ne-Wi-Fi. Lawa masevisi endawo kufanele akhanyiswe futhi atholakale kudivayisi yakho ukuze asetshenziswe uhlelo lokusebenza. Izinhlelo zokusebenza zingasebenzias lokhu ukucacisa lapho ukhona, futhi angasebenzisa ibhethri elingeziwe." - "indawo eseduze (kususelwe kunethiwekhi)" + "finyelela kundawo elinganiselwe (esuselwa kunethiwekhi)" "Ivumela uhlelo lokusebenza ukuthola cishe indawo yakho. Le ndawo isuselwe kumasevisi endawo kusetshenziswa imithombo yendawo yenethiwekhi njengama-cell tower ne-Wi-Fi. Lawo masevisi endawo kufanele akhanyiswe futhi atholakale kudivayisi yakho ukuze asetshenziswe uhlelo lakho lokusebenza. Izinhlelo zokusebenza zingasebenzisa lokhu ukucacisa cishe lapho ukhona." "shintsha izilungiselelo zakho zomsindo" "Ivumela uhlelo lokusebenza ukushintsha izilungiselelo zomsindo we-global njengevolomu nokuthi isiphi isipika esisetshenziselwa okukhiphayo." "qopha umsindo" "Ivumela uhlelo lokusebenza ukurekhoda umsindo nge-microphone. Le mvume ivumela uhlelo lokusebenza ukuqopha umsindo noma kunini ngaphandle kokuqinisekisa kwakho." - "uxhumano le-sim" + "thumela imilayezo ku-SIM" "Ivumela uhlelo lokusebenza ukuthumela imiyalo ku-SIM. Lokhu kuyingozi kakhulu." "thatha izithombe namavidiyo" "Ivumela uhlelo lokusebenza ukuthatha izithombe namavidiyo ngekhamera. Le mvume ivumela uhlelo lokusebenza ukusebenzisa ikhamera nganoma isiphi isikhathi ngaphandle kwemvume yakho." @@ -382,7 +382,7 @@ "Ivumela uhlelo lokusebenza ukuthola uhlu lwama-akhawunti aziwa ifoni. Lokhu kufaka phakathi noma yimaphi ama-akhawunti adalwe izinhlelo zokusebenza ozifakile." "buka ukuxhumeka kunethiwekhi" "Ivumela uhlelo lokusebenza ukubuka ulwazi mayelana noxhumo lenethiwekhi njengokuthi imaphi amanethiwekhi akhona futhi axhunyiwe." - "ukufinyelela kwenethiwekhi okugcwele" + "iba nokufinyelela okugcwele kwenethiwekhi" "Ivumela uhlelo lokusebenza ukudala amasokethi enethiwekhi nokusebenzisa iziphakamiso eziyisisekelo zenethiwekhi yezifiso. Iziphequluli nezinye izinhlelo zokusebenza zinikela ngezindlela zokuthumela idatha ku-intanethi, ngakho-le le mvume ayidingekile ukuthumela idatha ku-intanethi." "shintsha uxhumano lwenethiwekhi" "Ivumela uhlelo lokusebenza ukuthi iguqule isimo sokuxhuaniseka kwenethiwekhi." @@ -402,7 +402,7 @@ "Ivumela uhlelo lokusebenza ukumisa ifoni ye-Bluetooth yasendawni, nokuthola nokubhanqanisa namadivaysi okulawula okukude." "xhuma futhi unqamule kusuka ku-WiMAX" "Ivumela uhlelo lokusebenza ukucacisa ukuthi ingabe i-WiMAX inikwe amandla futhi ulwazi mayelana namanethiwekhi e-WiMAX axhunyiwe." - "Shintsha isimo se-WiMAX" + "shintsha isimo se-WiMAX" "Ivumela uhlelo lokusebenza ukuxhuma ithebhulethi nokunqamula ithebhulethi kumanethiwekhi e-WiMAX." "Ivumela uhlelo lokusebenza ukuthi lixhume i-TV liphinde liyinqamule kusukela kumanethiwekhi we-WiMAX." "Ivumela uhlelo lokusebenza ukuxhuma ifoni nokuyinqamula kumanethiwekhi e-WiMAX." @@ -485,7 +485,7 @@ "Ivumela uhlelo lokusebenza ukuthi lushintshe imingcele yokulinganisa yesikrini esithintwayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile." "finyelela izitifiketi ze-DRM" "Ivumela uhlelo lokusebenza ekunikezweni nokusetshenziswa kwezitifiketi ze-DRM. Akufanele kudingeke kuzinhlelo zokusebenza ezivamile." - "Thola isimo sokundlulisa se-Android Beam" + "thola isimo sokudlulisa se-Android Beam" "Ivumela lolu hlelo lokusebenza ukuthi luthole ulwazi mayelana nokundluliswa kwamanje kwe-Android Beam" "susa izitifiketi ze-DRM" "Ivumela uhlelo lokusebenza ukususa izitifiketi ze-DRM. Akufanele idingeke ngezinhlelo zokusebenza ezivamile." @@ -1091,11 +1091,11 @@ "Iyafometha..." "Akufakiwe" "Ayikho imisebenzi efanayo etholakele" - "Yenza umzila wemidiya wokukhiphayo" + "yenza umzila ukukhipha kwemidiya" "Ivumela uhlelo lokusebenza ukwenza umzila wokukhiphayo wemidiya kuya kumadivayisi angaphandle." - "Funda izikhathi zokufaka" + "funda izikhathi zokufaka" "Ivumela uhlelo lokusebenza ukufunda izikhathi. Lokhu kuzolivumela ukubona imininingwane mayelana nokufaka kwephakethi esebenzayo." - "Cela amaphakheji wokufaka" + "cela amaphakheji wokufaka" "Ivumela uhlelo lokusebenza ukucela ukufakwa kwamaphakheji." "Thinta kabili ukulawula ukusondeza" "Yehlulekile ukwengeza i-widget." diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 4e220b1df3361..e17b017b97a05 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1806,10 +1806,15 @@ i + + + + + @@ -2139,6 +2144,13 @@ i (which is exiting the screen). The wallpaper remains static behind the animation. --> + + + + diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index a0b92b9de307b..6da5941d16328 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1595,6 +1595,7 @@ {@link #AndroidManifest manifest} tag. --> + + diff --git a/core/res/res/values/cm_colors.xml b/core/res/res/values/cm_colors.xml index 8e7e5c59fc48d..3eca3aefbfe1d 100644 --- a/core/res/res/values/cm_colors.xml +++ b/core/res/res/values/cm_colors.xml @@ -1,5 +1,22 @@ + + @android:color/black + @android:color/black + @android:color/black + #ff000000 + #ffffffff + @color/perms_costs_money + #60FFFFFF + #FF000000 + #555555 + #FFFFFFFF + @android:color/holo_blue_light + @android:color/holo_blue_light + #99FFFFFF + #BB000000 + #FFFF00FF + #CC000000 #ff009688 @color/primary_text_default_material_light @android:color/white diff --git a/core/res/res/values/cm_integers.xml b/core/res/res/values/cm_integers.xml new file mode 100644 index 0000000000000..0668c92d3167e --- /dev/null +++ b/core/res/res/values/cm_integers.xml @@ -0,0 +1,22 @@ + + + + + 900000 + diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml index 25901c06e2776..a8fcbe5202425 100644 --- a/core/res/res/values/cm_strings.xml +++ b/core/res/res/values/cm_strings.xml @@ -28,7 +28,7 @@ modify protected SMS list - Allows the app to modify the protected sms address list. + Allows the app to modify the protected SMS address list. Security @@ -45,9 +45,6 @@ Allows an app to change the phone numbers that are blocked for incoming calls or messages. - - Profile - set keyguard wallpaper @@ -82,7 +79,7 @@ Rebooting\u2026 - Application killed + App killed ADB over network enabled @@ -92,42 +89,17 @@ Touch to disable debugging. - ADB - %1$s - Both + ADB - %1$s + USB & network USB Network - - access theme service - intercept app launch - - Allows an app to access the theme service. Should never be needed for normal apps. - - - read your theme info - - Allows the app to read your themes and - determine which theme you have applied. - - - modify your themes - - Allows the app to insert new themes and - modify which theme you have applied. - - - Failed to install theme - %s failed to install - %s is not installed - Theme reset - System theme restored due to multiple app crashes. - Priority None @@ -147,8 +119,7 @@ %1$s would like to %2$s. - Remember - Permission + Remember my choice access the camera @@ -186,9 +157,9 @@ start at power up display toast messages toggle Bluetooth - toggle mobile data + toggle cellular data toggle NFC - toggle WiFi + toggle Wi-Fi control alarm volume control the audio focus control the Bluetooth volume @@ -204,7 +175,7 @@ use fingerprint add a voicemail access phone state - Scan WiFi Networks + scan Wi-Fi networks change the wallpaper use assist structure take a screenshot @@ -215,25 +186,12 @@ write external storage turn the screen on get device accounts - change WiFI state - get Superuser access + change Wi-Fi state + get root access To unpin this screen, touch and hold the Back button. - - LiveDisplay - Automatic - Automatically adjust color temperature of screen after sunset and sunrise - Off - Disable all adjustments - Day - Use day settings only - Night - Use night settings only - Outdoor (bright sun) - Use outdoor settings only - LiveDisplay can help reduce eyestrain and help you sleep at night. Click here to try it out! %s @@ -241,4 +199,28 @@ No connected device %1$s connected device %1$s connected devices + + + + " | " + + + Activity launch blocked + %1$s is protected from being launched. Tap to authenticate and launch the application. + + + Battery fully charged + Disconnect your device from the charger to improve battery longevity. + + + reset battery statistics + + Allows an application to reset the current low-level battery usage data. + + + SIM cards have changed + Tap to set SIM card default preferences diff --git a/core/res/res/values/cm_styles.xml b/core/res/res/values/cm_styles.xml new file mode 100644 index 0000000000000..1d0de05a9e131 --- /dev/null +++ b/core/res/res/values/cm_styles.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 857b208a9a806..8ca58baa8796c 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -297,5 +297,11 @@ 300 + + false + + + false + diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 03ea73c262da7..a7efccd214d2d 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -531,7 +531,7 @@ 8dp - 7dp + 3dp 3dp diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 3a41c3c540bdd..2d70faa04c5bf 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -18,59 +18,8 @@ android:title="@string/system_ui_tuner"> - - - - - - - - - - - - - - - - - - - - - - - - - - + android:key="statusbar_icon_blacklist" + android:title="@string/status_bar" /> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java index 4717a0bf93d65..247e965a1c978 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java @@ -17,6 +17,7 @@ package com.android.systemui; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryStateRegistar; import android.content.Context; import android.content.res.Configuration; @@ -28,7 +29,10 @@ public class BatteryLevelTextView extends TextView implements BatteryController.BatteryStateChangeCallback{ - private BatteryController mBatteryController; + + private BatteryStateRegistar mBatteryStateRegistar; + private boolean mBatteryPresent; + private boolean mBatteryCharging; private boolean mForceShow; private boolean mAttached; @@ -38,7 +42,9 @@ public class BatteryLevelTextView extends TextView implements public BatteryLevelTextView(Context context, AttributeSet attrs) { super(context, attrs); - mRequestedVisibility = getVisibility(); + // setBatteryStateRegistar (if called) will made the view visible and ready to be hidden + // if the view shouldn't be displayed. Otherwise this view should be hidden from start. + mRequestedVisibility = GONE; } public void setForceShown(boolean forceShow) { @@ -46,10 +52,11 @@ public void setForceShown(boolean forceShow) { updateVisibility(); } - public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; + public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) { + mRequestedVisibility = VISIBLE; + mBatteryStateRegistar = batteryStateRegistar; if (mAttached) { - mBatteryController.addStateChangedCallback(this); + mBatteryStateRegistar.addStateChangedCallback(this); } } @@ -69,10 +76,12 @@ protected void onConfigurationChanged(Configuration newConfig) { } @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, + boolean charging) { String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); setText(percentage); - if (mBatteryCharging != charging) { + if (mBatteryPresent != present || mBatteryCharging != charging) { + mBatteryPresent = present; mBatteryCharging = charging; updateVisibility(); } @@ -94,8 +103,8 @@ public void onBatteryStyleChanged(int style, int percentMode) { public void onAttachedToWindow() { super.onAttachedToWindow(); - if (mBatteryController != null) { - mBatteryController.addStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.addStateChangedCallback(this); } mAttached = true; @@ -106,21 +115,22 @@ public void onDetachedFromWindow() { super.onDetachedFromWindow(); mAttached = false; - if (mBatteryController != null) { - mBatteryController.removeStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.removeStateChangedCallback(this); } } private void updateVisibility() { - boolean showNextPercent = mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE - || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE); + boolean showNextPercent = mBatteryPresent && ( + mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE + || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE)); if (mStyle == BatteryController.STYLE_GONE) { showNextPercent = false; } else if (mStyle == BatteryController.STYLE_TEXT) { showNextPercent = true; } - if (showNextPercent || mForceShow) { + if (mBatteryStateRegistar != null && (showNextPercent || mForceShow)) { super.setVisibility(mRequestedVisibility); } else { super.setVisibility(GONE); diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index 244b7f79b72f8..06c29577d755e 100755 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2013-14 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,42 +17,47 @@ package com.android.systemui; -import com.android.systemui.statusbar.policy.BatteryController; - import android.animation.ArgbEvaluator; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Resources; +import android.content.res.ThemeConfig; import android.content.res.TypedArray; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.Typeface; +import android.graphics.drawable.AnimatedVectorDrawable; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.os.BatteryManager; import android.os.Bundle; import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; import android.view.View; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryStateRegistar; + +import org.cyanogenmod.graphics.drawable.StopMotionVectorDrawable; + public class BatteryMeterView extends View implements DemoMode, BatteryController.BatteryStateChangeCallback { public static final String TAG = BatteryMeterView.class.getSimpleName(); public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; - private static final int FULL = 96; - - private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction - private final int[] mColors; protected boolean mShowPercent = true; - private float mButtonHeightFraction; - private float mSubpixelSmoothingLeft; - private float mSubpixelSmoothingRight; public enum BatteryMeterMode { BATTERY_METER_GONE, @@ -65,14 +71,10 @@ public enum BatteryMeterMode { private int mWidth; private String mWarningString; private final int mCriticalLevel; - private final int mFrameColor; private boolean mAnimationsEnabled; - private final Path mShapePath = new Path(); - private final Path mClipPath = new Path(); - private final Path mTextPath = new Path(); - + private BatteryStateRegistar mBatteryStateRegistar; private BatteryController mBatteryController; private boolean mPowerSaveEnabled; @@ -92,7 +94,10 @@ public enum BatteryMeterMode { private BatteryMeterDrawable mBatteryMeterDrawable; private int mIconTint = Color.WHITE; - private class BatteryTracker extends BroadcastReceiver { + private int mCurrentBackgroundColor = 0; + private int mCurrentFillColor = 0; + + protected class BatteryTracker extends BroadcastReceiver { public static final int UNKNOWN_LEVEL = -1; // current battery status @@ -128,7 +133,6 @@ public void onReceive(Context context, Intent intent) { technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY); voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); - setContentDescription( context.getString(R.string.accessibility_battery_level, level)); if (mBatteryMeterDrawable != null) { @@ -193,7 +197,9 @@ public void onAttachedToWindow() { // preload the battery level mTracker.onReceive(getContext(), sticky); } - mBatteryController.addStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.addStateChangedCallback(this); + } mAttached = true; } @@ -203,7 +209,9 @@ public void onDetachedFromWindow() { mAttached = false; getContext().unregisterReceiver(mTracker); - mBatteryController.removeStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.removeStateChangedCallback(this); + } } public BatteryMeterView(Context context) { @@ -220,8 +228,6 @@ public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { final Resources res = context.getResources(); TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView, defStyle, 0); - mFrameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor, - res.getColor(R.color.batterymeter_frame_color)); TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); @@ -237,12 +243,6 @@ public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); mCriticalLevel = getContext().getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); - mButtonHeightFraction = context.getResources().getFraction( - R.fraction.battery_button_height_fraction, 1, 1); - mSubpixelSmoothingLeft = context.getResources().getFraction( - R.fraction.battery_subpixel_smoothing_left, 1, 1); - mSubpixelSmoothingRight = context.getResources().getFraction( - R.fraction.battery_subpixel_smoothing_right, 1, 1); mDarkModeBackgroundColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_background); @@ -255,17 +255,13 @@ public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { } protected BatteryMeterDrawable createBatteryMeterDrawable(BatteryMeterMode mode) { - Resources res = mContext.getResources(); + Resources res = getResources(); switch (mode) { - case BATTERY_METER_CIRCLE: - return new CircleBatteryMeterDrawable(res); - case BATTERY_METER_ICON_LANDSCAPE: - return new NormalBatteryMeterDrawable(res, true); case BATTERY_METER_TEXT: case BATTERY_METER_GONE: return null; default: - return new NormalBatteryMeterDrawable(res, false); + return new AllInOneBatteryMeterDrawable(res, mode); } } @@ -274,25 +270,28 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); - if (mMeterMode == BatteryMeterMode.BATTERY_METER_CIRCLE) { - height += (CircleBatteryMeterDrawable.STROKE_WITH / 3); - width = height; - } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_TEXT) { + if (mMeterMode == BatteryMeterMode.BATTERY_METER_TEXT) { onSizeChanged(width, height, 0, 0); // Force a size changed event - } else if (mMeterMode.compareTo(BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) == 0) { - width = (int)(height * 1.2f); } setMeasuredDimension(width, height); } + public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) { + mBatteryStateRegistar = batteryStateRegistar; + if (!mAttached) { + mBatteryStateRegistar.addStateChangedCallback(this); + } + } + public void setBatteryController(BatteryController batteryController) { mBatteryController = batteryController; mPowerSaveEnabled = mBatteryController.isPowerSave(); } @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, + boolean charging) { // TODO: Use this callback instead of own broadcast receiver. } @@ -365,11 +364,6 @@ public void setMode(BatteryMeterMode mode) { mBatteryMeterDrawable.onDispose(); } mBatteryMeterDrawable = createBatteryMeterDrawable(mode); - if (mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_PORTRAIT || - mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) { - ((NormalBatteryMeterDrawable)mBatteryMeterDrawable).loadBoltPoints( - mContext.getResources()); - } if (tracker.present) { setVisibility(View.VISIBLE); requestLayout(); @@ -381,7 +375,6 @@ public void setMode(BatteryMeterMode mode) { } public int getColorForLevel(int percent) { - // If we are in power save mode, always use the normal color. if (mPowerSaveEnabled) { return mColors[mColors.length-1]; @@ -405,9 +398,9 @@ public int getColorForLevel(int percent) { public void setDarkIntensity(float darkIntensity) { if (mBatteryMeterDrawable != null) { - int backgroundColor = getBackgroundColor(darkIntensity); - int fillColor = getFillColor(darkIntensity); - mBatteryMeterDrawable.setDarkIntensity(backgroundColor, fillColor); + mCurrentBackgroundColor = getBackgroundColor(darkIntensity); + mCurrentFillColor = getFillColor(darkIntensity); + mBatteryMeterDrawable.setDarkIntensity(mCurrentBackgroundColor, mCurrentFillColor); } } @@ -469,253 +462,83 @@ protected interface BatteryMeterDrawable { void setDarkIntensity(int backgroundColor, int fillColor); } - protected class NormalBatteryMeterDrawable implements BatteryMeterDrawable { + protected class AllInOneBatteryMeterDrawable implements BatteryMeterDrawable { private static final boolean SINGLE_DIGIT_PERCENT = false; private static final boolean SHOW_100_PERCENT = false; private boolean mDisposed; - protected final boolean mHorizontal; + private boolean mIsAnimating; // stores charge-animation status to remove callbacks + + private float mTextX, mTextY; // precalculated position for drawText() to appear centered + + private boolean mInitialized; - private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint; - private float mTextHeight, mWarningTextHeight; + private Paint mTextAndBoltPaint; + private Paint mWarningTextPaint; + private Paint mClearPaint; - private int mChargeColor; - private final float[] mBoltPoints; - private final Path mBoltPath = new Path(); + private LayerDrawable mBatteryDrawable; + private Drawable mFrameDrawable; + private StopMotionVectorDrawable mLevelDrawable; + private Drawable mBoltDrawable; - private final RectF mFrame = new RectF(); - private final RectF mButtonFrame = new RectF(); - private final RectF mBoltFrame = new RectF(); + private BatteryMeterMode mMode; + private int mTextGravity; - public NormalBatteryMeterDrawable(Resources res, boolean horizontal) { + public AllInOneBatteryMeterDrawable(Resources res, BatteryMeterMode mode) { super(); - mHorizontal = horizontal; - mDisposed = false; - mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mFramePaint.setColor(mFrameColor); - mFramePaint.setDither(true); - mFramePaint.setStrokeWidth(0); - mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); + loadBatteryDrawables(res, mode); + + mMode = mode; + mDisposed = false; - mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBatteryPaint.setDither(true); - mBatteryPaint.setStrokeWidth(0); - mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); + // load text gravity and blend mode + int[] attrs = new int[] {android.R.attr.gravity, R.attr.blendMode}; + int resId = getBatteryDrawableStyleResourceForMode(mode); + PorterDuff.Mode xferMode = PorterDuff.Mode.XOR; + if (resId != 0) { + TypedArray a = getContext().obtainStyledAttributes( + getBatteryDrawableStyleResourceForMode(mode), attrs); + mTextGravity = a.getInt(0, Gravity.CENTER); + xferMode = PorterDuff.intToMode(a.getInt(1, + PorterDuff.modeToInt(PorterDuff.Mode.XOR))); + } else { + mTextGravity = Gravity.CENTER; + } + Log.d(TAG, "mTextGravity=" + mTextGravity); - mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTextAndBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); - mTextPaint.setTypeface(font); - mTextPaint.setTextAlign(Paint.Align.CENTER); + mTextAndBoltPaint.setTypeface(font); + mTextAndBoltPaint.setTextAlign(getPaintAlignmentFromGravity(mTextGravity)); + mTextAndBoltPaint.setXfermode(new PorterDuffXfermode(xferMode)); + mTextAndBoltPaint.setColor(mCurrentFillColor != 0 + ? mCurrentFillColor + : res.getColor(R.color.batterymeter_bolt_color)); mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mWarningTextPaint.setColor(mColors[1]); font = Typeface.create("sans-serif", Typeface.BOLD); mWarningTextPaint.setTypeface(font); - mWarningTextPaint.setTextAlign(Paint.Align.CENTER); + mWarningTextPaint.setTextAlign(getPaintAlignmentFromGravity(mTextGravity)); - mChargeColor = getResources().getColor(R.color.batterymeter_charge_color); - - mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color)); - mBoltPoints = loadBoltPoints(res); + mClearPaint = new Paint(); + mClearPaint.setColor(0); } @Override public void onDraw(Canvas c, BatteryTracker tracker) { if (mDisposed) return; - final int level = tracker.level; - - if (level == BatteryTracker.UNKNOWN_LEVEL) return; - - float drawFrac = (float) level / 100f; - final int pt = getPaddingTop() + (mHorizontal ? (int)(mHeight * 0.12f) : 0); - final int pl = getPaddingLeft(); - final int pr = getPaddingRight(); - final int pb = getPaddingBottom() + (mHorizontal ? (int)(mHeight * 0.08f) : 0); - final int height = mHeight - pt - pb; - final int width = mWidth - pl - pr; - - final int buttonHeight = (int) ((mHorizontal ? width : height) * mButtonHeightFraction); - - mFrame.set(0, 0, width, height); - mFrame.offset(pl, pt); - - if (mHorizontal) { - mButtonFrame.set( - /*cover frame border of intersecting area*/ - width - buttonHeight - mFrame.left, - mFrame.top + Math.round(height * 0.25f), - mFrame.right, - mFrame.bottom - Math.round(height * 0.25f)); - - mButtonFrame.top += mSubpixelSmoothingLeft; - mButtonFrame.bottom -= mSubpixelSmoothingRight; - mButtonFrame.right -= mSubpixelSmoothingRight; - } else { - // button-frame: area above the battery body - mButtonFrame.set( - mFrame.left + Math.round(width * 0.25f), - mFrame.top, - mFrame.right - Math.round(width * 0.25f), - mFrame.top + buttonHeight); - - mButtonFrame.top += mSubpixelSmoothingLeft; - mButtonFrame.left += mSubpixelSmoothingLeft; - mButtonFrame.right -= mSubpixelSmoothingRight; - } - - // frame: battery body area - - if (mHorizontal) { - mFrame.right -= buttonHeight; - } else { - mFrame.top += buttonHeight; + if (!mInitialized) { + init(); } - mFrame.left += mSubpixelSmoothingLeft; - mFrame.top += mSubpixelSmoothingLeft; - mFrame.right -= mSubpixelSmoothingRight; - mFrame.bottom -= mSubpixelSmoothingRight; - - // set the battery charging color - mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level)); - - if (level >= FULL) { - drawFrac = 1f; - } else if (level <= mCriticalLevel) { - drawFrac = 0f; - } - - final float levelTop; - if (drawFrac == 1f) { - if (mHorizontal) { - levelTop = mButtonFrame.right; - } else { - levelTop = mButtonFrame.top; - } - } else { - if (mHorizontal) { - levelTop = (mFrame.right - (mFrame.width() * (1f - drawFrac))); - } else { - levelTop = (mFrame.top + (mFrame.height() * (1f - drawFrac))); - } - } - - // define the battery shape - mShapePath.reset(); - mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); - if (mHorizontal) { - mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); - mShapePath.lineTo(mButtonFrame.right, mButtonFrame.bottom); - mShapePath.lineTo(mButtonFrame.left, mButtonFrame.bottom); - mShapePath.lineTo(mFrame.right, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); - } else { - mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); - mShapePath.lineTo(mButtonFrame.right, mFrame.top); - mShapePath.lineTo(mFrame.right, mFrame.top); - mShapePath.lineTo(mFrame.right, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); - } - - if (tracker.plugged) { - // define the bolt shape - final float bl = mFrame.left + mFrame.width() / (mHorizontal ? 9f : 4.5f); - final float bt = mFrame.top + mFrame.height() / (mHorizontal ? 4.5f : 6f); - final float br = mFrame.right - mFrame.width() / (mHorizontal ? 6f : 7f); - final float bb = mFrame.bottom - mFrame.height() / (mHorizontal ? 7f : 10f); - if (mBoltFrame.left != bl || mBoltFrame.top != bt - || mBoltFrame.right != br || mBoltFrame.bottom != bb) { - mBoltFrame.set(bl, bt, br, bb); - mBoltPath.reset(); - mBoltPath.moveTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); - for (int i = 2; i < mBoltPoints.length; i += 2) { - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); - } - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); - } - - float boltPct = mHorizontal ? - (mBoltFrame.left - levelTop) / (mBoltFrame.left - mBoltFrame.right) : - (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); - boltPct = Math.min(Math.max(boltPct, 0), 1); - if (boltPct <= BOLT_LEVEL_THRESHOLD) { - // draw the bolt if opaque - c.drawPath(mBoltPath, mBoltPaint); - } else { - // otherwise cut the bolt out of the overall shape - mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); - } - } - - // compute percentage text - boolean pctOpaque = false; - float pctX = 0, pctY = 0; - String pctText = null; - if (!tracker.plugged && level > mCriticalLevel && mShowPercent) { - mTextPaint.setColor(getColorForLevel(level)); - final float full = mHorizontal ? 0.60f : 0.45f; - final float nofull = mHorizontal ? 0.75f : 0.6f; - final float single = mHorizontal ? 0.86f : 0.75f; - mTextPaint.setTextSize(height * - (SINGLE_DIGIT_PERCENT ? single - : (tracker.level == 100 ? full : nofull))); - mTextHeight = -mTextPaint.getFontMetrics().ascent; - pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); - pctX = mWidth * 0.5f; - pctY = (mHeight + mTextHeight) * 0.47f; - if (mHorizontal) { - pctOpaque = pctX > levelTop; - } else { - pctOpaque = levelTop > pctY; - } - if (!pctOpaque) { - mTextPath.reset(); - mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); - // cut the percentage text out of the overall shape - mShapePath.op(mTextPath, Path.Op.DIFFERENCE); - } - } - - // draw the battery shape background - c.drawPath(mShapePath, mFramePaint); - - // draw the battery shape, clipped to charging level - if (mHorizontal) { - mFrame.right = levelTop; - } else { - mFrame.top = levelTop; - } - mClipPath.reset(); - mClipPath.addRect(mFrame, Path.Direction.CCW); - mShapePath.op(mClipPath, Path.Op.INTERSECT); - c.drawPath(mShapePath, mBatteryPaint); - - if (!tracker.plugged) { - if (level <= mCriticalLevel) { - // draw the warning text - final float x = mWidth * 0.5f; - final float y = (mHeight + mWarningTextHeight) * 0.48f; - c.drawText(mWarningString, x, y, mWarningTextPaint); - } else if (pctOpaque) { - // draw the percentage text - c.drawText(pctText, pctX, pctY, mTextPaint); - } + drawBattery(c, tracker); + if (mAnimationsEnabled) { + // TODO: Allow custom animations to be used } } @@ -727,274 +550,293 @@ public void onDispose() { @Override public void setDarkIntensity(int backgroundColor, int fillColor) { mIconTint = fillColor; - mFramePaint.setColor(backgroundColor); - mBoltPaint.setColor(fillColor); - mChargeColor = fillColor; + // Make bolt fully opaque for increased visibility + mBoltDrawable.setTint(0xff000000 | fillColor); + mFrameDrawable.setTint(backgroundColor); + updateBoltDrawableLayer(mBatteryDrawable, mBoltDrawable); invalidate(); } @Override public void onSizeChanged(int w, int h, int oldw, int oldh) { - mHeight = h; - mWidth = w; - mWarningTextPaint.setTextSize(h * 0.75f); - mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; - } - - private float[] loadBoltPoints(Resources res) { - final int[] pts = res.getIntArray((mHorizontal - ? R.array.batterymeter_inverted_bolt_points - : R.array.batterymeter_bolt_points)); - int maxX = 0, maxY = 0; - for (int i = 0; i < pts.length; i += 2) { - maxX = Math.max(maxX, pts[i]); - maxY = Math.max(maxY, pts[i + 1]); - } - final float[] ptsF = new float[pts.length]; - for (int i = 0; i < pts.length; i += 2) { - ptsF[i] = (float)pts[i] / maxX; - ptsF[i + 1] = (float)pts[i + 1] / maxY; - } - return ptsF; + init(); } - } - - protected class CircleBatteryMeterDrawable implements BatteryMeterDrawable { - private static final boolean SINGLE_DIGIT_PERCENT = false; - private static final boolean SHOW_100_PERCENT = false; - - private static final int FULL = 96; - - public static final float STROKE_WITH = 6.5f; - - private boolean mDisposed; - - private int mAnimOffset; - private boolean mIsAnimating; // stores charge-animation status to reliably - //remove callbacks - - private int mCircleSize; // draw size of circle - private RectF mRectLeft; // contains the precalculated rect used in drawArc(), - // derived from mCircleSize - private float mTextX, mTextY; // precalculated position for drawText() to appear centered - - private Paint mTextPaint; - private Paint mFrontPaint; - private Paint mBackPaint; - private Paint mBoltPaint; - private Paint mWarningTextPaint; - - private final RectF mBoltFrame = new RectF(); - private int mChargeColor; - private final float[] mBoltPoints; - private final Path mBoltPath = new Path(); - - public CircleBatteryMeterDrawable(Resources res) { - super(); - mDisposed = false; - - mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); - mTextPaint.setTypeface(font); - mTextPaint.setTextAlign(Paint.Align.CENTER); - - mFrontPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mFrontPaint.setStrokeCap(Paint.Cap.BUTT); - mFrontPaint.setDither(true); - mFrontPaint.setStrokeWidth(0); - mFrontPaint.setStyle(Paint.Style.STROKE); - - mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBackPaint.setColor(res.getColor(R.color.batterymeter_frame_color)); - mBackPaint.setStrokeCap(Paint.Cap.BUTT); - mBackPaint.setDither(true); - mBackPaint.setStrokeWidth(0); - mBackPaint.setStyle(Paint.Style.STROKE); - - mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mWarningTextPaint.setColor(mColors[1]); - font = Typeface.create("sans-serif", Typeface.BOLD); - mWarningTextPaint.setTypeface(font); - mWarningTextPaint.setTextAlign(Paint.Align.CENTER); - - mChargeColor = getResources().getColor(R.color.batterymeter_charge_color); - - mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color)); - mBoltPoints = loadBoltPoints(res); + private boolean isThemeApplied() { + ThemeConfig themeConfig = ThemeConfig.getBootTheme(getContext().getContentResolver()); + return themeConfig != null && + !ThemeConfig.SYSTEM_DEFAULT.equals(themeConfig.getOverlayForStatusBar()); } - @Override - public void onDraw(Canvas c, BatteryTracker tracker) { - if (mDisposed) return; + private void checkBatteryMeterDrawableValid(Resources res, BatteryMeterMode mode) { + final int resId = getBatteryDrawableResourceForMode(mode); + final Drawable batteryDrawable; + try { + batteryDrawable = res.getDrawable(resId); + } catch (Resources.NotFoundException e) { + throw new BatteryMeterDrawableException(res.getResourceName(resId) + " is an " + + "invalid drawable", e); + } - if (mRectLeft == null) { - initSizeBasedStuff(); + // check that the drawable is a LayerDrawable + if (!(batteryDrawable instanceof LayerDrawable)) { + throw new BatteryMeterDrawableException("Expected a LayerDrawable but received a " + + batteryDrawable.getClass().getSimpleName()); } - drawCircle(c, tracker, mTextX, mRectLeft); - if (mAnimationsEnabled) { - updateChargeAnim(tracker); + final LayerDrawable layerDrawable = (LayerDrawable) batteryDrawable; + final Drawable frame = layerDrawable.findDrawableByLayerId(R.id.battery_frame); + final Drawable level = layerDrawable.findDrawableByLayerId(R.id.battery_fill); + final Drawable bolt = layerDrawable.findDrawableByLayerId( + R.id.battery_charge_indicator); + // now check that the required layers exist and are of the correct type + if (frame == null) { + throw new BatteryMeterDrawableException("Missing battery_frame drawble"); + } + if (bolt == null) { + throw new BatteryMeterDrawableException( + "Missing battery_charge_indicator drawable"); + } + if (level != null) { + // check that the level drawable is an AnimatedVectorDrawable + if (!(level instanceof AnimatedVectorDrawable)) { + throw new BatteryMeterDrawableException("Expected a AnimatedVectorDrawable " + + "but received a " + level.getClass().getSimpleName()); + } + // make sure we can stop motion animate the level drawable + try { + StopMotionVectorDrawable smvd = new StopMotionVectorDrawable(level); + smvd.setCurrentFraction(0.5f); + } catch (Exception e) { + throw new BatteryMeterDrawableException("Unable to perform stop motion on " + + "battery_fill drawable", e); + } + } else { + throw new BatteryMeterDrawableException("Missing battery_fill drawable"); } } - @Override - public void onDispose() { - mDisposed = true; - } + private void loadBatteryDrawables(Resources res, BatteryMeterMode mode) { + if (isThemeApplied()) { + try { + checkBatteryMeterDrawableValid(res, mode); + } catch (BatteryMeterDrawableException e) { + Log.w(TAG, "Invalid themed battery meter drawable, falling back to system", e); + final Context context = getContext(); + PackageManager pm = getContext().getPackageManager(); + try { + res = pm.getThemedResourcesForApplication(context.getPackageName(), + ThemeConfig.SYSTEM_DEFAULT); + } catch (PackageManager.NameNotFoundException nnfe) { + /* ignore, this should not happen */ + } + } + } - @Override - public void setDarkIntensity(int backgroundColor, int fillColor) { - mIconTint = fillColor; - mBoltPaint.setColor(fillColor); - mChargeColor = fillColor; - invalidate(); + int drawableResId = getBatteryDrawableResourceForMode(mode); + mBatteryDrawable = (LayerDrawable) res.getDrawable(drawableResId); + mFrameDrawable = mBatteryDrawable.findDrawableByLayerId(R.id.battery_frame); + mFrameDrawable.setTint(mCurrentBackgroundColor != 0 + ? mCurrentBackgroundColor + : res.getColor(R.color.batterymeter_frame_color)); + // set the animated vector drawable we will be stop animating + Drawable levelDrawable = mBatteryDrawable.findDrawableByLayerId(R.id.battery_fill); + mLevelDrawable = new StopMotionVectorDrawable(levelDrawable); + mBoltDrawable = mBatteryDrawable.findDrawableByLayerId(R.id.battery_charge_indicator); } - @Override - public void onSizeChanged(int w, int h, int oldw, int oldh) { - initSizeBasedStuff(); - } + private void drawBattery(Canvas canvas, BatteryTracker tracker) { + boolean unknownStatus = tracker.status == BatteryManager.BATTERY_STATUS_UNKNOWN; + int level = tracker.level; - private float[] loadBoltPoints(Resources res) { - final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); - int maxX = 0, maxY = 0; - for (int i = 0; i < pts.length; i += 2) { - maxX = Math.max(maxX, pts[i]); - maxY = Math.max(maxY, pts[i + 1]); - } - final float[] ptsF = new float[pts.length]; - for (int i = 0; i < pts.length; i += 2) { - ptsF[i] = (float)pts[i] / maxX; - ptsF[i + 1] = (float)pts[i + 1] / maxY; + if (unknownStatus || tracker.status == BatteryManager.BATTERY_STATUS_FULL) { + level = 100; } - return ptsF; - } - private void drawCircle(Canvas canvas, BatteryTracker tracker, - float textX, RectF drawRect) { - boolean unknownStatus = tracker.status == BatteryManager.BATTERY_STATUS_UNKNOWN; - int level = tracker.level; - Paint paint; + mTextAndBoltPaint.setColor(getColorForLevel(level)); - if (unknownStatus) { - paint = mBackPaint; - level = 100; // Draw all the circle; + // Make sure we don't draw the charge indicator if not plugged in + Drawable d = mBatteryDrawable.findDrawableByLayerId(R.id.battery_charge_indicator); + if (d instanceof BitmapDrawable) { + // In case we are using a BitmapDrawable, which we should be unless something bad + // happened, we need to change the paint rather than the alpha in case the blendMode + // has been set to clear. Clear always clears regardless of alpha level ;) + BitmapDrawable bd = (BitmapDrawable) d; + bd.getPaint().set(tracker.plugged ? mTextAndBoltPaint : mClearPaint); } else { - paint = mFrontPaint; - paint.setColor(getColorForLevel(level)); - if (tracker.status == BatteryManager.BATTERY_STATUS_FULL) { - level = 100; - } + d.setAlpha(tracker.plugged ? 255 : 0); } - // draw thin gray ring first - canvas.drawArc(drawRect, 270, 360, false, mBackPaint); - if (level != 0) { - // draw colored arc representing charge level - canvas.drawArc(drawRect, 270 + mAnimOffset, 3.6f * level, false, paint); - } + // Now draw the level indicator + // set the level and tint color of the fill drawable + mLevelDrawable.setCurrentFraction(level / 100f); + mLevelDrawable.setTint(getColorForLevel(level)); + mBatteryDrawable.draw(canvas); + // if chosen by options, draw percentage text in the middle // always skip percentage when 100, so layout doesnt break if (unknownStatus) { - mTextPaint.setColor(paint.getColor()); - canvas.drawText("?", textX, mTextY, mTextPaint); + mTextAndBoltPaint.setColor(getContext().getColor(R.color.batterymeter_frame_color)); + canvas.drawText("?", mTextX, mTextY, mTextAndBoltPaint); - } else if (tracker.plugged) { - canvas.drawPath(mBoltPath, mBoltPaint); - } else { - if (level > mCriticalLevel - && (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT))) { - // draw the percentage text - String pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); - mTextPaint.setColor(paint.getColor()); - canvas.drawText(pctText, textX, mTextY, mTextPaint); - } else if (level <= mCriticalLevel) { - // draw the warning text - canvas.drawText(mWarningString, textX, mTextY, mWarningTextPaint); - } + } else if (!tracker.plugged) { + drawPercentageText(canvas, tracker); + } + } + + private void drawPercentageText(Canvas canvas, BatteryTracker tracker) { + final int level = tracker.level; + if (level > mCriticalLevel + && (mShowPercent && !(level == 100 && !SHOW_100_PERCENT))) { + // draw the percentage text + String pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); + mTextAndBoltPaint.setColor(getColorForLevel(level)); + canvas.drawText(pctText, mTextX, mTextY, mTextAndBoltPaint); + } else if (level <= mCriticalLevel) { + // draw the warning text + canvas.drawText(mWarningString, mTextX, mTextY, mWarningTextPaint); } } /** - * updates the animation counter - * cares for timed callbacks to continue animation cycles - * uses mInvalidate for delayed invalidate() callbacks + * initializes all size dependent variables */ - private void updateChargeAnim(BatteryTracker tracker) { - // Stop animation when battery is full or after the meter - // rotated back to 0 after unplugging. - if (!tracker.shouldIndicateCharging() - || tracker.status == BatteryManager.BATTERY_STATUS_FULL - || tracker.level == 0) { - mIsAnimating = false; + private void init() { + // not much we can do with zero width or height, we'll get another pass later + if (mWidth <= 0 || mHeight <=0) return; + + final float widthDiv2 = mWidth / 2f; + // text size is width / 2 - 2dp for wiggle room + final float textSize = widthDiv2 - getResources().getDisplayMetrics().density * 2; + mTextAndBoltPaint.setTextSize(textSize); + mWarningTextPaint.setTextSize(textSize); + + int pLeft = getPaddingLeft(); + Rect iconBounds = new Rect(pLeft, 0, pLeft + mWidth, mHeight); + mBatteryDrawable.setBounds(iconBounds); + + // calculate text position + Rect bounds = new Rect(); + mTextAndBoltPaint.getTextBounds("99", 0, "99".length(), bounds); + boolean isRtl = isLayoutRtl(); + + // compute mTextX based on text gravity + if ((mTextGravity & Gravity.START) == Gravity.START) { + mTextX = isRtl ? mWidth : 0; + } else if ((mTextGravity & Gravity.END) == Gravity.END) { + mTextX = isRtl ? 0 : mWidth; + } else if ((mTextGravity & Gravity.LEFT) == Gravity.LEFT) { + mTextX = 0; + }else if ((mTextGravity & Gravity.RIGHT) == Gravity.RIGHT) { + mTextX = mWidth; } else { - mIsAnimating = true; + mTextX = widthDiv2 + pLeft; } - if (mAnimOffset > 360) { - mAnimOffset = 0; + // compute mTextY based on text gravity + if ((mTextGravity & Gravity.TOP) == Gravity.TOP) { + mTextY = bounds.height(); + } else if ((mTextGravity & Gravity.BOTTOM) == Gravity.BOTTOM) { + mTextY = mHeight; + } else { + mTextY = widthDiv2 + bounds.height() / 2.0f; } - boolean continueAnimation = mIsAnimating || mAnimOffset != 0; + updateBoltDrawableLayer(mBatteryDrawable, mBoltDrawable); + + mInitialized = true; + } - if (continueAnimation) { - mAnimOffset += 3; + private int getBatteryDrawableResourceForMode(BatteryMeterMode mode) { + switch (mode) { + case BATTERY_METER_ICON_LANDSCAPE: + return R.drawable.ic_battery_landscape; + case BATTERY_METER_CIRCLE: + return R.drawable.ic_battery_circle; + case BATTERY_METER_ICON_PORTRAIT: + return R.drawable.ic_battery_portrait; + default: + return 0; } + } - if (continueAnimation) { - postInvalidateDelayed(50); + private int getBatteryDrawableStyleResourceForMode(BatteryMeterMode mode) { + switch (mode) { + case BATTERY_METER_ICON_LANDSCAPE: + return R.style.BatteryMeterViewDrawable_Landscape; + case BATTERY_METER_CIRCLE: + return R.style.BatteryMeterViewDrawable_Circle; + case BATTERY_METER_ICON_PORTRAIT: + return R.style.BatteryMeterViewDrawable_Portrait; + default: + return R.style.BatteryMeterViewDrawable; } } - /** - * initializes all size dependent variables - * sets stroke width and text size of all involved paints - * YES! i think the method name is appropriate - */ - private void initSizeBasedStuff() { - mCircleSize = Math.min(getMeasuredWidth(), getMeasuredHeight()); - mTextPaint.setTextSize(mCircleSize / 2f); - mWarningTextPaint.setTextSize(mCircleSize / 2f); + private Paint.Align getPaintAlignmentFromGravity(int gravity) { + boolean isRtl = isLayoutRtl(); + if ((gravity & Gravity.START) == Gravity.START) { + return isRtl ? Paint.Align.RIGHT : Paint.Align.LEFT; + } + if ((gravity & Gravity.END) == Gravity.END) { + return isRtl ? Paint.Align.LEFT : Paint.Align.RIGHT; + } + if ((gravity & Gravity.LEFT) == Gravity.LEFT) return Paint.Align.LEFT; + if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) return Paint.Align.RIGHT; - float strokeWidth = mCircleSize / STROKE_WITH; - mFrontPaint.setStrokeWidth(strokeWidth); - mBackPaint.setStrokeWidth(strokeWidth); + // default to center + return Paint.Align.CENTER; + } - // calculate rectangle for drawArc calls - int pLeft = getPaddingLeft(); - mRectLeft = new RectF(pLeft + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize - - strokeWidth / 2.0f + pLeft, mCircleSize - strokeWidth / 2.0f); + // Creates a BitmapDrawable of the bolt so we can make use of the XOR xfer mode with vector + // based drawables + private void updateBoltDrawableLayer(LayerDrawable batteryDrawable, Drawable boltDrawable) { + BitmapDrawable newBoltDrawable; + if (boltDrawable instanceof BitmapDrawable) { + newBoltDrawable = (BitmapDrawable) boltDrawable.mutate(); + } else { + Bitmap boltBitmap = createBoltBitmap(boltDrawable); + if (boltBitmap == null) { + // not much to do with a null bitmap so keep original bolt for now + return; + } + Rect bounds = boltDrawable.getBounds(); + newBoltDrawable = new BitmapDrawable(getResources(), boltBitmap); + newBoltDrawable.setBounds(bounds); + } + newBoltDrawable.getPaint().set(mTextAndBoltPaint); + batteryDrawable.setDrawableByLayerId(R.id.battery_charge_indicator, newBoltDrawable); + } - // calculate Y position for text - Rect bounds = new Rect(); - mTextPaint.getTextBounds("99", 0, "99".length(), bounds); - mTextX = mCircleSize / 2.0f + getPaddingLeft(); - // the +1dp at end of formula balances out rounding issues.works out on all resolutions - mTextY = mCircleSize / 2.0f + (bounds.bottom - bounds.top) / 2.0f - - strokeWidth / 2.0f + getResources().getDisplayMetrics().density; - - // draw the bolt - final float bl = (int) (mRectLeft.left + mRectLeft.width() / 3.2f); - final float bt = (int) (mRectLeft.top + mRectLeft.height() / 4f); - final float br = (int) (mRectLeft.right - mRectLeft.width() / 5.2f); - final float bb = (int) (mRectLeft.bottom - mRectLeft.height() / 8f); - if (mBoltFrame.left != bl || mBoltFrame.top != bt - || mBoltFrame.right != br || mBoltFrame.bottom != bb) { - mBoltFrame.set(bl, bt, br, bb); - mBoltPath.reset(); - mBoltPath.moveTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); - for (int i = 2; i < mBoltPoints.length; i += 2) { - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); + private Bitmap createBoltBitmap(Drawable boltDrawable) { + // not much we can do with zero width or height, we'll get another pass later + if (mWidth <= 0 || mHeight <= 0) return null; + + Bitmap bolt; + if (!(boltDrawable instanceof BitmapDrawable)) { + int pLeft = getPaddingLeft(); + Rect iconBounds = new Rect(pLeft, 0, pLeft + mWidth, mHeight); + bolt = Bitmap.createBitmap(iconBounds.width(), iconBounds.height(), + Bitmap.Config.ARGB_8888); + if (bolt != null) { + Canvas c = new Canvas(bolt); + c.drawColor(-1, PorterDuff.Mode.CLEAR); + boltDrawable.draw(c); } - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); + } else { + bolt = ((BitmapDrawable) boltDrawable).getBitmap(); + } + + return bolt; + } + + private class BatteryMeterDrawableException extends RuntimeException { + public BatteryMeterDrawableException(String detailMessage) { + super(detailMessage); + } + + public BatteryMeterDrawableException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); } } } diff --git a/core/java/android/content/res/ThemeChangeRequest.aidl b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java similarity index 56% rename from core/java/android/content/res/ThemeChangeRequest.aidl rename to packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java index e6cf11561b28c..1678e9460fb2b 100644 --- a/core/java/android/content/res/ThemeChangeRequest.aidl +++ b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.res; -/** @hide */ -parcelable ThemeChangeRequest; +package com.android.systemui; + +import android.content.Context; +import android.graphics.Paint; +import android.util.AttributeSet; + +public class DockBatteryLevelTextView extends BatteryLevelTextView { + + public DockBatteryLevelTextView(Context context, AttributeSet attrs) { + super(context, attrs); + setPaintFlags(getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java new file mode 100755 index 0000000000000..a29b16ce1e7be --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import android.content.Context; +import android.content.Intent; +import android.os.BatteryManager; +import android.util.AttributeSet; +import android.view.View; + +public class DockBatteryMeterView extends BatteryMeterView { + + private BatteryManager mBatteryService; + private final boolean mSupported; + + private class DockBatteryTracker extends BatteryTracker { + + public DockBatteryTracker() { + super(); + present = false; + } + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { + if (testmode && ! intent.getBooleanExtra("testmode", false)) return; + + if (mSupported) { + level = (int)(100f + * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0) + / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100)); + + present = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false); + plugType = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0); + // We need to add a extra check over the status because of dock batteries + // PlugType doesn't means that the dock battery is charging (some devices + // doesn't charge under dock usb) + plugged = plugType != 0 && (status == BatteryManager.BATTERY_STATUS_CHARGING || + status == BatteryManager.BATTERY_STATUS_FULL); + health = intent.getIntExtra(BatteryManager.EXTRA_DOCK_HEALTH, + BatteryManager.BATTERY_HEALTH_UNKNOWN); + status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN); + technology = intent.getStringExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY); + voltage = intent.getIntExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, 0); + temperature = intent.getIntExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE, 0); + + + if (present && (mMeterMode != BatteryMeterMode.BATTERY_METER_GONE && + mMeterMode != BatteryMeterMode.BATTERY_METER_TEXT)) { + setContentDescription(context.getString( + R.string.accessibility_dock_battery_level, level)); + setVisibility(View.VISIBLE); + invalidate(); + } else { + setContentDescription(null); + setVisibility(View.GONE); + } + } else { + setContentDescription(null); + setVisibility(View.GONE); + + // If dock is not supported then we don't need this receiver anymore + getContext().unregisterReceiver(this); + } + } else if (action.equals(ACTION_LEVEL_TEST)) { + testmode = true; + post(new Runnable() { + int curLevel = 0; + int incr = 1; + int saveLevel = level; + int savePlugged = plugType; + Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); + @Override + public void run() { + if (curLevel < 0) { + testmode = false; + dummy.putExtra("level", saveLevel); + dummy.putExtra("plugged", savePlugged); + dummy.putExtra("testmode", false); + } else { + dummy.putExtra("level", curLevel); + dummy.putExtra("plugged", incr > 0 + ? BatteryManager.BATTERY_DOCK_PLUGGED_AC : 0); + dummy.putExtra("testmode", true); + } + getContext().sendBroadcast(dummy); + + if (!testmode) return; + + curLevel += incr; + if (curLevel == 100) { + incr *= -1; + } + postDelayed(this, 200); + } + }); + } + } + } + + public DockBatteryMeterView(Context context) { + this(context, null, 0); + } + + public DockBatteryMeterView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DockBatteryMeterView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE)); + mSupported = mBatteryService.isDockBatterySupported(); + mDemoTracker = new DockBatteryTracker(); + mTracker = new DockBatteryTracker(); + } + + @Override + public void onDetachedFromWindow() { + // We already unregistered the listener once when we decided + // support was absent. Don't do it again. + if (mSupported) { + super.onDetachedFromWindow(); + } + } + + @Override + public void setMode(BatteryMeterMode mode) { + super.setMode(mode); + int visibility = getVisibility(); + if (visibility == View.VISIBLE && !mSupported) { + setVisibility(View.GONE); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags b/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags index a584cf638177b..a08d4b75cd3e3 100644 --- a/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags +++ b/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags @@ -51,3 +51,28 @@ option java_package com.android.systemui; # SearchPanelView.java # --------------------------- 36050 sysui_searchpanel_touch (type|1),(x|1),(y|1) + +# --------------------------- +# LiveLockScreenController.java +# --------------------------- +# sysui_lls_keyguard_showing +## screenOn: 0:screen turned off +## 1:screen turned on +36060 sysui_lls_keyguard_showing (screenOn|1) +# sysui_lls_keyguard_dismissed: Logged when user unlocks the device +## onLls: 0:dismissed while showing notifications +## 1:dismissed while user interacting with LLS +36061 sysui_lls_keyguard_dismissed (onLls|1) +# sysui_lls_notification_panel_shown: Logged when the notification panel is swiped in and out +## shown: 0:panel is hidden +## 1:panel is visible +36062 sysui_lls_notification_panel_shown (shown|1) + +# --------------------------- +# RecentsView.java +# --------------------------- +36070 sysui_recents_event (what|1) +## what: 1: OPEN +## 2: CLOSE +## 3: CHOSE_TASK +## 4: CLOSE_ALL_TASKS diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index 1dca14928c6d1..59119168fa14b 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -36,6 +36,7 @@ import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.FlingAnimationUtils; +import com.android.systemui.statusbar.MediaExpandableNotificationRow; import com.android.systemui.statusbar.policy.ScrollAdapter; public class ExpandHelper implements Gefingerpoken { @@ -96,7 +97,7 @@ public interface Callback { private float mCurrentHeight; private int mSmallSize; - private int mLargeSize; + private int mLargeSize, mInitialLargeSize; private float mMaximumStretch; private boolean mOnlyMovements; @@ -161,6 +162,7 @@ public ExpandHelper(Context context, Callback callback, int small, int large) { mSmallSize = small; mMaximumStretch = mSmallSize * STRETCH_INTERVAL; mLargeSize = large; + mInitialLargeSize = large; mContext = context; mCallback = callback; mScaler = new ViewScaler(); @@ -511,7 +513,14 @@ private boolean startExpanding(ExpandableView v, int expandType) { mCurrentHeight = mOldHeight; if (mCallback.canChildBeExpanded(v)) { if (DEBUG) Log.d(TAG, "working on an expandable child"); - mNaturalHeight = mScaler.getNaturalHeight(mLargeSize); + if (v instanceof MediaExpandableNotificationRow) { + final int maxHeight = ((MediaExpandableNotificationRow) v).getMaxContentHeight(); + mLargeSize = maxHeight; + mNaturalHeight = maxHeight; + } else { + mLargeSize = mInitialLargeSize; + mNaturalHeight = mScaler.getNaturalHeight(mLargeSize); + } } else { if (DEBUG) Log.d(TAG, "working on a non-expandable child"); mNaturalHeight = mOldHeight; diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 33f6564b948a4..c3e50436cdb49 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -45,9 +45,15 @@ public class SwipeHelper implements Gefingerpoken { public static final int X = 0; public static final int Y = 1; + public static final int SWIPE_ZONE_LEFT = 0x1; + public static final int SWIPE_ZONE_RIGHT = 0x2; + public static final int SWIPE_ZONE_TOP = 0x4; + public static final int SWIPE_ZONE_BOTTOM = 0x8; private static LinearInterpolator sLinearInterpolator = new LinearInterpolator(); private final Interpolator mFastOutLinearInInterpolator; + private final int mTouchSlop; + private int mSwipeZone; private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms @@ -69,6 +75,7 @@ public class SwipeHelper implements Gefingerpoken { private VelocityTracker mVelocityTracker; private float mInitialTouchPos; + private float mPerpendicularInitialTouchPos; private boolean mDragging; private View mCurrView; private View mCurrAnimView; @@ -84,6 +91,8 @@ public class SwipeHelper implements Gefingerpoken { private int mFalsingThreshold; private boolean mTouchAboveFalsingThreshold; + private float mSwipeProgressFadeEnd; + public SwipeHelper(int swipeDirection, Callback callback, Context context) { mCallback = callback; mHandler = new Handler(); @@ -91,12 +100,28 @@ public SwipeHelper(int swipeDirection, Callback callback, Context context) { mVelocityTracker = VelocityTracker.obtain(); mDensityScale = context.getResources().getDisplayMetrics().density; mPagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop(); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mLongPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f); // extra long-press! mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_linear_in); mFalsingThreshold = context.getResources().getDimensionPixelSize( R.dimen.swipe_helper_falsing_threshold); + if (swipeDirection == X) { + mSwipeZone = SWIPE_ZONE_LEFT | SWIPE_ZONE_RIGHT; + } else { + mSwipeZone = SWIPE_ZONE_TOP | SWIPE_ZONE_BOTTOM; + } + mSwipeProgressFadeEnd = SWIPE_PROGRESS_FADE_END; + } + + public SwipeHelper(int swipeDirection, int swipeZone, Callback callback, Context context) { + this(swipeDirection, callback, context); + mSwipeZone = swipeZone; + } + + public boolean isDragging() { + return mDragging; } public void setLongPressListener(LongPressListener listener) { @@ -115,6 +140,10 @@ private float getPos(MotionEvent ev) { return mSwipeDirection == X ? ev.getX() : ev.getY(); } + private float getPerpendicularPos(MotionEvent ev) { + return mSwipeDirection == X ? ev.getY() : ev.getX(); + } + private float getTranslation(View v) { return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY(); } @@ -158,7 +187,7 @@ public void setMaxSwipeProgress(float maxSwipeProgress) { private float getSwipeProgressForOffset(View view) { float viewSize = getSize(view); - final float fadeSize = SWIPE_PROGRESS_FADE_END * viewSize; + final float fadeSize = mSwipeProgressFadeEnd * viewSize; float result = 1.0f; float pos = getTranslation(view); if (pos >= viewSize * SWIPE_PROGRESS_FADE_START) { @@ -236,6 +265,7 @@ public boolean onInterceptTouchEvent(final MotionEvent ev) { mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); mVelocityTracker.addMovement(ev); mInitialTouchPos = getPos(ev); + mPerpendicularInitialTouchPos = getPerpendicularPos(ev); if (mLongPressListener != null) { if (mWatchLongPress == null) { @@ -413,11 +443,30 @@ public boolean onTouchEvent(MotionEvent ev) { case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_MOVE: if (mCurrView != null) { + float pos = getPos(ev); + float altPos = getPerpendicularPos(ev); float delta = getPos(ev) - mInitialTouchPos; float absDelta = Math.abs(delta); if (absDelta >= getFalsingThreshold()) { mTouchAboveFalsingThreshold = true; } + + boolean touchBeyondZoneLimit = true; + if (mSwipeDirection == X) { + if ((mSwipeZone & SWIPE_ZONE_RIGHT) == 0 && pos > mInitialTouchPos) { + touchBeyondZoneLimit = false; + } else if ((mSwipeZone & SWIPE_ZONE_LEFT) == 0 && pos < mInitialTouchPos) { + touchBeyondZoneLimit = false; + } + } else { + if ((mSwipeZone & SWIPE_ZONE_TOP) == 0 && altPos < mPerpendicularInitialTouchPos) { + touchBeyondZoneLimit = false; + } else if ((mSwipeZone & SWIPE_ZONE_BOTTOM) == 0 && pos > mInitialTouchPos) { + touchBeyondZoneLimit = false; + } + } + if (!touchBeyondZoneLimit) return false; + // don't let items that can't be dismissed be dragged more than // maxScrollDistance if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) { @@ -470,6 +519,10 @@ public boolean onTouchEvent(MotionEvent ev) { return true; } + public void setSwipeProgressFadeEnd(float end) { + mSwipeProgressFadeEnd = end; + } + private int getFalsingThreshold() { float factor = mCallback.getFalsingThresholdFactor(); return (int) (mFalsingThreshold * factor); @@ -505,6 +558,49 @@ public interface Callback { float getFalsingThresholdFactor(); } + public static abstract class SimpleCallback implements Callback { + public abstract View getChildAtPosition(MotionEvent ev); + public abstract View getChildContentView(View v); + + @Override + public boolean canChildBeDismissed(View v) { + return false; + } + + @Override + public boolean isAntiFalsingNeeded() { + return false; + } + + @Override + public void onBeginDrag(View v) { + } + + @Override + public void onChildDismissed(View v) { + } + + @Override + public void onDragCancelled(View v) { + } + + @Override + public void onChildSnappedBack(View animView) { + } + + @Override + public boolean updateSwipeProgress(View animView, + boolean dismissable, + float swipeProgress) { + return false; + } + + @Override + public float getFalsingThresholdFactor() { + return 0; + } + } + /** * Equivalent to View.OnLongClickListener with coordinates */ diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 0b066afe26d5d..565fbd7d47704 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; +import android.content.res.ThemeConfig; import android.os.SystemProperties; import android.util.Log; @@ -58,6 +59,7 @@ public class SystemUIApplication extends Application { private boolean mServicesStarted; private boolean mBootCompleted; private final Map, Object> mComponents = new HashMap, Object>(); + private Configuration mConfig; @Override public void onCreate() { @@ -85,6 +87,7 @@ public void onReceive(Context context, Intent intent) { } } }, filter); + mConfig = new Configuration(getResources().getConfiguration()); } /** @@ -134,6 +137,12 @@ public void startServicesIfNeeded() { @Override public void onConfigurationChanged(Configuration newConfig) { + if (isThemeChange(mConfig, newConfig)) { + // theme resource changed so recreate styles and attributes + recreateTheme(); + } + + mConfig.setTo(newConfig); if (mServicesStarted) { int len = mServices.length; for (int i = 0; i < len; i++) { @@ -150,4 +159,11 @@ public T getComponent(Class interfaceType) { public SystemUI[] getServices() { return mServices; } + + private static boolean isThemeChange(Configuration oldConfig, Configuration newConfig) { + final ThemeConfig oldThemeConfig = oldConfig != null ? oldConfig.themeConfig : null; + final ThemeConfig newThemeConfig = newConfig != null ? newConfig.themeConfig : null; + + return newThemeConfig != null && !newThemeConfig.equals(oldThemeConfig); + } } diff --git a/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java index d8cfa5e6455b9..3cd86fefbb7f4 100644 --- a/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsActivity.java @@ -1,5 +1,6 @@ package com.android.systemui.cm; +import com.android.internal.app.AssistUtils; import com.android.settingslib.cm.ShortcutPickHelper; import com.android.systemui.R; import com.android.systemui.cm.LockscreenShortcutsHelper.Shortcuts; @@ -34,6 +35,7 @@ public class LockscreenShortcutsActivity extends Activity implements View.OnClic private View mSelectedView; private ColorMatrixColorFilter mFilter; private ColorStateList mDefaultTintList; + private AssistUtils mAssistUtils; @Override public void shortcutPicked(String uri, String friendlyName, boolean isApplication) { @@ -107,6 +109,7 @@ protected void onCreate(Bundle savedInstanceState) { mFilter = new ColorMatrixColorFilter(cm); ImageView unlockButton = (ImageView) findViewById(R.id.middle_button); mDefaultTintList = unlockButton.getImageTintList(); + mAssistUtils = new AssistUtils(this); createActionList(); initiateViews(); updateDrawables(); @@ -146,19 +149,40 @@ private void updateDrawables() { if (mShortcutHelper.isTargetEmpty(shortcut)) { drawable = getResources().getDrawable(R.drawable.ic_lockscreen_shortcuts_blank); } else { - drawable = mShortcutHelper.getDrawableForTarget(shortcut); - if (drawable == null) { - drawable = getResources().getDrawable(shortcut == Shortcuts.LEFT_SHORTCUT - ? R.drawable.ic_phone_24dp : R.drawable.ic_camera_alt_24dp); + if (shortcut == Shortcuts.LEFT_SHORTCUT && + !mShortcutHelper.isTargetCustom(shortcut)) { + drawable = getLeftAffordanceDrawable(); v.setImageTintList(mDefaultTintList); } else { - v.setColorFilter(mFilter); + drawable = mShortcutHelper.getDrawableForTarget(shortcut); + if (drawable == null) { + drawable = (shortcut == Shortcuts.LEFT_SHORTCUT) ? + getLeftAffordanceDrawable() + : getResources().getDrawable(R.drawable.ic_camera_alt_24dp); + v.setImageTintList(mDefaultTintList); + } else { + v.setColorFilter(mFilter); + } } } v.setImageDrawable(drawable); } } + private Drawable getLeftAffordanceDrawable() { + Drawable drawable; + if (canLaunchVoiceAssist()) { + drawable = getResources().getDrawable(R.drawable.ic_mic_26dp); + } else { + drawable = getResources().getDrawable(R.drawable.ic_phone_24dp); + } + return drawable; + } + + private boolean canLaunchVoiceAssist() { + return mAssistUtils.activeServiceSupportsLaunchFromKeyguard(); + } + private void createActionList() { mActions = new ActionHolder(); mActions.addAction(LockscreenShortcutsHelper.NONE, R.string.lockscreen_none_target); @@ -211,13 +235,15 @@ public void onCancel(DialogInterface dialog) { private void onTargetChange(String uri) { if (uri == null) { - final GlowBackground background = (GlowBackground) mSelectedView.getBackground(); - background.hideGlow(); + if (mSelectedView != null) { + final GlowBackground background = (GlowBackground) mSelectedView.getBackground(); + background.hideGlow(); + } return; } if (uri.equals(ACTION_APP)) { - mPicker.pickShortcut(null, null, 0); + mPicker.pickShortcut(null, null, 0, false); } else { mSelectedView.setTag(uri); saveCustomActions(); diff --git a/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java index 12b98107c5dc8..b47b69f58c855 100644 --- a/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java +++ b/packages/SystemUI/src/com/android/systemui/cm/LockscreenShortcutsHelper.java @@ -53,9 +53,15 @@ public LockscreenShortcutsHelper(Context context, OnChangeListener listener) { if (listener != null) { mListener = listener; mHandler = new Handler(Looper.getMainLooper()); - mContext.getContentResolver().registerContentObserver( - CMSettings.Secure.getUriFor(CMSettings.Secure.LOCKSCREEN_TARGETS), false, mObserver); + registerAndFetchTargets(); + } else { + fetchTargets(); } + } + + public void registerAndFetchTargets() { + mContext.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.LOCKSCREEN_TARGETS), false, mObserver); fetchTargets(); } @@ -76,7 +82,6 @@ public void run() { public void cleanup() { mContext.getContentResolver().unregisterContentObserver(mObserver); - mListener = null; } public static class TargetInfo { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index d2c60efd12820..a6ca6a068dd2b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -90,6 +90,12 @@ public void setOccluded(boolean isOccluded) { mKeyguardViewMediator.setOccluded(isOccluded); } + @Override + public void showKeyguard() { + checkPermission(); + mKeyguardViewMediator.showKeyguard(); + } + @Override // Binder interface public void dismiss() { checkPermission(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 0957316a61b67..283375925dd18 100755 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -30,7 +30,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.pm.UserInfo; +import android.database.ContentObserver; import android.media.AudioManager; import android.media.SoundPool; import android.os.Bundle; @@ -51,13 +53,16 @@ import android.util.Log; import android.util.Slog; import android.view.IWindowManager; +import android.view.View; import android.view.ViewGroup; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import com.android.systemui.cm.UserContentObserver; import com.android.systemui.qs.tiles.LockscreenToggleTile; +import com.android.systemui.statusbar.StatusBarState; import cyanogenmod.app.Profile; import cyanogenmod.app.ProfileManager; @@ -78,6 +83,7 @@ import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarWindowManager; +import cyanogenmod.providers.CMSettings; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -147,6 +153,8 @@ public class KeyguardViewMediator extends SystemUI { "com.android.internal.action.KEYGUARD_SERVICE_STATE_CHANGED"; private static final String KEYGUARD_SERVICE_EXTRA_ACTIVE = "active"; + private static final String DECRYPT_STATE = "trigger_restart_framework"; + // used for handler messages private static final int SHOW = 2; private static final int HIDE = 3; @@ -167,6 +175,7 @@ public class KeyguardViewMediator extends SystemUI { private static final int NOTIFY_SCREEN_TURNED_ON = 22; private static final int NOTIFY_SCREEN_TURNED_OFF = 23; private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 24; + private static final int NOTIFY_KEYGUARD_PANEL_FOCUS_CHANGED = 25; /** * The default amount of time we stay awake (used for all key input) @@ -199,7 +208,6 @@ public class KeyguardViewMediator extends SystemUI { private AudioManager mAudioManager; private StatusBarManager mStatusBarManager; private boolean mSwitchingUser; - private ProfileManager mProfileManager; private boolean mSystemReady; private boolean mBootCompleted; private boolean mBootSendUserPresent; @@ -249,6 +257,8 @@ public class KeyguardViewMediator extends SystemUI { // true if the keyguard is hidden by another window private boolean mOccluded = false; + private boolean mKeyguardPanelFocused = false; + /** * Helps remember whether the screen has turned on since the last time * it turned off due to timeout. see {@link #onScreenTurnedOff(int)} @@ -340,9 +350,57 @@ public class KeyguardViewMediator extends SystemUI { */ private boolean mPendingLock; + private boolean mCryptKeeperEnabled = true; + private boolean mWakeAndUnlocking; private IKeyguardDrawnCallback mDrawnCallback; + private LockscreenEnabledSettingsObserver mSettingsObserver; + private PhoneStatusBar mStatusBar; + + public static class LockscreenEnabledSettingsObserver extends UserContentObserver { + + private static final String KEY_ENABLED = "lockscreen_enabled"; + + private boolean mObserving; + private SharedPreferences mPrefs; + private Context mContext; + + public LockscreenEnabledSettingsObserver(Context context, Handler handler) { + super(handler); + mContext = context; + mPrefs = mContext.getSharedPreferences("quicksettings", Context.MODE_PRIVATE); + } + + public boolean getPersistedDefaultOldSetting() { + return mPrefs.getBoolean(KEY_ENABLED, true); + } + + @Override + public void observe() { + if (mObserving) { + return; + } + mObserving = true; + mContext.getContentResolver().registerContentObserver(CMSettings.Secure.getUriFor( + CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED), false, this, + UserHandle.USER_ALL); + update(); + } + + @Override + public void unobserve() { + if (mObserving) { + mObserving = false; + mContext.getContentResolver().unregisterContentObserver(this); + } + } + + @Override + public void update() { + } + } + KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -429,21 +487,20 @@ public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simS // only force lock screen in case of missing sim if user hasn't // gone through setup wizard synchronized (this) { - if (shouldWaitForProvisioning()) { - if (!mShowing) { - if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing," - + " we need to show the keyguard since the " - + "device isn't provisioned yet."); - doKeyguardLocked(null); - } else { - resetStateLocked(); - } + if (shouldWaitForProvisioning() && !mShowing) { + if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing," + + " we need to show the keyguard since the " + + "device isn't provisioned yet."); + doKeyguardLocked(null); + } else { + resetStateLocked(); } } break; case PIN_REQUIRED: case PUK_REQUIRED: synchronized (this) { + mStatusBar.hideHeadsUp(); if (!mShowing) { if (DEBUG_SIM_STATES) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't " @@ -469,7 +526,10 @@ public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simS break; case READY: synchronized (this) { - if (mShowing) { + if ((mInternallyDisabled || isProfileDisablingKeyguard()) + && !mUpdateMonitor.isSimPinSecure()) { + hideLocked(); + } else if (mShowing) { resetStateLocked(); } } @@ -577,12 +637,12 @@ private void setupLocked() { mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard"); mShowKeyguardWakeLock.setReferenceCounted(false); - mProfileManager = ProfileManager.getInstance(mContext); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION)); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DISMISS_KEYGUARD_SECURELY_ACTION), android.Manifest.permission.CONTROL_KEYGUARD, null); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(KEYGUARD_SERVICE_ACTION_STATE_CHANGE), android.Manifest.permission.CONTROL_KEYGUARD, null); + mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED)); mKeyguardDisplayManager = new KeyguardDisplayManager(mContext); @@ -634,6 +694,25 @@ private void setupLocked() { mHideAnimation = AnimationUtils.loadAnimation(mContext, com.android.internal.R.anim.lock_screen_behind_enter); + + mSettingsObserver = new LockscreenEnabledSettingsObserver(mContext, new Handler()) { + @Override + public void update() { + boolean newDisabledState = CMSettings.Secure.getIntForUser(mContext.getContentResolver(), + CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED, + getPersistedDefaultOldSetting() ? 1 : 0, + UserHandle.USER_CURRENT) == 0; + + synchronized (KeyguardViewMediator.this) { + if (mKeyguardBound) { + if (newDisabledState != mInternallyDisabled) { + // it was updated, + setKeyguardEnabledInternal(!newDisabledState); + } + } + } + } + }; } @Override @@ -688,7 +767,7 @@ public void onStartedGoingToSleep(int why) { Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e); } mExitSecureCallback = null; - if (!mExternallyEnabled) { + if (!mInternallyDisabled && !mExternallyEnabled) { hideLocked(); } } else if (mShowing) { @@ -841,15 +920,27 @@ private boolean isKeyguardDisabled(int userId) { if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by setting"); return true; } - Profile profile = mProfileManager.getActiveProfile(); - if (profile != null) { - if (profile.getScreenLockMode().getValue() == Profile.LockMode.DISABLE) { - if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by profile"); - return true; - } - } + if (mInternallyDisabled) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled internally"); + return true; + } + if (isProfileDisablingKeyguard()) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by profile"); + return true; + } return false; - } + } + + private boolean isCryptKeeperEnabled() { + if (!mCryptKeeperEnabled) { + // once it's disabled, it's disabled. + return false; + } + final String state = SystemProperties.get("vold.decrypt"); + mCryptKeeperEnabled = !"".equals(state) && !DECRYPT_STATE.equals(state); + if (DEBUG) Log.w(TAG, "updated crypt keeper state to: " + mCryptKeeperEnabled); + return mCryptKeeperEnabled; + } /** * A dream started. We should lock after the usual screen-off lock timeout but only @@ -882,6 +973,10 @@ public void onDreamingStopped() { */ public void setKeyguardEnabledInternal(boolean enabled) { mInternallyDisabled = !enabled; + if (!mUpdateMonitor.isSimPinSecure()) { + // disable when sim is ready + return; + } setKeyguardEnabled(enabled); if (mInternallyDisabled) { mNeedToReshowWhenReenabled = false; @@ -892,6 +987,12 @@ public boolean getKeyguardEnabledInternal() { return !mInternallyDisabled; } + public boolean isProfileDisablingKeyguard() { + final Profile activeProfile = ProfileManager.getInstance(mContext).getActiveProfile(); + return activeProfile != null + && activeProfile.getScreenLockMode().getValue() == Profile.LockMode.DISABLE; + } + /** * Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide * a way for external stuff to override normal keyguard behavior. For instance @@ -900,15 +1001,15 @@ public boolean getKeyguardEnabledInternal() { public void setKeyguardEnabled(boolean enabled) { synchronized (this) { if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")"); - - if (mInternallyDisabled && enabled && !lockscreenEnforcedByDevicePolicy()) { + mExternallyEnabled = enabled; + if (mInternallyDisabled + && enabled + && !lockscreenEnforcedByDevicePolicy()) { // if keyguard is forcefully disabled internally (by lock screen tile), don't allow // it to be enabled externally, unless the device policy manager says so. return; } - mExternallyEnabled = enabled; - if (!enabled && mShowing) { if (mExitSecureCallback != null) { if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring"); @@ -920,7 +1021,7 @@ public void setKeyguardEnabled(boolean enabled) { // hiding keyguard that is showing, remember to reshow later if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, " + "disabling status bar expansion"); - mNeedToReshowWhenReenabled = true; + mNeedToReshowWhenReenabled = !isProfileDisablingKeyguard(); updateInputRestrictedLocked(); hideLocked(); } else if (enabled && mNeedToReshowWhenReenabled) { @@ -1100,22 +1201,6 @@ private void updateInputRestrictedLocked() { * Enable the keyguard if the settings are appropriate. */ private void doKeyguardLocked(Bundle options) { - // if another app is disabling us, don't show - if (!mExternallyEnabled) { - if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); - - // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes - // for an occasional ugly flicker in this situation: - // 1) receive a call with the screen on (no keyguard) or make a call - // 2) screen times out - // 3) user hits key to turn screen back on - // instead, we reenable the keyguard when we know the screen is off and the call - // ends (see the broadcast receiver below) - // TODO: clean this up when we have better support at the window manager level - // for apps that wish to be on top of the keyguard - return; - } - // if the keyguard is already showing, don't bother if (mStatusBarKeyguardViewManager.isShowing()) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); @@ -1123,6 +1208,14 @@ private void doKeyguardLocked(Bundle options) { return; } + // Ugly hack to ensure keyguard is not shown on top of the CryptKeeper which prevents + // a user from being able to decrypt their device. + if (isCryptKeeperEnabled()) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because CryptKeeper is enabled"); + resetStateLocked(); + return; + } + // if the setup wizard hasn't run yet, don't show final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false); final boolean absent = SubscriptionManager.isValidSubscriptionId( @@ -1138,9 +1231,30 @@ private void doKeyguardLocked(Bundle options) { return; } + // if another app is disabling us, don't show + if (!mExternallyEnabled && !lockedOrMissing) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes + // for an occasional ugly flicker in this situation: + // 1) receive a call with the screen on (no keyguard) or make a call + // 2) screen times out + // 3) user hits key to turn screen back on + // instead, we reenable the keyguard when we know the screen is off and the call + // ends (see the broadcast receiver below) + // TODO: clean this up when we have better support at the window manager level + // for apps that wish to be on top of the keyguard + return; + } + if (isKeyguardDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); + // update state + setShowingLocked(false); + updateActivityLockScreenState(); + adjustStatusBarLocked(); + userActivity(); return; } @@ -1165,15 +1279,7 @@ public boolean lockscreenEnforcedByDevicePolicy() { DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); if (dpm != null) { - int passwordQuality = dpm.getPasswordQuality(null); - switch (passwordQuality) { - case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: - case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: - case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: - return true; - } + return dpm.requireSecureKeyguard(); } return false; } @@ -1191,6 +1297,36 @@ public void dismiss() { mHandler.sendEmptyMessage(DISMISS); } + public void showKeyguard() { + // This is to prevent left edge from interfering + // with affordances. + if (mStatusBar.isAffordanceSwipeInProgress() + || mStatusBar.getBarState() == StatusBarState.KEYGUARD) { + return; + } + + // Disable edge detector once we're back on lockscreen + try { + WindowManagerGlobal.getWindowManagerService() + .setLiveLockscreenEdgeDetector(false); + } catch (RemoteException e){ + Log.e(TAG, e.getMessage()); + } + + mHandler.post(new Runnable() { + @Override + public void run() { + // Hide status bar window to avoid flicker, + // slideNotificationPanelIn will make it visible later. + mStatusBar.getStatusBarWindow().setVisibility(View.INVISIBLE); + // Get the keyguard into the correct state by calling mStatusBar.showKeyguard() + mStatusBar.showKeyguard(); + // Now have the notification panel slid back into view + mStatusBar.slideNotificationPanelIn(); + } + }); + } + /** * Send message to keyguard telling it to reset its state. * @see #handleReset @@ -1298,9 +1434,14 @@ public void onReceive(Context context, Intent intent) { } } else if (KEYGUARD_SERVICE_ACTION_STATE_CHANGE.equals(intent.getAction())) { mKeyguardBound = intent.getBooleanExtra(KEYGUARD_SERVICE_EXTRA_ACTIVE, false); - context.sendBroadcast(new Intent( - LockscreenToggleTile.ACTION_APPLY_LOCKSCREEN_STATE) - .setPackage(context.getPackageName())); + if (mKeyguardBound) { + mSettingsObserver.observe(); + } else { + mSettingsObserver.unobserve(); + } + } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction())) { + mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); + if (DEBUG) Log.d(TAG, "phone state change, new state: " + mPhoneState); } } }; @@ -1380,6 +1521,9 @@ public void handleMessage(Message msg) { case ON_ACTIVITY_DRAWN: handleOnActivityDrawn(); break; + case NOTIFY_KEYGUARD_PANEL_FOCUS_CHANGED: + notifyKeyguardPanelFocusChanged(msg.arg1 != 0); + break; } } }; @@ -1466,6 +1610,10 @@ private void playSounds(boolean locked) { private void playSound(int soundId) { if (soundId == 0) return; + if (mInternallyDisabled) { + Log.d(TAG, "suppressing lock screen sounds because it is disabled"); + return; + } final ContentResolver cr = mContext.getContentResolver(); if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) { @@ -1596,7 +1744,9 @@ private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDurati // only play "unlock" noises if not on a call (since the incall UI // disables the keyguard) if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) { - playSounds(false); + if (mShowing && mDeviceInteractive) { + playSounds(false); + } } setShowingLocked(false); @@ -1649,7 +1799,7 @@ private void adjustStatusBarLocked() { private void handleReset() { synchronized (KeyguardViewMediator.this) { if (DEBUG) Log.d(TAG, "handleReset"); - mStatusBarKeyguardViewManager.reset(); + mStatusBarKeyguardViewManager.reset(false); } } @@ -1754,6 +1904,7 @@ public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatus FingerprintUnlockController fingerprintUnlockController) { mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container, statusBarWindowManager, scrimController, fingerprintUnlockController); + mStatusBar = phoneStatusBar; return mStatusBarKeyguardViewManager; } @@ -1824,6 +1975,31 @@ private void setShowingLocked(boolean showing) { } } + public void setKeyguardPanelFocused(boolean focused) { + if (DEBUG) Log.d(TAG, "setSlideOffset " + focused); + mHandler.removeMessages(NOTIFY_KEYGUARD_PANEL_FOCUS_CHANGED); + Message msg = mHandler.obtainMessage(NOTIFY_KEYGUARD_PANEL_FOCUS_CHANGED, + focused ? 1 : 0, 0); + mHandler.sendMessage(msg); + } + + public void notifyKeyguardPanelFocusChanged(boolean focused) { + if (focused != mKeyguardPanelFocused) { + mKeyguardPanelFocused = focused; + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + try { + mKeyguardStateCallbacks.get(i).onKeyguardPanelFocusChanged(focused); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onShowingStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } + } + } + } + } + public void addStateMonitorCallback(IKeyguardStateCallback callback) { synchronized (this) { mKeyguardStateCallbacks.add(callback); @@ -1831,6 +2007,7 @@ public void addStateMonitorCallback(IKeyguardStateCallback callback) { callback.onSimSecureStateChanged(mUpdateMonitor.isSimPinSecure()); callback.onShowingStateChanged(mShowing); callback.onInputRestrictedStateChanged(mInputRestricted); + callback.onKeyguardPanelFocusChanged(mKeyguardPanelFocused); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged or onInputRestrictedStateChanged", e); } diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index a1a11cae1f872..e519e34ceee4b 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -237,8 +237,8 @@ public void onReceive(Context context, Intent intent) { if (mIgnoreFirstPowerEvent) { mIgnoreFirstPowerEvent = false; } else { - if (CMSettings.Global.getInt(cr, - CMSettings.Global.POWER_NOTIFICATIONS_ENABLED, 0) == 1) { + if (Settings.Global.getInt(cr, + Settings.Global.CHARGING_SOUNDS_ENABLED, 0) == 1) { playPowerNotificationSound(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java b/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java index d2d13ae7a93e6..50845da19eb01 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java @@ -49,6 +49,7 @@ public class QSBooleanSettingRow extends LinearLayout implements View.OnClickLis private TextView mText; private Switch mSwitch; private int mDefaultValue; + private CompoundButton.OnCheckedChangeListener mOnCheckedChangeListener; public QSBooleanSettingRow(Context context) { this(context, null); @@ -99,6 +100,9 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + "buttonView = [" + buttonView + "], isChecked = [" + isChecked + "] and table: " + mWhichTable + ", and key: " + mKey); applyChange(isChecked); + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener.onCheckedChanged(buttonView, isChecked); + } } }); } @@ -106,6 +110,13 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { a.recycle(); } + public void setChecked(boolean checked) { + if (mSwitch.isChecked() == checked) { + return; + } + mSwitch.setChecked(checked); + } + private void applyChange(boolean value) { ContentResolver cr = getContext().getContentResolver(); switch (mWhichTable) { @@ -160,4 +171,8 @@ private boolean getCurrent() { public void onClick(View v) { mSwitch.setChecked(!mSwitch.isChecked()); } + + public void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener l) { + mOnCheckedChangeListener = l; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java index 578a9832ca6b6..3e0ab8be0f965 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItemsList.java @@ -27,6 +27,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; @@ -42,7 +43,7 @@ /** * Quick settings common detail list view with line items. */ -public class QSDetailItemsList extends LinearLayout { +public class QSDetailItemsList extends FrameLayout { private static final String TAG = "QSDetailItemsList"; private ListView mListView; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java index 8bbd619fcf8f4..13f552c57ed61 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java @@ -19,76 +19,88 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.ActivityManager; -import android.app.AlertDialog; import android.content.ContentResolver; import android.content.Context; -import android.content.DialogInterface; -import android.content.res.Resources; +import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Point; import android.graphics.PointF; +import android.graphics.PorterDuff; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.UserHandle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; +import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; import android.view.DragEvent; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.EditText; +import android.widget.BaseExpandableListAdapter; +import android.widget.ExpandableListView; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.cm.UserContentObserver; +import com.android.systemui.qs.tiles.CustomQSTile; import com.android.systemui.qs.tiles.EditTile; -import com.android.systemui.qs.tiles.IntentTile; import com.android.systemui.settings.BrightnessController; import com.android.systemui.settings.ToggleSlider; +import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.QSTileHost; -import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.tuner.QsTuner; - import com.viewpagerindicator.CirclePageIndicator; - -import org.cyanogenmod.internal.util.QSUtils; - -import cyanogenmod.providers.CMSettings; - import cyanogenmod.app.StatusBarPanelCustomTile; +import cyanogenmod.providers.CMSettings; +import org.cyanogenmod.internal.logging.CMMetricsLogger; +import org.cyanogenmod.internal.util.QSUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; public class QSDragPanel extends QSPanel implements View.OnDragListener, View.OnLongClickListener { private static final String TAG = "QSDragPanel"; + public static final boolean DEBUG_TILES = false; public static final boolean DEBUG_DRAG = false; private static final int MAX_ROW_COUNT = 3; - private static final int INITIAL_OFFSCREEN_PAGE_LIMIT = 3; - private static final String BROADCAST_TILE_SPEC_PLACEHOLDER = "broadcast_placeholder"; + + // how long to wait before resetting the page + private static final int PAGE_RESET_DELAY = 10000; protected final ArrayList mPages = new ArrayList<>(); + private NotificationPanelView mPanelView; protected QSViewPager mViewPager; protected PagerAdapter mPagerAdapter; QSPanelTopView mQsPanelTop; CirclePageIndicator mPageIndicator; + private int mPageIndicatorHeight; private TextView mDetailRemoveButton; - private DragTileRecord mDraggingRecord; + private DragTileRecord mDraggingRecord, mLastDragRecord; + private ViewGroup mDetailButtons; private boolean mEditing; private boolean mDragging; private float mLastTouchLocationX, mLastTouchLocationY; @@ -105,7 +117,17 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On List mCurrentlyAnimating = Collections.synchronizedList(new ArrayList()); - private Collection> mTempTiles = null; + + private Runnable mResetPage = new Runnable() { + @Override + public void run() { + if (!mExpanded) { + // only reset when the user isn't interacting at all + mViewPager.setCurrentItem(0); + mPagerAdapter.notifyDataSetChanged(); + } + } + }; public QSDragPanel(Context context) { this(context, null); @@ -120,6 +142,7 @@ protected void setupViews() { updateResources(); mDetail = LayoutInflater.from(mContext).inflate(R.layout.qs_detail, this, false); + mDetailButtons = (ViewGroup) mDetail.findViewById(R.id.buttons); mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content); mDetailRemoveButton = (TextView) mDetail.findViewById(android.R.id.button3); mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2); @@ -128,33 +151,20 @@ protected void setupViews() { mDetail.setVisibility(GONE); mDetail.setClickable(true); - mQsPanelTop = (QSPanelTopView) LayoutInflater.from(mContext).inflate(R.layout.qs_tile_top, this, false); + mQsPanelTop = (QSPanelTopView) LayoutInflater.from(mContext).inflate(R.layout.qs_tile_top, + this, false); mBrightnessView = mQsPanelTop.getBrightnessView(); mFooter = new QSFooter(this, mContext); - getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - getViewTreeObserver().removeOnGlobalLayoutListener(this); - - ViewPager.LayoutParams params = new ViewPager.LayoutParams(); - params.isDecor = true; - - mViewPager.addView(mQsPanelTop, params); - - mQsPanelTop.setOnDragListener(QSDragPanel.this); - mPageIndicator.setOnDragListener(QSDragPanel.this); - mViewPager.setOnDragListener(QSDragPanel.this); - } - }); - // add target click listener - mQsPanelTop.findViewById(R.id.add_target).setOnClickListener( + mQsPanelTop.getAddTarget().setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { - showAddDialog(); + TilesListAdapter adapter = new TilesListAdapter(mContext, QSDragPanel.this); + showDetailAdapter(true, adapter, v.getLocationOnScreen()); + mDetail.bringToFront(); } }); mViewPager = new QSViewPager(getContext()); @@ -162,6 +172,7 @@ public void onClick(View v) { mPageIndicator = new CirclePageIndicator(getContext()); addView(mDetail); + addView(mQsPanelTop); addView(mViewPager); addView(mPageIndicator); addView(mFooter.getView()); @@ -184,7 +195,7 @@ public void onClick(View v) { mPagerAdapter = new PagerAdapter() { @Override public Object instantiateItem(ViewGroup container, int position) { - if (DEBUG_DRAG) { + if (DEBUG_TILES) { Log.d(TAG, "instantiateItem() called with " + "container = [" + container + "], position = [" + position + "]"); } @@ -196,15 +207,10 @@ public Object instantiateItem(ViewGroup container, int position) { container.addView(qss, 0); return qss; } else { - QSPage page = new QSPage(container.getContext(), - QSDragPanel.this, mEditing ? position - 1 : position); - - container.addView(page); - int viewPos = page.getPageIndex(); - if (viewPos > mPages.size()) { - mPages.add(page); - } else { - mPages.add(viewPos, page); + final int adjustedPosition = mEditing ? position - 1 : position; + QSPage page = mPages.get(adjustedPosition); + if (!page.isAttachedToWindow()) { + container.addView(page); } return page; } @@ -212,15 +218,12 @@ public Object instantiateItem(ViewGroup container, int position) { @Override public void destroyItem(ViewGroup container, int position, Object object) { - if (DEBUG_DRAG) { + if (DEBUG_TILES) { Log.d(TAG, "destroyItem() called with " + "container = [" + container + "], position = [" + position + "], object = [" + object + "]"); } if (object instanceof View) { - if (object instanceof QSPage) { - mPages.remove(object); - } container.removeView((View) object); } } @@ -228,16 +231,34 @@ public void destroyItem(ViewGroup container, int position, Object object) { @Override public int getItemPosition(Object object) { if (object instanceof QSPage) { + if (mEditing != ((QSPage) object).getAdapterEditingState()) { + // position of item changes when we set change the editing mode, + // sync it and send the new position + ((QSPage) object).setAdapterEditingState(mEditing); + + // calculate new position + int indexOf = ((QSPage) object).getPageIndex(); + if (mEditing) return indexOf + 1; + else return indexOf; + + } else if (!mPages.contains(object) && !mDragging) { + // only return none if we aren't dragging (object may be removed from + // the records array temporarily and we might think we have less pages, + // we don't want to prematurely remove this page + return POSITION_NONE; + } else { - final int indexOf = ((QSPage) object).getPageIndex(); - if (mEditing) return indexOf + 1; - else return indexOf; + return POSITION_UNCHANGED; + } } else if (object instanceof QSSettings) { - - if (mEditing) return 0; - else return POSITION_NONE; - + if (((QSSettings) object).getAdapterEditingState() != mEditing) { + ((QSSettings) object).setAdapterEditingState(mEditing); + if (mEditing) return 0 /* locked at position 0 */; + else return POSITION_NONE; + } else { + return POSITION_UNCHANGED; + } } return super.getItemPosition(object); } @@ -246,6 +267,12 @@ public int getItemPosition(Object object) { public int getCount() { final int qsPages = Math.max(getCurrentMaxPageCount(), 1); + if (mPages != null && qsPages > mPages.size()) { + for(int i = mPages.size(); i < qsPages; i++) { + mPages.add(i, new QSPage(mViewPager.getContext(), QSDragPanel.this, i)); + } + } + if (mEditing) return qsPages + 1; return qsPages; } @@ -256,7 +283,6 @@ public boolean isViewFromObject(View view, Object object) { } }; mViewPager.setAdapter(mPagerAdapter); - mViewPager.setOffscreenPageLimit(INITIAL_OFFSCREEN_PAGE_LIMIT); mPageIndicator.setViewPager(mViewPager); mPageIndicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @@ -316,11 +342,18 @@ public void onPageScrollStateChanged(int state) { setClipChildren(false); mSettingsObserver = new SettingsObserver(new Handler()); + + mViewPager.setOnDragListener(QSDragPanel.this); + mQsPanelTop.setOnDragListener(QSDragPanel.this); + mPageIndicator.setOnDragListener(QSDragPanel.this); + setOnDragListener(QSDragPanel.this); + + mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER); } @Override public boolean hasOverlappingRendering() { - return mClipper.isAnimating() || mEditing; + return mClipper.isAnimating() || mEditing || !mCurrentlyAnimating.isEmpty(); } @Override @@ -334,8 +367,19 @@ public void setBrightnessMirror(BrightnessMirrorController c) { } protected void drawTile(TileRecord r, QSTile.State state) { - final int visibility = state.visible || mEditing ? VISIBLE : GONE; + if (mEditing) { + if ((r.tile instanceof CustomQSTile) + && (((CustomQSTile) r.tile).isUserRemoved() + || ((CustomQSTile) r.tile).getTile() == null)) { + // don't modify visibility state if removed, or not yet published + } else { + state.visible = true; + state.enabled = true; + } + } + final int visibility = state.visible ? VISIBLE : GONE; setTileVisibility(r.tileView, visibility); + setTileEnabled(r.tileView, state.enabled); r.tileView.onStateChanged(state); } @@ -347,6 +391,7 @@ public void setListening(boolean listening) { r.tile.setListening(mListening); } mFooter.setListening(mListening); + mQsPanelTop.setListening(mListening); if (mListening) { refreshAllTiles(); } @@ -363,33 +408,43 @@ public void setListening(boolean listening) { } } + private void persistRecords() { + // persist the new config. + List newTiles = new ArrayList<>(); + for (TileRecord record : mRecords) { + newTiles.add(mHost.getSpec(record.tile)); + } + mHost.setTiles(newTiles); + } + public void setEditing(boolean editing) { if (mEditing == editing) return; - mEditing = editing; + final boolean isOnSettings = isOnSettingsPage(); + mQsPanelTop.setEditing(editing, isOnSettings); if (!editing) { - // persist the new config. - List newTiles = new ArrayList<>(); - for (TileRecord record : mRecords) { - newTiles.add(mHost.getSpec(record.tile)); - } - mHost.setTiles(newTiles); + persistRecords(); refreshAllTiles(); - mQsPanelTop.animate().translationX(0).start(); + mQsPanelTop.setTranslationX(0); + if (isOnSettings) { + mViewPager.setCurrentItem(1, true); + } } + mEditing = editing; + mPagerAdapter.notifyDataSetChanged(); + + mPageIndicator.setEditing(editing); + mViewPager.setOffscreenPageLimit(mEditing ? getCurrentMaxPageCount() + 1 : 1); + mPagerAdapter.notifyDataSetChanged(); // clear the record state for (TileRecord record : mRecords) { setupRecord(record); drawTile(record, record.tile.getState()); } - mQsPanelTop.setEditing(editing); - mPageIndicator.setEditing(editing); - mPagerAdapter.notifyDataSetChanged(); - ensurePagerState(); requestLayout(); } @@ -400,6 +455,7 @@ protected void onStartDrag() { protected void onStopDrag() { mDraggingRecord.tileView.setAlpha(1f); + mLastDragRecord = mDraggingRecord; mDraggingRecord = null; mDragging = false; mRestored = false; @@ -408,9 +464,6 @@ protected void onStopDrag() { mLastRightShift = -1; mQsPanelTop.onStopDrag(); - - requestLayout(); - ensurePagerState(); } protected View getDropTarget() { @@ -426,16 +479,16 @@ public boolean isEditing() { } protected int getPagesForCount(int tileCount) { - tileCount -= getTilesPerPage(true); + if (tileCount == 0) { + return 1; + } + tileCount = Math.max(0, tileCount - getTilesPerPage(true)); // first page + rest of tiles return 1 + (int) Math.ceil(tileCount / (double) getTilesPerPage(false)); } protected int getCurrentMaxPageCount() { int initialSize = mRecords.size(); - if (mTempTiles != null) { - return getPagesForCount(initialSize + mTempTiles.size()); - } return getPagesForCount(initialSize); } @@ -445,86 +498,192 @@ protected void updateDetailText() { mDetailRemoveButton.setText(R.string.quick_settings_remove); } - /** - * @return returns the number of pages that has at least 1 visible tile - */ - protected int getVisibleTilePageCount() { - // if all tiles are invisible on the page, do not count it - int pages = 0; + public void setTiles(final Collection> tilesCollection) { + // we try to be as efficient as possible here because this can happen while the user + // is in edit mode, or maybe even while tiles are animating + // step 1: stop all animations + // step 2: remove tiles no longer to be used, cache ones that are still valid + // step 3: remove empty viewpager pages + // step 4: generate new tiles, re-add cached ones - int lastPage = -1; - boolean allTilesInvisible = true; + if (DEBUG_TILES) { + Log.i(TAG, "setTiles() called with tiles = [" + tilesCollection + "]"); + } + if (mLastDragRecord != null && mRecords.indexOf(mLastDragRecord) == -1) { + // the last removed record might be stored in mLastDragRecord if we just shifted + // re-add it to the list so we'll clean it up below + mRecords.add(mLastDragRecord); + mLastDragRecord = null; + } - for (TileRecord record : mRecords) { - DragTileRecord dr = (DragTileRecord) record; - if (dr.destinationPage != lastPage) { - if (!allTilesInvisible) { - pages++; + // step kinda-1 + if (mDraggingRecord != null) { + // dragging record might be animating back, force it to finished position + mDraggingRecord.tileView.animate().cancel(); + } + + int currentViewPagerPage = mViewPager.getCurrentItem(); + int removedPages = 0; + + Map, DragTileRecord> cachedRecords = new ArrayMap<>(); + ListIterator iterator = mRecords.listIterator(mRecords.size()); + + int recordsRemoved = 0; + // cleanup current records + while (iterator.hasPrevious()) { // mRecords + DragTileRecord dr = (DragTileRecord) iterator.previous(); + + // step 1 + dr.tileView.animate().cancel(); + + // step 2 + if (tilesCollection.contains(dr.tile)) { + if (DEBUG_TILES) { + Log.i(TAG, "caching tile: " + dr.tile); } - lastPage = dr.destinationPage; - allTilesInvisible = true; - } - if (allTilesInvisible && dr.tile.getState().visible) { - allTilesInvisible = false; + cachedRecords.put(dr.tile, dr); + } else { + if (dr.page >= 0) { + if (DEBUG_TILES) { + Log.w(TAG, "removed dr.tileView: " + dr.tileView + " from page: " + + dr.page + " (dest page: " + dr.destinationPage + ")"); + } + + removeTileView(dr.tileView); + } + if (DEBUG_TILES) { + Log.i(TAG, "removing tile: " + dr.tile); + } + + // remove record + iterator.remove(); + recordsRemoved++; + + dr.page = -1; + dr.destinationPage = -1; } } - // last tile may have set this - if (!allTilesInvisible) { - pages++; + + // at this point cachedRecords should have all retained tiles, no new or old tiles + int delta = tilesCollection.size() - cachedRecords.size() - recordsRemoved; + if (DEBUG_TILES) { + Log.i(TAG, "record map delta: " + delta); } - return pages; - } - public void setTiles(Collection> tiles) { - if (DEBUG_DRAG) { - Log.i(TAG, "setTiles() called with " + "tiles = [" - + tiles + "], mTempTiles: " + mTempTiles); - if (mTempTiles != null) { - Log.e(TAG, "temp tiles being overridden... : " + - Arrays.toString(mTempTiles.toArray())); + // step 3 + final Iterator pageIterator = mPages.iterator(); + while (pageIterator.hasNext()) { + final QSPage page = pageIterator.next(); + final int viewpagerIndex = page.getPageIndex() + (mEditing ? 1 : 0); + final int childCount = page.getChildCount(); + + if (DEBUG_TILES) { + Log.d(TAG, "page " + viewpagerIndex + " has " + childCount); + } + if (page.getPageIndex() >= getCurrentMaxPageCount() - 1) { + if (DEBUG_TILES) { + Log.d(TAG, "page : " + page + " has " + childCount + " children"); + } + if (childCount == 0) { + removedPages++; + + page.removeAllViews(); + mPagerAdapter.startUpdate(mViewPager); + mPagerAdapter.destroyItem(mViewPager, viewpagerIndex, page); + mPagerAdapter.finishUpdate(mViewPager); + mPagerAdapter.notifyDataSetChanged(); + } } } - for (Record record : mRecords) { - if (record instanceof DragTileRecord) { - DragTileRecord dr = (DragTileRecord) record; - mPages.get(dr.page).removeView(dr.tileView); + + if (removedPages > 0) { + // even though we explicitly destroy old pages, without this call, + // the viewpager doesn't seem to want to pick up the fact that we have less pages + // and allows "empty" scrolls to the right where there is no page. + if (DEBUG_TILES) { + Log.d(TAG, "re-setting adapter, page: " + currentViewPagerPage); } + mViewPager.setAdapter(mPagerAdapter); + mViewPager.setCurrentItem(Math.min(currentViewPagerPage, mPagerAdapter.getCount()), + false); + mPagerAdapter.notifyDataSetChanged(); } - mRecords.clear(); - if (isLaidOut()) { - for (QSTile tile : tiles) { - addTile(tile); + + // step 4 + mRecords.ensureCapacity(tilesCollection.size()); + int runningCount = 0; + + final Iterator> newTileIterator = tilesCollection.iterator(); + while (newTileIterator.hasNext()) { + QSTile tile = newTileIterator.next(); + if (tile instanceof CustomQSTile) { + if (((CustomQSTile) tile).isUserRemoved() + || ((CustomQSTile) tile).getTile() == null) { + // tile not published yet + continue; + } } - if (isShowingDetail()) { - mDetail.bringToFront(); + final int tileDestPage = getPagesForCount(runningCount + 1) - 1; + + if (DEBUG_TILES) { + Log.d(TAG, "tile at : " + runningCount + ": " + tile + + " to dest page: " + tileDestPage); } - } else if (!isLaidOut()) { - if (DEBUG_DRAG) { - Log.w(TAG, "setting temporary tiles to layout"); + DragTileRecord record; + if (!cachedRecords.containsKey(tile)) { + if (DEBUG_TILES) { + Log.d(TAG, "tile at: " + runningCount + " not cached, adding it to records"); + } + record = makeRecord(tile); + record.destinationPage = tileDestPage; + mRecords.add(runningCount, record); + mPagerAdapter.notifyDataSetChanged(); + } else { + record = cachedRecords.get(tile); + if (DEBUG_TILES) { + Log.d(TAG, "tile at : " + runningCount + ": cached, restoring: " + record); + } + + mPages.get(record.page).removeView(record.tileView); + + record.page = -1; + record.destinationPage = tileDestPage; + + mRecords.remove(record); + mRecords.add(runningCount, record); + mPagerAdapter.notifyDataSetChanged(); + } + if (record.page == -1) { + // add the view + mPages.get(record.destinationPage).addView(record.tileView); + record.page = record.destinationPage; + if (DEBUG_TILES) { + Log.d(TAG, "added view " + record); + } } - mTempTiles = Collections.synchronizedCollection(new ArrayList>(tiles)); + runningCount++; + } + + if (isShowingDetail()) { + mDetail.bringToFront(); } mPagerAdapter.notifyDataSetChanged(); + + refreshAllTiles(); requestLayout(); - ensurePagerState(); } - protected void addTile(final QSTile tile) { - if (DEBUG_DRAG) { - Log.d(TAG, "+++ addTile() called with " + "tile = [" + tile + "]"); + private DragTileRecord makeRecord(final QSTile tile) { + if (DEBUG_TILES) { + Log.d(TAG, "+++ makeRecord() called with " + "tile = [" + tile + "]"); } final DragTileRecord r = new DragTileRecord(); - mRecords.add(r); - mPagerAdapter.notifyDataSetChanged(); - - int potentialPageIdx = getPagesForCount(mRecords.size()) - 1; r.tile = tile; - r.page = potentialPageIdx; - r.destinationPage = r.page; + r.page = -1; + r.destinationPage = -1; r.tileView = tile.createTileView(mContext); - r.tileView.setVisibility(View.GONE); final QSTile.Callback callback = new QSTile.Callback() { @Override public void onStateChanged(QSTile.State state) { @@ -589,30 +748,35 @@ public boolean onLongClick(View v) { r.tileView.init(click, clickSecondary, longClick); r.tile.setListening(mListening); r.tile.refreshState(); - if (mEditing) { - // force it to be visible, we'll refresh its state once editing is done - r.tile.getState().visible = true; - } + r.tileView.setVisibility(mEditing ? View.VISIBLE : View.GONE); callback.onStateChanged(r.tile.getState()); - mPages.get(r.page).addView(r.tileView); - - ensurePagerState(); + if (DEBUG_TILES) { + Log.d(TAG, "--- makeRecord() called with " + "tile = [" + tile + "]"); + } + return r; + } - if (DEBUG_DRAG) { - Log.d(TAG, "--- addTile() called with " + "tile = [" + tile + "]"); + private void removeTileView(QSTileView v) { + for (QSPage page : mPages) { + page.removeView(v); + page.removeTransientView(v); } + } - public void ensurePagerState() { - if (!isShowingDetail()) { - final boolean pagingEnabled = getVisibleTilePageCount() > 1 || mDragging || mEditing; - mViewPager.setPagingEnabled(pagingEnabled); + private void removeDraggingRecord() { + // what spec is this tile? + String spec = mHost.getSpec(mDraggingRecord.tile); + if (DEBUG_TILES) { + Log.w(TAG, "removing tile: " + mDraggingRecord + " with spec: " + spec); } + onStopDrag(); + mHost.remove(spec); } public int getTilesPerPage(boolean firstPage) { - if ((!mFirstRowLarge && firstPage)|| !firstPage) { + if ((!mFirstRowLarge && firstPage) || !firstPage) { return QSTileHost.TILES_PER_PAGE + 1; } return QSTileHost.TILES_PER_PAGE; @@ -622,26 +786,28 @@ public int getTilesPerPage(boolean firstPage) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); - if (isLaidOut()) { - mQsPanelTop.measure(exactly(width), MeasureSpec.UNSPECIFIED); - } + mQsPanelTop.measure(exactly(width), MeasureSpec.UNSPECIFIED); mViewPager.measure(exactly(width), MeasureSpec.UNSPECIFIED); - mPageIndicator.measure(exactly(width), MeasureSpec.UNSPECIFIED); + mPageIndicator.measure(exactly(width), atMost(mPageIndicatorHeight)); mFooter.getView().measure(exactly(width), MeasureSpec.UNSPECIFIED); - int h = mBrightnessPaddingTop - + mViewPager.getMeasuredHeight() - + mPageIndicator.getMeasuredHeight(); + int h = getRowTop(getCurrentMaxRow() + 1) + mPanelPaddingBottom; + if (mFooter.hasFooter()) { h += mFooter.getView().getMeasuredHeight(); } + mGridHeight = h; + mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED); + if (mDetail.getMeasuredHeight() < h) { mDetail.measure(exactly(width), exactly(h)); } - mGridHeight = h; - setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight())); + if (isShowingDetail() && !isClosingDetail() && mExpanded) { + h = mDetail.getMeasuredHeight(); + } + setMeasuredDimension(width, h); for (TileRecord record : mRecords) { setupRecord(record); } @@ -656,6 +822,10 @@ public static int exactly(int size) { return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); } + public static int atMost(int size) { + return MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST); + } + @Override protected void handleShowDetailTile(TileRecord r, boolean show) { if (r instanceof DragTileRecord) { @@ -667,27 +837,26 @@ protected void handleShowDetailTile(TileRecord r, boolean show) { } r.tile.setDetailListening(show); int x = (int) ((DragTileRecord) r).destination.x + r.tileView.getWidth() / 2; - int y = mViewPager.getTop() + (int) ((DragTileRecord) r).destination.y + r.tileView.getHeight() / 2; + int y = mViewPager.getTop() + + (int) ((DragTileRecord) r).destination.y + r.tileView.getHeight() / 2; handleShowDetailImpl(r, show, x, y); } else { super.handleShowDetailTile(r, show); } + mPageIndicator.setVisibility(!show ? View.VISIBLE : View.INVISIBLE); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int w = getWidth(); - int top = mBrightnessPaddingTop; + mQsPanelTop.layout(0, 0, w, mQsPanelTop.getMeasuredHeight()); - mViewPager.layout(0, top, w, top + mViewPager.getMeasuredHeight()); - top += mViewPager.getMeasuredHeight(); + int viewPagerBottom = mQsPanelTop.getMeasuredHeight() + mViewPager.getMeasuredHeight(); + // view pager laid out from top of brightness view to bottom to page through settings + mViewPager.layout(0, 0, w, viewPagerBottom); - // layout page indicator below view pager - mPageIndicator.layout(0, top, w, top + mPageIndicator.getMeasuredHeight()); - - // detail takes up whole height - mDetail.layout(0, 0, mDetail.getMeasuredWidth(), getMeasuredHeight()); + mDetail.layout(0, 0, w, mDetail.getMeasuredHeight()); if (mFooter.hasFooter()) { View footer = mFooter.getView(); @@ -695,20 +864,16 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { footer.getMeasuredWidth(), getMeasuredHeight()); } - if (mTempTiles != null) { - final Iterator> iterator = mTempTiles.iterator(); - while (iterator.hasNext()) { - addTile(iterator.next()); - iterator.remove(); - } - mTempTiles = null; - mPagerAdapter.notifyDataSetChanged(); + if (!isShowingDetail() && !isClosingDetail()) { + mQsPanelTop.bringToFront(); + } - ensurePagerState(); + // layout page indicator inside viewpager inset + mPageIndicator.layout(0, b - mPageIndicatorHeight, w, b); } protected int getRowTop(int row) { - int baseHeight = mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop; + int baseHeight = mQsPanelTop.getMeasuredHeight(); if (row <= 0) return baseHeight; return baseHeight + mLargeCellHeight - mDualTileUnderlap + (row - 1) * mCellHeight; } @@ -717,7 +882,7 @@ public int getColumnCount() { return mColumns; } - public int getColumnCount(int page, int row) { + public int getColumnCount(int page, int row, boolean smart) { int cols = 0; for (Record record : mRecords) { if (record instanceof DragTileRecord) { @@ -728,24 +893,30 @@ public int getColumnCount(int page, int row) { } } - if (isEditing() && (isDragging() || mRestoring) && !isDragRecordAttached()) { + if (smart && isEditing() && (isDragging() || mRestoring) && !isDragRecordAttached()) { // if shifting tiles back, and one moved from previous page // if it's the very last row on the last page, we should add an extra column to account - // for where teh dragging record would go - DragTileRecord record = (DragTileRecord) mRecords.get(mRecords.size() - 1); - - if (record.destinationPage == page && record.row == row && cols < getColumnCount()) { + // for where teh dragging lastRecord would go + DragTileRecord lastRecord = (DragTileRecord) mRecords.get(mRecords.size() - 1); + if (lastRecord.destinationPage == page && lastRecord.row == row + && cols < getColumnCount()) { cols++; if (DEBUG_DRAG) { - Log.w(TAG, "adding another col, cols: " + cols + ", last: " + record - + ", drag: " + mDraggingRecord + ", "); + boolean draggingRecordBefore = isBefore(mDraggingRecord, lastRecord); + Log.w(TAG, "adding another col, cols: " + cols + ", last: " + lastRecord + + ", drag: " + mDraggingRecord + + ", and dragging record before last: " + draggingRecordBefore); } } } return cols; } + public int getColumnCount(int page, int row) { + return getColumnCount(page, row, true); + } + public int getCurrentMaxRow() { int max = 0; for (TileRecord record : mRecords) { @@ -803,21 +974,45 @@ public boolean onDrag(View v, DragEvent event) { boolean dragRecordAttached = dragRecordIndex != -1; switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: + if (DEBUG_DRAG) { + Log.v(TAG, "ACTION_DRAG_STARTED on view: " + v); + } + if (originatingTileEvent) { if (DEBUG_DRAG) { Log.v(TAG, "ACTION_DRAG_STARTED on target view."); } mRestored = false; + mQsPanelTop.setDropIcon(R.drawable.ic_qs_tile_delete_disable, R.color.qs_tile_trash_normal_tint); } - return true; + + break; case DragEvent.ACTION_DRAG_ENTERED: if (DEBUG_DRAG) { - Log.v(TAG, "ACTION_DRAG_ENTERED on view with tile: " + targetTile); + if (targetTile != null) { + Log.v(TAG, "ACTION_DRAG_ENTERED on view with tile: " + targetTile); + } else { + Log.v(TAG, "ACTION_DRAG_ENTERED on view: " + v); + } } mLocationHits = 0; mMovedByLocation = false; + if (v == mQsPanelTop) { + int icon, color; + if (mDraggingRecord.tile instanceof EditTile) { + // use a different warning, user can't erase this one + icon = R.drawable.ic_qs_tile_delete_disable_avd; + color = R.color.qs_tile_trash_delete_tint_warning; + } else { + icon = R.drawable.ic_qs_tile_delete_disable; + color = R.color.qs_tile_trash_delete_tint; + } + + mQsPanelTop.setDropIcon(icon, color); + } + if (!originatingTileEvent && v != getDropTarget() && targetTile != null) { if (DEBUG_DRAG) { Log.e(TAG, "entered tile " + targetTile); @@ -834,7 +1029,7 @@ public boolean onDrag(View v, DragEvent event) { } } - return true; + break; case DragEvent.ACTION_DRAG_ENDED: if (DEBUG_DRAG) { Log.v(TAG, "ACTION_DRAG_ENDED on view: " + v + "(tile: " @@ -842,10 +1037,10 @@ public boolean onDrag(View v, DragEvent event) { } if (originatingTileEvent && !event.getResult()) { // view pager probably ate the event - restoreDraggingTilePosition(v); + restoreDraggingTilePosition(v, null); } - return true; + break; case DragEvent.ACTION_DROP: if (DEBUG_DRAG) { @@ -860,25 +1055,40 @@ public boolean onDrag(View v, DragEvent event) { Log.d(TAG, "dropping on delete target!!"); } if (mDraggingRecord.tile instanceof EditTile) { + final QSTileView editTileView = mDraggingRecord.tileView; + mQsPanelTop.toast(R.string.quick_settings_cannot_delete_edit_tile); - restoreDraggingTilePosition(v); - return true; + restoreDraggingTilePosition(v, new Runnable() { + @Override + public void run() { + // move edit tile to the back + final TileRecord editTile = getRecord(editTileView); + if (mRecords.remove(editTile)) { + // we depend on mHost.setTiles() placing it on the end + persistRecords(); + } + } + }); + break; + } else if (mDraggingRecord.tile instanceof CustomQSTile) { + ((CustomQSTile) mDraggingRecord.tile).setUserRemoved(true); + final String spec = mHost.getSpec(mDraggingRecord.tile); + restoreDraggingTilePosition(v, new Runnable() { + @Override + public void run() { + // it might get added back later by the app, but that's ok, + // we just want to reset its position after it has been removed. + mHost.remove(spec); + } + }); } else { mRestored = true; - getPage(mDraggingRecord.page).removeView(mDraggingRecord.tileView); - - // what spec is this tile? - String spec = mHost.getSpec(mDraggingRecord.tile); - if (DEBUG_DRAG) { - Log.w(TAG, "removing tile: " + mDraggingRecord + " with spec: " + spec); - } - mHost.remove(spec); - onStopDrag(); + removeDraggingRecord(); } } else { - restoreDraggingTilePosition(v); + restoreDraggingTilePosition(v, null); } - return true; + break; case DragEvent.ACTION_DRAG_EXITED: if (DEBUG_DRAG) { @@ -888,6 +1098,11 @@ public boolean onDrag(View v, DragEvent event) { Log.v(TAG, "ACTION_DRAG_EXITED on view: " + v); } } + + if (v == mQsPanelTop) { + mQsPanelTop.setDropIcon(R.drawable.ic_qs_tile_delete_disable, R.color.qs_tile_trash_normal_tint); + } + if (originatingTileEvent && mCurrentlyAnimating.isEmpty() && !mViewPager.isFakeDragging() @@ -903,7 +1118,7 @@ public boolean onDrag(View v, DragEvent event) { // move tiles back shiftTiles(mDraggingRecord, false); - return true; + break; } // fall through so exit events can trigger a left shift case DragEvent.ACTION_DRAG_LOCATION: @@ -965,17 +1180,20 @@ public boolean onDrag(View v, DragEvent event) { shiftTiles((DragTileRecord) mRecords.get(mLastRightShift), false); mMovedByLocation = true; } + } else { if (DEBUG_DRAG) { Log.i(TAG, "ignoring location event because things are animating, size: " + mCurrentlyAnimating.size()); } } - return true; + break; + default: Log.w(TAG, "unhandled event"); + return false; } - return false; + return true; } private boolean isDropTargetEvent(DragEvent event, View v) { @@ -999,7 +1217,7 @@ private boolean isDropTargetEvent(DragEvent event, View v) { return false; } - private void restoreDraggingTilePosition(View v) { + private void restoreDraggingTilePosition(View v, final Runnable onAnimationFinishedRunnable) { if (mRestored) { return; } @@ -1050,9 +1268,18 @@ private void restoreDraggingTilePosition(View v) { // setup x destination to animate to float destinationX = mDraggingRecord.destination.x; - if (mDraggingRecord.destinationPage + 1 > mViewPager.getCurrentItem()) { + + // see if we should animate this to the left or right off the page + // the +1's are to account for the edit page + if (mDraggingRecord.destinationPage > mViewPager.getCurrentItem() - 1) { + if (DEBUG_DRAG) { + Log.d(TAG, "adding width to animate out >>>>>"); + } destinationX += getWidth(); - } else if (mDraggingRecord.destinationPage + 1 < mViewPager.getCurrentItem()) { + } else if (mDraggingRecord.destinationPage < mViewPager.getCurrentItem() - 1) { + if (DEBUG_DRAG) { + Log.d(TAG, "removing width to animate out <<<<<"); + } destinationX -= getWidth(); } @@ -1060,6 +1287,7 @@ private void restoreDraggingTilePosition(View v) { float destinationY = mDraggingRecord.destination.y + mViewPager.getTop(); mDraggingRecord.tileView.animate() + .withLayer() .x(destinationX) .y(destinationY) // part of the viewpager now .setListener(new AnimatorListenerAdapter() { @@ -1068,6 +1296,20 @@ public void onAnimationStart(Animator animation) { mDraggingRecord.tileView.setAlpha(1); } + @Override + public void onAnimationCancel(Animator animation) { + mViewPager.requestDisallowInterceptTouchEvent(false); + removeTransientView(mDraggingRecord.tileView); + mCurrentlyAnimating.remove(mDraggingRecord); + mRestoring = false; + mPagerAdapter.notifyDataSetChanged(); + onStopDrag(); + + if (onAnimationFinishedRunnable != null) { + postOnAnimation(onAnimationFinishedRunnable); + } + } + @Override public void onAnimationEnd(Animator animation) { mViewPager.requestDisallowInterceptTouchEvent(false); @@ -1076,14 +1318,15 @@ public void onAnimationEnd(Animator animation) { final QSPage targetP = getPage(mDraggingRecord.destinationPage); - if (dragRecordDetached) { - Log.i(TAG, "drag record was detached"); - - } else { - Log.i(TAG, "drag record was attached"); + if (DEBUG_DRAG) { + if (dragRecordDetached) { + Log.i(TAG, "drag record was detached"); + } else { + Log.i(TAG, "drag record was attached"); + } } - mDraggingRecord.page = mDraggingRecord.destinationPage; targetP.addView(mDraggingRecord.tileView); + mDraggingRecord.page = mDraggingRecord.destinationPage; mDraggingRecord.tileView.setX(mDraggingRecord.destination.x); // reset this to be in the coords of the page, not viewpager anymore @@ -1098,6 +1341,12 @@ public void onAnimationEnd(Animator animation) { mPagerAdapter.notifyDataSetChanged(); } onStopDrag(); + + if (onAnimationFinishedRunnable != null) { + postOnAnimation(onAnimationFinishedRunnable); + } else { + requestLayout(); + } } }); } @@ -1130,18 +1379,15 @@ private void setToNextDestination(DragTileRecord tile) { Log.w(TAG, "tile's destination page moved to: " + tile.destinationPage); } } - int columnCount = Math.max(1, getColumnCount(tile.destinationPage, tile.row)); + int columnCount = Math.max(1, getColumnCount(tile.destinationPage, tile.row, false)); + if (columnCount < maxCols) { + // if columncount gives us 1 and we're at col 2 + columnCount = Math.max((tile.col + 1), columnCount); + } if (DEBUG_DRAG) { - Log.w(TAG, "columCount initially at: " + columnCount); + Log.w(TAG, "columCount at: " + columnCount); } - if (!mRecords.contains(tile) && tile != mDraggingRecord) { - // increase column count for the destination location to account for this tile being added - columnCount++; - if (DEBUG_DRAG) { - Log.w(TAG, "column count adjusted to: " + columnCount); - } - } boolean firstRowLarge = mFirstRowLarge && tile.row == 0 && tile.destinationPage == 0; tile.destination.x = getLeft(tile.row, tile.col, columnCount, firstRowLarge); @@ -1153,11 +1399,34 @@ private void setToNextDestination(DragTileRecord tile) { } } + private boolean isBefore(DragTileRecord r1, DragTileRecord r2) { + if (DEBUG_DRAG) { + Log.d(TAG, "isBefore() called with " + "r1 = [" + r1 + "], r2 = [" + r2 + "]"); + } + boolean isBefore = r1.destinationPage <= r2.destinationPage; + if (r1.destinationPage == r2.destinationPage) { + isBefore = r1.row <= r2.row; + if (r1.row == r2.row) { + isBefore = r1.col <= r2.col; + } + } + + if (DEBUG_DRAG) { + Log.d(TAG, "r1 isBefore r2: " + isBefore); + } + return isBefore; + } + private void setToLastDestination(DragTileRecord record) { DragTileRecord last = (DragTileRecord) mRecords.get(mRecords.size() - 1); - Log.d(TAG, "setToLastDestination() called with record = [" - + record + "], and last record is: " + last); - if (record != last && record.destinationPage <= last.destinationPage) { + if (DEBUG_DRAG) { + Log.d(TAG, "setToLastDestination() called with record = [" + + record + "], and last record is: " + last); + } + + if (isBefore(record, last)) { + // if the record is before the last record in the records list, set it to the + // last location, then spoof it one space forward record.destinationPage = last.destinationPage; record.row = last.row; record.col = last.col; @@ -1289,18 +1558,21 @@ private void shiftAllTilesRight(int startingIndex) { tilePageSource.addTransientView(ti.tileView, 0); ti.tileView.animate() + .withLayer() .x(ti.destination.x + getWidth()) .y(ti.destination.y) .setListener(new AnimatorListenerAdapter() { @Override - public void onAnimationStart(Animator animation) { + public void onAnimationCancel(Animator animation) { + tilePageSource.removeTransientView(ti.tileView); + mCurrentlyAnimating.remove(ti); } @Override public void onAnimationEnd(Animator animation) { tilePageSource.removeTransientView(ti.tileView); - ti.page = tilePageTarget.getPageIndex(); tilePageTarget.addView(ti.tileView); + ti.page = tilePageTarget.getPageIndex(); ti.tileView.setX(ti.destination.x); ti.tileView.setY(ti.destination.y); @@ -1311,12 +1583,26 @@ public void onAnimationEnd(Animator animation) { } else { ti.tileView.animate() + .withLayer() .x(ti.destination.x) .y(ti.destination.y) .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + mCurrentlyAnimating.remove(ti); + } + @Override public void onAnimationEnd(Animator animation) { mCurrentlyAnimating.remove(ti); + final boolean dual = getPage(ti.destinationPage).dualRecord(ti); + if (ti.tileView.setDual(dual, ti.tile.hasDualTargetsDetails())) { + if (DEBUG_DRAG) { + Log.w(TAG, ti + " changed dual state to : " + + ti.tileView.isDual()); + } + } + requestLayout(); } }); } @@ -1337,14 +1623,21 @@ public void onAnimationEnd(Animator animation) { tilePageSource.addTransientView(last.tileView, 0); last.tileView.animate() + .withLayer() .x(last.destination.x + getWidth()) .y(last.destination.y) .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + tilePageSource.removeTransientView(last.tileView); + mCurrentlyAnimating.remove(last); + } + @Override public void onAnimationEnd(Animator animation) { tilePageSource.removeTransientView(last.tileView); - last.page = tilePageTarget.getPageIndex(); tilePageTarget.addView(last.tileView); + last.page = tilePageTarget.getPageIndex(); last.tileView.setX(last.destination.x); last.tileView.setY(last.destination.y); @@ -1358,9 +1651,15 @@ public void onAnimationEnd(Animator animation) { }); } else { last.tileView.animate() + .withLayer() .x(last.destination.x) .y(last.destination.y) .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + mCurrentlyAnimating.remove(last); + } + @Override public void onAnimationEnd(Animator animation) { if (DEBUG_DRAG) { @@ -1368,6 +1667,7 @@ public void onAnimationEnd(Animator animation) { } mCurrentlyAnimating.remove(last); + requestLayout(); } }); } @@ -1398,7 +1698,9 @@ private void shiftAllTilesLeft(int startingIndex) { if (ti.row != lastRow) { desiredColCount = getColumnCount(ti.destinationPage, ti.row); - Log.e(TAG, "updating desired colum count to: " + desiredColCount); + if (DEBUG_DRAG) { + Log.e(TAG, "updating desired colum count to: " + desiredColCount); + } } // save current tile's loc @@ -1413,7 +1715,7 @@ private void shiftAllTilesLeft(int startingIndex) { ti.col = lastCol; ti.destination.x = getLeft(lastRow, lastCol, columnCountF, - lastPage == 0 && lastRow == 0); + lastPage == 0 && lastRow == 0 && mFirstRowLarge); ti.destination.y = getRowTop(lastRow); final boolean dual = getPage(ti.destinationPage).dualRecord(ti); @@ -1430,6 +1732,7 @@ private void shiftAllTilesLeft(int startingIndex) { originalPage.removeView(ti.tileView); ti.tileView.animate() + .withLayer() .x(ti.destination.x) .y(ti.destination.y) .setListener(new AnimatorListenerAdapter() { @@ -1438,11 +1741,17 @@ public void onAnimationStart(Animator animation) { page.addTransientView(ti.tileView, 0); } + @Override + public void onAnimationCancel(Animator animation) { + page.removeTransientView(ti.tileView); + mCurrentlyAnimating.remove(ti); + } + @Override public void onAnimationEnd(Animator animation) { page.removeTransientView(ti.tileView); - ti.page = page.getPageIndex(); page.addView(ti.tileView); + ti.page = page.getPageIndex(); mCurrentlyAnimating.remove(ti); requestLayout(); @@ -1450,21 +1759,19 @@ public void onAnimationEnd(Animator animation) { }); } else { ti.tileView.animate() + .withLayer() .x(ti.destination.x) .y(ti.destination.y) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { + mCurrentlyAnimating.remove(ti); if (ti.tileView.setDual(dual, ti.tile.hasDualTargetsDetails())) { if (DEBUG_DRAG) { Log.w(TAG, ti + " changed dual state to : " + ti.tileView.isDual()); } - ti.tileView.handleStateChanged(ti.tile.getState()); - ti.tileView.invalidate(); } - - mCurrentlyAnimating.remove(ti); requestLayout(); } }); @@ -1492,33 +1799,35 @@ protected void handleShowDetailImpl(Record r, boolean show, int x, int y) { mDetailRemoveButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mHost.collapsePanels(); mHost.removeCustomTile(customTile); + closeDetail(); } }); } - } - - public int getDesiredColumnCount(int page, int row) { - if (page == 0 && row == 0) { - return 2; // TODO change if large tiles are disabled - } else { - return mColumns; - } + mPanelView.setDetailRequestedScrollLock(mExpanded && show + && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE); } @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); FontSizeUtils.updateFontSize(mDetailRemoveButton, R.dimen.qs_detail_button_text_size); + mPanelView.setDetailRequestedScrollLock(mExpanded && isShowingDetail() + && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE); } @Override public void setExpanded(boolean expanded) { super.setExpanded(expanded); + // reset the page when inactive for a while + if (expanded) { + removeCallbacks(mResetPage); + } else { + postDelayed(mResetPage, PAGE_RESET_DELAY); + } if (!expanded) { if (mEditing) { - setEditing(false); + mHost.setEditing(false); } } } @@ -1533,18 +1842,20 @@ public void updateResources() { mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom); mDualTileUnderlap = res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical); mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top); + mPageIndicatorHeight = res.getDimensionPixelSize(R.dimen.qs_panel_page_indicator_height); + if (mColumns != columns) { + mColumns = columns; + if (isLaidOut()) postInvalidate(); + } if (isLaidOut()) { - if (mColumns != columns) { - mColumns = columns; - postInvalidate(); - } for (TileRecord r : mRecords) { r.tile.clearState(); } + updateDetailText(); + mQsPanelTop.updateResources(); if (mListening) { refreshAllTiles(); } - updateDetailText(); } } @@ -1552,74 +1863,375 @@ public boolean isAnimating(TileRecord t) { return mCurrentlyAnimating.contains(t); } - // todo implement proper add tile ui - protected void showAddDialog() { - List currentTileSpec = mHost.getTileSpecs(); - final List availableTilesSpec = QSUtils.getAvailableTiles(getContext()); + public void cleanup() { + if (mSettingsObserver != null) { + mSettingsObserver.unobserve(); + } + } + + public void setPanelView(NotificationPanelView panelView) { + this.mPanelView = panelView; + } + + public static class TilesListAdapter extends BaseExpandableListAdapter + implements QSTile.DetailAdapter { + + public static final String PACKAGE_ANDROID = "android"; + + Context mContext; + QSTileHost mHost; + QSDragPanel mPanel; + + ArrayMap> mPackageTileMap = new ArrayMap<>(); + + public TilesListAdapter(Context context, QSDragPanel panel) { + mContext = context; + mHost = panel.getHost(); + mPanel = panel; + + List currentTileSpec = mHost.getTileSpecs(); + final Collection tiles = QSUtils.getAvailableTiles(mContext); + tiles.removeAll(currentTileSpec); + + // we'll always have a system tiles category + mPackageTileMap.put(PACKAGE_ANDROID, new ArrayList()); + + final Iterator i = tiles.iterator(); + while (i.hasNext()) { + final String spec = i.next(); + if (QSUtils.isStaticQsTile(spec) + || QSUtils.isDynamicQsTile(extractTileTagFromSpec(spec))) { + List packageList = mPackageTileMap.get(PACKAGE_ANDROID); + packageList.add(spec); + } else { + String tilePackage = getCustomTilePackage(spec); + List packageList = mPackageTileMap.get(tilePackage); + if (packageList == null) { + mPackageTileMap.put(tilePackage, packageList = new ArrayList<>()); + } + packageList.add(spec); + } + } + + final Map stringMap = CustomQSTile.getCustomQSTilePrefs(mContext).getAll(); + for (Map.Entry entry : stringMap.entrySet()) { + if (entry.getValue() instanceof Boolean) { + if ((Boolean)entry.getValue()) { + final String key = entry.getKey(); + if (QSUtils.isDynamicQsTile(extractTileTagFromSpec(key))) { + mPackageTileMap.get(PACKAGE_ANDROID).add(key); + } else { + final String customTilePackage = getCustomTilePackage(key); + List packageList = mPackageTileMap.get(customTilePackage); + if (packageList == null) { + mPackageTileMap.put(customTilePackage, + packageList = new ArrayList<>()); + } + packageList.add(key); - // Remove tiles already used - availableTilesSpec.removeAll(currentTileSpec); + } + } + } + }; + + final List systemTiles = mPackageTileMap.get(PACKAGE_ANDROID); + Collections.sort(systemTiles); + } - // Populate labels - List availableTilesLabel = new ArrayList(); - for (String tileSpec : availableTilesSpec) { - int resource = QSTileHost.getLabelResource(tileSpec); - if (resource != 0) { - availableTilesLabel.add(getContext().getString(resource)); + private String getCustomTilePackage(String spec) { + if (mHost.getCustomTileData().get(spec) != null) { + StatusBarPanelCustomTile sbc = mHost.getCustomTileData().get(spec).sbc; + return sbc.getPackage(); } else { - availableTilesLabel.add(tileSpec); + return extractPackageFromCustomTileSpec(spec); } } - // Add broadcast tile - availableTilesLabel.add(getContext().getString(R.string.broadcast_tile)); - availableTilesSpec.add(BROADCAST_TILE_SPEC_PLACEHOLDER); + private static String extractPackageFromCustomTileSpec(String spec) { + if (spec != null && !spec.isEmpty()) { + final String[] split = spec.split("\\|"); + if (split != null && split.length > 2) { + return split[1]; + } + return spec; + } + return null; + } - String[] items = new String[availableTilesLabel.size()]; - availableTilesLabel.toArray(items); + private static String extractTileTagFromSpec(String spec) { + if (spec != null && !spec.isEmpty()) { + final String[] split = spec.split("\\|"); + if (split != null && split.length == 5) { + /** for {@link cyanogenmod.app.StatusBarPanelCustomTile#key() **/ + return split[3]; + } else if (split != null && split.length == 3) { + /** for {@link cyanogenmod.app.StatusBarPanelCustomTile#persistableKey()} **/ + return split[2]; + } + return spec; + } + return null; + } - final AlertDialog d = new AlertDialog.Builder(getContext(), R.style.Theme_SystemUI_Dialog) - .setTitle(R.string.add_tile) - .setItems(items, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String tileSpec = availableTilesSpec.get(which); - if (tileSpec.equals(BROADCAST_TILE_SPEC_PLACEHOLDER)) { - showBroadcastTileDialog(); - } else { - add(tileSpec); - } + private Drawable getQSTileIcon(String spec) { + if (QSUtils.isDynamicQsTile(extractTileTagFromSpec(spec))) { + return QSTile.ResourceIcon.get(QSUtils.getDynamicQSTileResIconId(mContext, + UserHandle.myUserId(), extractTileTagFromSpec(spec))).getDrawable(mContext); + } else if (QSUtils.isStaticQsTile(spec)) { + final int res = QSTileHost.getIconResource(spec); + if (res != 0) { + return QSTile.ResourceIcon.get(res).getDrawable(mContext); + } else { + return mContext.getPackageManager().getDefaultActivityIcon(); + } + } else { + QSTile tile = mHost.getTile(spec); + if (tile != null) { + QSTile.State state = tile.getState(); + if (state != null && state.icon != null) { + return state.icon.getDrawable(mContext); } - }).create(); - SystemUIDialog.makeSystemUIDialog(d); - d.show(); - } - - public void showBroadcastTileDialog() { - final EditText editText = new EditText(getContext()); - final AlertDialog d = new AlertDialog.Builder(getContext()) - .setTitle(R.string.broadcast_tile) - .setView(editText) - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String action = editText.getText().toString(); - if (isValid(action)) { - add(IntentTile.PREFIX + action + ')'); - } + } + return getPackageDrawable(getCustomTilePackage(spec)); + } + } + + private String getPackageLabel(String packageName) { + try { + return mContext.getPackageManager().getApplicationLabel( + mContext.getPackageManager().getApplicationInfo(packageName, 0)).toString(); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + private Drawable getPackageDrawable(String packageName) { + try { + return mContext.getPackageManager().getApplicationIcon(packageName); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + private String getQSTileLabel(String spec) { + if (QSUtils.isStaticQsTile(spec)) { + int resource = QSTileHost.getLabelResource(spec); + if (resource != 0) { + return mContext.getText(resource).toString(); + } else { + return spec; + } + } else if (QSUtils.isDynamicQsTile(extractTileTagFromSpec(spec))) { + return QSUtils.getDynamicQSTileLabel(mContext, + UserHandle.myUserId(), extractTileTagFromSpec(spec)); + } else { + return getPackageLabel(getCustomTilePackage(spec)); + } + } + + @Override + public int getGroupCount() { + return mPackageTileMap.keySet().size(); + } + + @Override + public int getChildrenCount(int groupPosition) { + return mPackageTileMap.valueAt(groupPosition).size(); + } + + @Override + public String getGroup(int groupPosition) { + return mPackageTileMap.keyAt(groupPosition); + } + + @Override + public String getChild(int groupPosition, int childPosition) { + return mPackageTileMap.valueAt(groupPosition).get(childPosition); + } + + @Override + public long getGroupId(int groupPosition) { + return groupPosition; + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return mPackageTileMap.valueAt(groupPosition).get(childPosition).hashCode(); + } + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, + ViewGroup parent) { + LinearLayout row = (LinearLayout) convertView; + if (row == null) { + row = (LinearLayout) LayoutInflater.from(mContext) + .inflate(R.layout.qs_tile_category_row, parent, false); + } + TextView title = (TextView) row.findViewById(android.R.id.title); + + ImageView systemOrAppIcon = (ImageView) row.findViewById(android.R.id.icon); + ImageView expansionIndicator = (ImageView) row.findViewById(android.R.id.icon2); + + expansionIndicator.setImageResource(isExpanded ? R.drawable.ic_qs_tile_contract + : R.drawable.ic_qs_tile_expand); + // hide indicator when there's only 1 group + final boolean singleGroupMode = getGroupCount() == 1; + expansionIndicator.setVisibility(singleGroupMode ? View.GONE : View.VISIBLE); + + String group = getGroup(groupPosition); + if (group.equals(PACKAGE_ANDROID)) { + group = mContext.getText(R.string.quick_settings_tiles_category_system).toString(); + // special icon + systemOrAppIcon.setImageResource(R.drawable.ic_qs_tile_category_system); + } else { + group = getPackageLabel(group); + systemOrAppIcon.setImageResource(R.drawable.ic_qs_tile_category_other); + } + title.setText(group); + + if (isExpanded) { + expansionIndicator.setColorFilter( + mContext.getColor( + R.color.qs_detailed_expansion_indicator_color), PorterDuff.Mode.SRC_ATOP); + systemOrAppIcon.setColorFilter( + mContext.getColor(R.color.qs_detailed_icon_tint_color), PorterDuff.Mode.SRC_ATOP); + title.setTextColor(mContext.getColor(R.color.qs_detailed_title_text_color)); + } else { + title.setTextColor(mContext.getColor(R.color.qs_detailed_default_text_color)); + systemOrAppIcon.setColorFilter(null); + expansionIndicator.setColorFilter(null); + } + return row; + } + + @Override + public View getChildView(int groupPosition, int childPosition, boolean isLastChild, + View convertView, ViewGroup parent) { + LinearLayout child = (LinearLayout) convertView; + if (child == null) { + child = (LinearLayout) LayoutInflater.from(mContext) + .inflate(R.layout.qs_tile_child_row, parent, false); + } + String spec = getChild(groupPosition, childPosition); + + TextView title = (TextView) child.findViewById(android.R.id.title); + title.setText(getQSTileLabel(spec)); + + ImageView icon = (ImageView) child.findViewById(android.R.id.icon); + icon.setImageDrawable(getQSTileIcon(spec)); + + return child; + } + + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return true; + } + + @Override + public int getTitle() { + return R.string.quick_settings_tiles_add_tiles; + } + + @Override + public Boolean getToggleState() { + return null; + } + + @Override + public View createDetailView(Context context, View convertView, ViewGroup parent) { + ExpandableListView lv = (ExpandableListView) convertView; + if (lv == null) { + lv = new ExpandableListView(parent.getContext()); + lv.setOnTouchListener(new OnTouchListener() { + // Setting on Touch Listener for handling the touch inside ScrollView + @Override + public boolean onTouch(View v, MotionEvent event) { + // Disallow the touch request for parent scroll on touch of child view + v.getParent().requestDisallowInterceptTouchEvent(true); + return false; } - }).create(); - SystemUIDialog.makeSystemUIDialog(d); - d.show(); - } + }); + } + lv.setAdapter(this); + lv.expandGroup(mPackageTileMap.indexOfKey(PACKAGE_ANDROID)); + lv.setGroupIndicator(null); + lv.setChildIndicator(null); + lv.setChildDivider(new ColorDrawable(Color.TRANSPARENT)); + lv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { + @Override + public boolean onChildClick(ExpandableListView parent, View v, + int groupPosition, int childPosition, long id) { + String spec = getChild(groupPosition, childPosition); + + final QSTile tile = mHost.getTile(spec); + if (tile != null && tile instanceof CustomQSTile) { + // already present + ((CustomQSTile) tile).setUserRemoved(false); + mPanel.refreshAllTiles(); + } else { + // reset its state just in case it's not published + CustomQSTile.getCustomQSTilePrefs(mContext) + .edit() + .remove(spec) + .apply(); + mPanel.add(spec); + // TODO notify user the app isn't publishing the tile, but it now can be! + } + mPanel.closeDetail(); + return true; + } + }); + lv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { + @Override + public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, + long id) { + if (getGroupCount() == 1) { + // disable contracting/expanding group when there's only 1 + return true; + } + return false; + } + }); + return lv; + } - private boolean isValid(String action) { - for (int i = 0; i < action.length(); i++) { - char c = action.charAt(i); - if (!Character.isAlphabetic(c) && !Character.isDigit(c) && c != '.') { - return false; + @Override + public Intent getSettingsIntent() { + return null; + } + + @Override + public StatusBarPanelCustomTile getCustomTile() { + return null; + } + + @Override + public void setToggleState(boolean state) { + + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.DONT_LOG; + } + + private boolean isValid(String action) { + for (int i = 0; i < action.length(); i++) { + char c = action.charAt(i); + if (!Character.isAlphabetic(c) && !Character.isDigit(c) && c != '.') { + return false; + } } + return true; } - return true; } public void add(String tile) { @@ -1634,7 +2246,11 @@ public boolean isDragging() { } public boolean isDragRecordAttached() { - return mDragging && mDraggingRecord != null && mRecords.indexOf(mDraggingRecord) >= 0; + return mRecords.indexOf(mDraggingRecord) >= 0; + } + + public boolean isOnSettingsPage() { + return mEditing && mViewPager.getCurrentItem() == 0; } public void goToSettingsPage() { @@ -1675,6 +2291,7 @@ public void update() { if (firstRowLarge != mFirstRowLarge) { mFirstRowLarge = firstRowLarge; setTiles(mHost.getTiles()); + mPagerAdapter.notifyDataSetChanged(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPage.java b/packages/SystemUI/src/com/android/systemui/qs/QSPage.java index be2f7e52bf39d..7871a62bb2a5a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPage.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPage.java @@ -23,6 +23,8 @@ public class QSPage extends ViewGroup { private int mPage; + private boolean mAdapterEditingState; + public QSPage(Context context, QSDragPanel panel, int page) { super(context); mPanel = panel; @@ -120,7 +122,11 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } else { right = left + tileWith; } - if (mPanel.isAnimating(record)) continue; + if (mPanel.isAnimating(record)) { + record.tileView.layout(record.tileView.getLeft(), record.tileView.getTop(), + record.tileView.getRight(), record.tileView.getBottom()); + continue; + } if (false) { Log.v(TAG + "-" + mPage, "laying out " + record + ", top: " + top + ", left: " + left); Log.d(TAG, record + " wiping translations: " @@ -137,6 +143,14 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } } + public boolean getAdapterEditingState() { + return mAdapterEditingState; + } + + public void setAdapterEditingState(boolean editing) { + this.mAdapterEditingState = editing; + } + public boolean dualRecord(QSPanel.TileRecord record) { return mPanel.mFirstRowLarge && record.row == 0 && mPage == 0; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 1e6867d1f61c6..77ede938f3aa3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -72,7 +72,7 @@ public class QSPanel extends ViewGroup { protected int mDualTileUnderlap; protected int mBrightnessPaddingTop; protected int mGridHeight; - private boolean mExpanded; + protected boolean mExpanded; protected boolean mListening; private boolean mClosingDetail; @@ -82,7 +82,7 @@ public class QSPanel extends ViewGroup { protected QSTileHost mHost; protected QSFooter mFooter; - private boolean mGridContentVisible = true; + protected boolean mGridContentVisible = true; public QSPanel(Context context) { this(context, null); @@ -281,6 +281,15 @@ private void handleSetTileVisibility(View v, int visibility) { v.setVisibility(visibility); } + protected void setTileEnabled(View v, boolean enabled) { + mHandler.obtainMessage(H.SET_TILE_ENABLED, enabled ? 1 : 0, 0, v).sendToTarget(); + } + + private void handleSetTileEnabled(View v, boolean enabled) { + if (enabled == v.isEnabled()) return; + v.setEnabled(enabled); + } + public void setTiles(Collection> tiles) { for (TileRecord record : mRecords) { removeView(record.tileView); @@ -454,7 +463,7 @@ public void onClick(View v) { } } - private void setGridContentVisibility(boolean visible) { + protected void setGridContentVisibility(boolean visible) { int newVis = visible ? VISIBLE : INVISIBLE; for (int i = 0; i < mRecords.size(); i++) { TileRecord tileRecord = mRecords.get(i); @@ -606,12 +615,15 @@ private void setDetailRecord(Record r) { private class H extends Handler { private static final int SHOW_DETAIL = 1; private static final int SET_TILE_VISIBILITY = 2; + private static final int SET_TILE_ENABLED = 3; @Override public void handleMessage(Message msg) { if (msg.what == SHOW_DETAIL) { handleShowDetail((Record)msg.obj, msg.arg1 != 0); } else if (msg.what == SET_TILE_VISIBILITY) { handleSetTileVisibility((View)msg.obj, msg.arg1); + } else if (msg.what == SET_TILE_ENABLED) { + handleSetTileEnabled((View)msg.obj, msg.arg1 == 1); } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java index c2862e6be2d87..b00483ca607b2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java @@ -20,15 +20,27 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.ContentResolver; import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.UserHandle; +import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.util.Log; import android.view.View; -import android.view.ViewTreeObserver; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.TextView; import com.android.systemui.R; +import com.android.systemui.cm.UserContentObserver; +import com.android.systemui.settings.ToggleSlider; + +import cyanogenmod.providers.CMSettings; public class QSPanelTopView extends FrameLayout { @@ -40,13 +52,21 @@ public class QSPanelTopView extends FrameLayout { protected View mDropTarget; protected View mBrightnessView; protected TextView mToastView; + protected View mAddTarget; + protected TextView mEditInstructionText; private boolean mEditing = false; private boolean mDisplayingInstructions = false; private boolean mDisplayingTrash = false; private boolean mDisplayingToast = false; + public boolean mHasBrightnessSliderToDisplay = true; private AnimatorSet mAnimator; + private ImageView mDropTargetIcon; + + private SettingsObserver mSettingsObserver; + private boolean mListening; + private boolean mSkipAnimations; public QSPanelTopView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); @@ -59,6 +79,8 @@ public QSPanelTopView(Context context, @Nullable AttributeSet attrs, int defStyl public QSPanelTopView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + setFocusable(true); + mSettingsObserver = new SettingsObserver(new Handler()); } @Override @@ -70,30 +92,54 @@ public View getDropTarget() { return mDropTarget; } + public ImageView getDropTargetIcon() { + return mDropTargetIcon; + } + public View getBrightnessView() { return mBrightnessView; } + public View getAddTarget() { + return mAddTarget; + } + @Override protected void onFinishInflate() { super.onFinishInflate(); mDropTarget = findViewById(R.id.delete_container); + mDropTargetIcon = (ImageView) findViewById(R.id.delete_target); mEditTileInstructionView = findViewById(R.id.edit_container); mBrightnessView = findViewById(R.id.brightness_container); mToastView = (TextView) findViewById(R.id.qs_toast); + mAddTarget = findViewById(R.id.add_target); + mEditInstructionText = (TextView) findViewById(R.id.edit_text_instruction); + updateResources(); + } + + public void updateResources() { + if (mEditInstructionText != null) { + mEditInstructionText.setText(R.string.qs_tile_edit_header_instruction); + } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); - mBrightnessView.measure(exactly(width), MeasureSpec.UNSPECIFIED); - int dh = mBrightnessView.getMeasuredHeight(); + mBrightnessView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED); + mEditTileInstructionView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED); + mToastView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED); + + // if we are showing a brightness slider, always fit to that, otherwise only + // declare a height when editing. + int dh = mHasBrightnessSliderToDisplay ? mBrightnessView.getMeasuredHeight() + : mEditing ? mEditTileInstructionView.getMeasuredHeight() : 0; - mDropTarget.measure(exactly(width), atMost(dh)); - mEditTileInstructionView.measure(exactly(width), atMost(dh)); - mToastView.measure(exactly(width), atMost(dh)); + mDropTarget.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh)); + mEditTileInstructionView.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh)); + mToastView.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh)); - setMeasuredDimension(width, mBrightnessView.getMeasuredHeight()); + setMeasuredDimension(width, dh); } @Override @@ -101,20 +147,11 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto boolean animateToState = !isLaidOut(); super.onLayout(changed, left, top, right, bottom); if (animateToState) { - Log.e(TAG, "first layout animating to state!"); - animateToState(); + goToState(); } } - private static int atMost(int height) { - return MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); - } - - private static int exactly(int size) { - return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); - } - - public void setEditing(boolean editing) { + public void setEditing(boolean editing, boolean skipAnim) { mEditing = editing; if (editing) { mDisplayingInstructions = true; @@ -123,7 +160,11 @@ public void setEditing(boolean editing) { mDisplayingInstructions = false; mDisplayingTrash = false; } - animateToState(); + if (skipAnim) { + goToState(); + } else { + animateToState(); + } } public void onStopDrag() { @@ -136,6 +177,18 @@ public void onStartDrag() { animateToState(); } + public void setDropIcon(int resourceId, int colorResourceId) { + mDropTargetIcon.setImageResource(resourceId); + final Drawable drawable = mDropTargetIcon.getDrawable(); + + DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_ATOP); + DrawableCompat.setTint(drawable, mContext.getColor(colorResourceId)); + + if (drawable instanceof Animatable) { + ((Animatable) drawable).start(); + } + } + public void toast(int textStrResId) { mDisplayingToast = true; mToastView.setText(textStrResId); @@ -173,38 +226,36 @@ public void run() { mAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { - setLayerType(LAYER_TYPE_HARDWARE, null); - - mDropTarget.setLayerType(LAYER_TYPE_HARDWARE, null); - mEditTileInstructionView.setLayerType(LAYER_TYPE_HARDWARE, null); - mBrightnessView.setLayerType(LAYER_TYPE_HARDWARE, null); - mToastView.setLayerType(LAYER_TYPE_HARDWARE, null); - - mDropTarget.setVisibility(View.VISIBLE); - mEditTileInstructionView.setVisibility(View.VISIBLE); - mBrightnessView.setVisibility(View.VISIBLE); - mToastView.setVisibility(View.VISIBLE); - - if (showToast) { - mToastView.bringToFront(); + // if the view is already visible, keep it visible on animation start + // to animate it out, otherwise set it as invisible (to not affect view height) + mEditTileInstructionView.setVisibility( + getVisibilityForAnimation(mEditTileInstructionView, showInstructions)); + mDropTarget.setVisibility( + getVisibilityForAnimation(mDropTarget, showTrash)); + mToastView.setVisibility( + getVisibilityForAnimation(mToastView, showToast)); + if (mHasBrightnessSliderToDisplay) { + mBrightnessView.setVisibility( + getVisibilityForAnimation(mBrightnessView, showBrightness)); } } @Override public void onAnimationEnd(Animator animation) { mToastView.setVisibility(showToast ? View.VISIBLE : View.GONE); - mEditTileInstructionView.setVisibility(showInstructions ? View.VISIBLE : View.GONE); + mEditTileInstructionView.setVisibility(showInstructions + ? View.VISIBLE : View.GONE); mDropTarget.setVisibility(showTrash ? View.VISIBLE : View.GONE); - mBrightnessView.setVisibility(showBrightness ? View.VISIBLE : View.GONE); + if (mHasBrightnessSliderToDisplay) { + mBrightnessView.setVisibility(showBrightness ? View.VISIBLE : View.GONE); + } - setLayerType(LAYER_TYPE_NONE, null); + mAnimator = null; - mDropTarget.setLayerType(LAYER_TYPE_NONE, null); - mEditTileInstructionView.setLayerType(LAYER_TYPE_NONE, null); - mBrightnessView.setLayerType(LAYER_TYPE_NONE, null); - mToastView.setLayerType(LAYER_TYPE_NONE, null); + requestLayout(); if (showToast) { + mToastView.bringToFront(); mToastView.postDelayed(new Runnable() { @Override public void run() { @@ -216,21 +267,34 @@ public void run() { } }); - mAnimator.setDuration(500); + mAnimator.setDuration(mSkipAnimations ? 0 : 500); mAnimator.setInterpolator(new FastOutSlowInInterpolator()); - mAnimator.setStartDelay(100); + mAnimator.setStartDelay(mSkipAnimations ? 0 : 100); mAnimator.playTogether(instructionAnimator, trashAnimator, brightnessAnimator, toastAnimator); mAnimator.start(); } }; + private int getVisibilityForAnimation(View view, boolean show) { + if (show || view.getVisibility() != View.GONE) { + return View.VISIBLE; + } + return View.INVISIBLE; + } + private void animateToState() { + mSkipAnimations = false; + post(mAnimateRunnable); + } + + private void goToState() { + mSkipAnimations = true; post(mAnimateRunnable); } + private Animator animateView(View v, boolean show) { - return ObjectAnimator.ofFloat(v, "translationY", - show ? 0 : -mBrightnessView.getMeasuredHeight()); + return ObjectAnimator.ofFloat(v, "translationY", show ? 0 : -getMeasuredHeight()); } private Animator showBrightnessSlider(boolean show) { @@ -248,4 +312,66 @@ private Animator showTrash(boolean show) { private Animator showToast(boolean show) { return animateView(mToastView, show); } + + public void setListening(boolean listening) { + if (mListening == listening) return; + mListening = listening; + if (mListening) { + mSettingsObserver.observe(); + } else { + mSettingsObserver.unobserve(); + } + + } + + class SettingsObserver extends UserContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + @Override + protected void observe() { + super.observe(); + + ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.QS_SHOW_BRIGHTNESS_SLIDER), false, this, UserHandle.USER_ALL); + update(); + } + + @Override + protected void unobserve() { + super.unobserve(); + + ContentResolver resolver = mContext.getContentResolver(); + resolver.unregisterContentObserver(this); + } + + @Override + public void update() { + ContentResolver resolver = mContext.getContentResolver(); + int currentUserId = ActivityManager.getCurrentUser(); + boolean showSlider = CMSettings.System.getIntForUser(resolver, + CMSettings.System.QS_SHOW_BRIGHTNESS_SLIDER, 1, currentUserId) == 1; + if (showSlider != mHasBrightnessSliderToDisplay) { + if (mAnimator != null) { + mAnimator.cancel(); // cancel everything we're animating + mAnimator = null; + } + mHasBrightnessSliderToDisplay = showSlider; + if (mBrightnessView != null) { + mBrightnessView.setVisibility(showSlider ? View.VISIBLE : View.GONE); + + // as per showBrightnessSlider() in QSPanel.java, we look it up on-the-go + ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider); + if (brightnessSlider != null) { + brightnessSlider.setVisibility(showSlider ? View.VISIBLE : View.GONE); + } + + } + getParent().requestLayout(); + animateToState(); + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java index 959a1eec94c6a..0a2b937a1a3f9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java @@ -15,27 +15,44 @@ */ package com.android.systemui.qs; +import android.Manifest; import android.annotation.Nullable; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.ResultReceiver; import android.util.AttributeSet; import android.view.View; -import android.widget.LinearLayout; +import android.widget.CompoundButton; +import android.widget.ScrollView; + +import com.android.systemui.R; import com.android.systemui.statusbar.phone.QSTileHost; import com.android.systemui.statusbar.phone.SystemUIDialog; -import com.android.systemui.R; +public class QSSettings extends ScrollView { + + private static final String RESULT_RECEIVER_EXTRA = "result_receiver"; + private static final String LOCK_CLOCK_PACKAGENAME = "com.cyanogenmod.lockclock"; + private static final String LOCK_CLOCK_PERM_CLASS = LOCK_CLOCK_PACKAGENAME + + ".weather.PermissionRequestActivity"; -public class QSSettings extends LinearLayout { private QSTileHost mHost; - public QSSettings(Context context) { - super(context); - } + private boolean mAdapterEditingState; + private QSBooleanSettingRow mShowWeather; + private ResultReceiver mResultReceiver; public QSSettings(Context context, @Nullable AttributeSet attrs) { super(context, attrs); + setFillViewport(true); } @Override @@ -48,6 +65,51 @@ public void onClick(View v) { initiateTileReset(); } }); + + mShowWeather = (QSBooleanSettingRow) findViewById(R.id.show_weather); + mShowWeather.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + PackageManager packageManager = getContext().getPackageManager(); + if (packageManager.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, + LOCK_CLOCK_PACKAGENAME) != PackageManager.PERMISSION_GRANTED) { + mShowWeather.setChecked(false); + requestPermission(); + mHost.collapsePanels(); + } + } + } + }); + } + + public Parcelable getResultReceiverForSending() { + if (mResultReceiver == null) { + mResultReceiver = new ResultReceiver(new Handler()) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + super.onReceiveResult(resultCode, resultData); + if (resultCode == Activity.RESULT_OK) { + mShowWeather.setChecked(true); + } + mResultReceiver = null; + } + }; + } + Parcel parcel = Parcel.obtain(); + mResultReceiver.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); + parcel.recycle(); + return receiverForSending; + } + + private void requestPermission() { + Intent i = new Intent(); + i.setClassName(LOCK_CLOCK_PACKAGENAME, LOCK_CLOCK_PERM_CLASS); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + i.putExtra(RESULT_RECEIVER_EXTRA, getResultReceiverForSending()); + getContext().startActivity(i); } private void initiateTileReset() { @@ -58,7 +120,7 @@ private void initiateTileReset() { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mHost.resetTiles(); + mHost.initiateReset(); } }).create(); SystemUIDialog.makeSystemUIDialog(d); @@ -68,4 +130,12 @@ public void onClick(DialogInterface dialog, int which) { public void setHost(QSTileHost host) { mHost = host; } + + public boolean getAdapterEditingState() { + return mAdapterEditingState; + } + + public void setAdapterEditingState(boolean editing) { + this.mAdapterEditingState = editing; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index 7d7e5168010b8..01a170f61ad15 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -34,6 +34,7 @@ import android.widget.RemoteViews; import com.android.systemui.qs.QSTile.State; +import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.FlashlightController; @@ -344,6 +345,7 @@ public interface Host { CastController getCastController(); FlashlightController getFlashlightController(); KeyguardMonitor getKeyguardMonitor(); + BatteryController getBatteryController(); boolean isEditing(); void setEditing(boolean editing); void resetTiles(); @@ -354,6 +356,7 @@ public interface Callback { void setEditing(boolean editing); boolean isEditing(); void goToSettingsPage(); + void resetTiles(); } } @@ -497,6 +500,7 @@ private UserBoolean(boolean userInitiated, boolean value) { public static class State { public boolean visible; + public boolean enabled = true; public Icon icon; public String label; public String contentDescription; @@ -507,6 +511,7 @@ public boolean copyTo(State other) { if (other == null) throw new IllegalArgumentException(); if (!other.getClass().equals(getClass())) throw new IllegalArgumentException(); final boolean changed = other.visible != visible + || !Objects.equals(other.enabled, enabled) || !Objects.equals(other.icon, icon) || !Objects.equals(other.label, label) || !Objects.equals(other.contentDescription, contentDescription) @@ -514,6 +519,7 @@ public boolean copyTo(State other) { || !Objects.equals(other.dualLabelContentDescription, dualLabelContentDescription); other.visible = visible; + other.enabled = enabled; other.icon = icon; other.label = label; other.contentDescription = contentDescription; @@ -530,6 +536,7 @@ public String toString() { protected StringBuilder toStringBuilder() { final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('['); sb.append("visible=").append(visible); + sb.append(",enabled=").append(enabled); sb.append(",icon=").append(icon); sb.append(",label=").append(label); sb.append(",contentDescription=").append(contentDescription); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index 667bd30229dbd..7c637828c94d0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -22,6 +22,8 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; @@ -128,37 +130,36 @@ protected void onConfigurationChanged(Configuration newConfig) { } private void recreateLabel() { - Log.d(TAG, "recreateLabel() called with " + ""); CharSequence labelText = null; CharSequence labelDescription = null; - if (mLabel != null) { + if (mLabel != null && mLabel.isAttachedToWindow()) { labelText = mLabel.getText(); removeView(mLabel); - mLabel = null; } - if (mDualLabel != null) { + if (mDualLabel != null && mDualLabel.isAttachedToWindow()) { labelText = mDualLabel.getText(); labelDescription = mDualLabel.getContentDescription(); removeView(mDualLabel); - mDualLabel = null; } final Resources res = mContext.getResources(); if (mDual) { - mDualLabel = new QSDualTileLabel(mContext); - mDualLabel.setId(View.generateViewId()); - mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect); - if (mDualDetails) { - mDualLabel.setFirstLineCaret(mContext.getDrawable(R.drawable.qs_dual_tile_caret)); + if (mDualLabel == null) { + mDualLabel = new QSDualTileLabel(mContext); + mDualLabel.setId(View.generateViewId()); + mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect); + if (mDualDetails) { + mDualLabel.setFirstLineCaret(mContext.getDrawable(R.drawable.qs_dual_tile_caret)); + } + mDualLabel.setTextColor(mContext.getColor(R.color.qs_tile_text)); + mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx); + mDualLabel.setTypeface(CONDENSED); + mDualLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, + res.getDimensionPixelSize(R.dimen.qs_tile_text_size)); + mDualLabel.setClickable(true); + mDualLabel.setFocusable(true); + mDualLabel.setOnClickListener(mDualDetails ? mClickSecondary : mClickPrimary); + mDualLabel.setOnLongClickListener(mLongClick); } - mDualLabel.setTextColor(mContext.getColor(R.color.qs_tile_text)); - mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx); - mDualLabel.setTypeface(CONDENSED); - mDualLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, - res.getDimensionPixelSize(R.dimen.qs_tile_text_size)); - mDualLabel.setClickable(true); - mDualLabel.setFocusable(true); - mDualLabel.setOnClickListener(mDualDetails ? mClickSecondary : mClickPrimary); - mDualLabel.setOnLongClickListener(mLongClick); if (labelText != null) { mDualLabel.setText(labelText); } @@ -168,16 +169,18 @@ private void recreateLabel() { addView(mDualLabel); mDualLabel.setAccessibilityTraversalAfter(mTopBackgroundView.getId()); } else { - mLabel = new TextView(mContext); - mLabel.setTextColor(mContext.getColor(R.color.qs_tile_text)); - mLabel.setGravity(Gravity.CENTER_HORIZONTAL); - mLabel.setMinLines(2); - mLabel.setPadding(0, 0, 0, 0); - mLabel.setTypeface(CONDENSED); - mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, - res.getDimensionPixelSize(R.dimen.qs_tile_text_size)); - mLabel.setClickable(false); - mLabel.setFocusable(false); + if (mLabel == null) { + mLabel = new TextView(mContext); + mLabel.setTextColor(mContext.getColor(R.color.qs_tile_text)); + mLabel.setGravity(Gravity.CENTER_HORIZONTAL); + mLabel.setMinLines(2); + mLabel.setPadding(0, 0, 0, 0); + mLabel.setTypeface(CONDENSED); + mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, + res.getDimensionPixelSize(R.dimen.qs_tile_text_size)); + mLabel.setClickable(false); + mLabel.setFocusable(false); + } if (labelText != null) { mLabel.setText(labelText); } @@ -217,6 +220,10 @@ public boolean setDual(boolean dual, boolean hasDetails) { setFocusable(!dual); mDivider.setVisibility(dual ? VISIBLE : GONE); mTopBackgroundView.setVisibility(dual ? VISIBLE : GONE); + + if (changed) { + getParent().requestLayout(); + } postInvalidate(); return changed; } @@ -329,9 +336,20 @@ protected void handleStateChanged(QSTile.State state) { mDualLabel.setText(state.label); mDualLabel.setContentDescription(state.dualLabelContentDescription); mTopBackgroundView.setContentDescription(state.contentDescription); + if (!Objects.equals(state.enabled, mDualLabel.isEnabled())) { + mTopBackgroundView.setEnabled(state.enabled); + mDualLabel.setEnabled(state.enabled); + mDualLabel.setTextColor(mContext.getResources().getColor(state.enabled ? + R.color.qs_tile_text : R.color.qs_tile_text_disabled)); + } } else { mLabel.setText(state.label); setContentDescription(state.contentDescription); + if (!Objects.equals(state.enabled, mLabel.isEnabled())) { + mLabel.setEnabled(state.enabled); + mLabel.setTextColor(mContext.getResources().getColor(state.enabled ? + R.color.qs_tile_text : R.color.qs_tile_text_disabled)); + } } } @@ -350,6 +368,14 @@ protected void setIcon(ImageView iv, QSTile.State state) { } } } + if (!Objects.equals(state.enabled, iv.isEnabled())) { + iv.setEnabled(state.enabled); + if (state.enabled) { + iv.setColorFilter(null); + } else { + iv.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); + } + } } public void onStateChanged(QSTile.State state) { @@ -392,7 +418,18 @@ public void setEditing(boolean editing) { if (mLabel != null) { mLabel.setFocusable(!editing); } - mRipple.setVisible(!editing, false); + if (mRipple != null) { + mRipple.setVisible(!editing, false); + } + } + + // clean up extra label view if needed + if (!editing) { + if (mDual && mLabel != null) { + mLabel = null; + } else if (!mDual && mDualLabel != null) { + mDualLabel = null; + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java b/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java index 01c48b190e4c6..3dc5d27c99e91 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java @@ -14,7 +14,7 @@ public class QSViewPager extends ViewPager { private static final String TAG = "QSViewPager"; protected static final float SCROLL_PERCENT = .10f; - private boolean mPagingEnabled; + QSDragPanel mDragPanel; public QSViewPager(Context context) { @@ -34,7 +34,6 @@ public boolean hasOverlappingRendering() { public boolean canScrollHorizontally(int direction) { if (direction < 0 && mDragPanel.isDragging() - && mPagingEnabled && getCurrentItem() == 1) { // can't scroll left while not editing, OR dragging on the first page return false; @@ -49,7 +48,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { View child = getChildAt(i); child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = child.getMeasuredHeight(); - if (h > height) height = h; + if (h > height && !(child instanceof QSSettings)) height = h; } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -103,30 +102,4 @@ public void onAnimationUpdate(ValueAnimator animation) { Log.e(TAG, "can't start fake drag?"); } } - - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - if (mPagingEnabled) { - return super.onInterceptTouchEvent(event); - } - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mPagingEnabled) { - return super.onTouchEvent(event); - } - return false; - } - - public void setPagingEnabled(boolean enabled) { - if (mPagingEnabled == enabled) return; - mPagingEnabled = enabled; - //Log.i(TAG, "setPagingEnabled() called with " + "enabled = [" + enabled + "]"); - if (getCurrentItem() > 0 && !mPagingEnabled) { - //Log.w(TAG, "resetting to item 0 because paging is disabled."); - setCurrentItem(0, true); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java index 7da198df028f1..b970a4cddbe6d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The CyanogenMod Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,16 +26,18 @@ import android.os.UserHandle; import android.provider.Settings; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSTile; import java.net.InetAddress; import cyanogenmod.providers.CMSettings; +import org.cyanogenmod.internal.logging.CMMetricsLogger; public class AdbOverNetworkTile extends QSTile { + private boolean mListening; + private static final Intent SETTINGS_DEVELOPMENT = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); @@ -72,24 +74,24 @@ protected void handleUpdateState(BooleanState state, Object arg) { InetAddress address = NetworkUtils.intToInetAddress(wifiInfo.getIpAddress()); state.label = address.getHostAddress(); } else { - //if wifiInfo is null, set the enabled label without host address - state.label = mContext.getString(R.string.quick_settings_network_adb_enabled_label); + // if wifiInfo is null, set the label without host address + state.label = mContext.getString(R.string.quick_settings_network_adb_label); } state.icon = ResourceIcon.get(R.drawable.ic_qs_network_adb_on); } else { // Otherwise set the disabled label and icon - state.label = mContext.getString(R.string.quick_settings_network_adb_disabled_label); + state.label = mContext.getString(R.string.quick_settings_network_adb_label); state.icon = ResourceIcon.get(R.drawable.ic_qs_network_adb_off); } } @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_ADB_OVER_NETWORK; } private boolean isAdbEnabled() { - return Settings.Secure.getInt(mContext.getContentResolver(), + return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ADB_ENABLED, 0) > 0; } @@ -111,16 +113,18 @@ public void onChange(boolean selfChange, Uri uri) { @Override public void setListening(boolean listening) { - if (listening) { - mContext.getContentResolver().registerContentObserver( - CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT), - false, mObserver); - mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(Settings.Global.ADB_ENABLED), - false, mObserver); - } else { - mContext.getContentResolver().unregisterContentObserver(mObserver); + if (mListening != listening) { + mListening = listening; + if (listening) { + mContext.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT), + false, mObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.ADB_ENABLED), + false, mObserver); + } else { + mContext.getContentResolver().unregisterContentObserver(mObserver); + } } } - } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java index 3ea97492dda5d..cc08d0257c089 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AmbientDisplayTile.java @@ -21,10 +21,10 @@ import android.provider.Settings; import android.provider.Settings.Secure; -import com.android.internal.logging.MetricsLogger; import com.android.systemui.qs.SecureSetting; import com.android.systemui.qs.QSTile; import com.android.systemui.R; +import org.cyanogenmod.internal.logging.CMMetricsLogger; /** Quick settings tile: Ambient Display **/ public class AmbientDisplayTile extends QSTile { @@ -86,7 +86,7 @@ protected void handleUpdateState(BooleanState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsLogger.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_AMBIENT_DISPLAY; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java new file mode 100644 index 0000000000000..1a60fa9a36b54 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles; + +import android.content.Context; +import android.content.Intent; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.PowerManager; +import android.provider.Settings; + +import com.android.systemui.qs.QSTile; +import com.android.systemui.R; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryStateRegistar; + +import cyanogenmod.power.PerformanceManager; + +import org.cyanogenmod.internal.logging.CMMetricsLogger; + +/** Quick settings tile: Battery saver **/ +public class BatterySaverTile extends QSTile { + + private static final Intent BATTERY_SETTINGS = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); + + private final PowerManager mPm; + private final boolean mHasPowerProfiles; + + private boolean mListening; + private boolean mPluggedIn; + + public BatterySaverTile(Host host) { + super(host); + mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mHasPowerProfiles = PerformanceManager.getInstance(mContext).getNumberOfProfiles() > 0; + } + + @Override + protected BooleanState newTileState() { + return new BooleanState(); + } + + @Override + public void handleClick() { + mPm.setPowerSaveMode(!mState.value); + refreshState(!mState.value); + } + + @Override + public void handleLongClick() { + mHost.startActivityDismissingKeyguard(BATTERY_SETTINGS); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + state.value = arg instanceof Boolean ? (boolean) arg : mPm.isPowerSaveMode(); + state.visible = !mHasPowerProfiles; + state.label = mContext.getString(R.string.quick_settings_battery_saver_label); + if (state.value) { + state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_battery_saver_on); + } else { + state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_battery_saver_off); + } + + state.enabled = !mPluggedIn; + if (mPluggedIn) { + state.label = mContext.getString(R.string.quick_settings_battery_saver_label_charging); + } + } + + @Override + protected String composeChangeAnnouncement() { + if (mState.value) { + return mContext.getString( + R.string.accessibility_quick_settings_battery_saver_changed_on); + } else { + return mContext.getString( + R.string.accessibility_quick_settings_battery_saver_changed_off); + } + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.TILE_BATTERY_SAVER; + } + + private BatteryStateRegistar.BatteryStateChangeCallback mBatteryState + = new BatteryStateRegistar.BatteryStateChangeCallback() { + @Override + public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, + boolean charging) { + mPluggedIn = pluggedIn || charging; + refreshState(); + } + + @Override + public void onPowerSaveChanged() { + refreshState(); + } + + @Override + public void onBatteryStyleChanged(int style, int percentMode) { + // ignore + } + }; + + @Override + public void setListening(boolean listening) { + if (mListening == listening) return; + mListening = listening; + + if (listening) { + getHost().getBatteryController().addStateChangedCallback(mBatteryState); + } else { + getHost().getBatteryController().removeStateChangedCallback(mBatteryState); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index a798e4e4cfe63..cdedc26695fbd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -225,6 +225,7 @@ public View createDetailView(Context context, View convertView, ViewGroup parent listView.setOnItemClickListener(this); listView.setAdapter(mAdapter = new QSDetailItemsList.QSDetailListAdapter(context, mBluetoothItems)); + mAdapter.setCallback(this); mItemsList.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty, R.string.quick_settings_bluetooth_detail_empty_text); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java new file mode 100644 index 0000000000000..fb6ec428ea991 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.CountDownTimer; +import android.os.PowerManager; +import android.os.SystemClock; +import android.provider.Settings; + +import com.android.systemui.qs.QSTile; +import com.android.systemui.R; + +import org.cyanogenmod.internal.logging.CMMetricsLogger; + +/** Quick settings tile: Caffeine **/ +public class CaffeineTile extends QSTile { + + private final PowerManager.WakeLock mWakeLock; + private int mSecondsRemaining; + private int mDuration; + private static int[] DURATIONS = new int[] { + 5 * 60, // 5 min + 10 * 60, // 10 min + 30 * 60, // 30 min + -1, // infinity + }; + private CountDownTimer mCountdownTimer = null; + public long mLastClickTime = -1; + private final Receiver mReceiver = new Receiver(); + private boolean mListening; + + public CaffeineTile(Host host) { + super(host); + mWakeLock = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE)).newWakeLock( + PowerManager.FULL_WAKE_LOCK, "CaffeineTile"); + mReceiver.init(); + } + + @Override + protected BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleDestroy() { + super.handleDestroy(); + stopCountDown(); + mReceiver.destroy(); + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } + + @Override + public void setListening(boolean listening) { + } + + @Override + public void handleClick() { + // If last user clicks < 5 seconds + // we cycle different duration + // otherwise toggle on/off + if (mWakeLock.isHeld() && (mLastClickTime != -1) && + (SystemClock.elapsedRealtime() - mLastClickTime < 5000)) { + // cycle duration + mDuration++; + if (mDuration >= DURATIONS.length) { + // all durations cycled, turn if off + mDuration = -1; + stopCountDown(); + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } else { + // change duration + startCountDown(DURATIONS[mDuration]); + if (!mWakeLock.isHeld()) { + mWakeLock.acquire(); + } + } + } else { + // toggle + if (mWakeLock.isHeld()) { + mWakeLock.release(); + stopCountDown(); + } else { + mWakeLock.acquire(); + mDuration = 0; + startCountDown(DURATIONS[mDuration]); + } + } + mLastClickTime = SystemClock.elapsedRealtime(); + refreshState(); + } + + private void startCountDown(long duration) { + stopCountDown(); + mSecondsRemaining = (int)duration; + if (duration == -1) { + // infinity timing, no need to start timer + return; + } + mCountdownTimer = new CountDownTimer(duration * 1000, 1000) { + + @Override + public void onTick(long millisUntilFinished) { + mSecondsRemaining = (int) (millisUntilFinished / 1000); + refreshState(); + } + + @Override + public void onFinish() { + if (mWakeLock.isHeld()) + mWakeLock.release(); + refreshState(); + } + + }.start(); + } + + private void stopCountDown() { + if (mCountdownTimer != null) { + mCountdownTimer.cancel(); + mCountdownTimer = null; + } + } + + private String formatValueWithRemainingTime() { + if (mSecondsRemaining == -1) { + return "\u221E"; // infinity + } + return String.format("%02d:%02d", + mSecondsRemaining / 60 % 60, mSecondsRemaining % 60); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + state.value = mWakeLock.isHeld(); + state.visible = true; + if (state.value) { + state.label = formatValueWithRemainingTime(); + state.icon = ResourceIcon.get(R.drawable.ic_qs_caffeine_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_caffeine_on); + } else { + state.label = mContext.getString(R.string.quick_settings_caffeine_label); + state.icon = ResourceIcon.get(R.drawable.ic_qs_caffeine_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_caffeine_off); + } + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.TILE_CAFFEINE; + } + + private final class Receiver extends BroadcastReceiver { + public void init() { + // Register for Intent broadcasts for... + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(this, filter, null, mHandler); + } + + public void destroy() { + mContext.unregisterReceiver(this); + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_SCREEN_OFF.equals(action)) { + // disable caffeine if user force off (power button) + stopCountDown(); + if (mWakeLock.isHeld()) + mWakeLock.release(); + refreshState(); + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index f83bbf465de70..cd608d69aa82e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -208,12 +208,14 @@ public View createDetailView(Context context, View convertView, ViewGroup parent @Override public void onViewAttachedToWindow(View v) { if (DEBUG) Log.d(TAG, "onViewAttachedToWindow"); + mController.setDiscovering(true); } @Override public void onViewDetachedFromWindow(View v) { if (DEBUG) Log.d(TAG, "onViewDetachedFromWindow"); mVisibleOrder.clear(); + mController.setDiscovering(false); } }); } @@ -221,7 +223,6 @@ public void onViewDetachedFromWindow(View v) { R.string.quick_settings_cast_detail_empty_text); mItems.setCallback(this); updateItems(mController.getCastDevices()); - mController.setDiscovering(true); return mItems; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index e2c0a2d9dbbf4..038fa5e6b1970 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -17,10 +17,12 @@ package com.android.systemui.qs.tiles; +import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.os.UserHandle; import android.telephony.TelephonyManager; import android.view.LayoutInflater; import android.view.View; @@ -47,11 +49,8 @@ public class CellularTile extends QSTile { private static final Intent MOBILE_NETWORK_SETTINGS = new Intent(Intent.ACTION_MAIN) .setComponent(new ComponentName("com.android.phone", "com.android.phone.MobileNetworkSettings")); - private static final Intent MOBILE_NETWORK_SETTINGS_MSIM = new Intent(Intent.ACTION_MAIN) - .setClassName("com.android.phone", "com.android.phone.msim.SelectSubscription") - .putExtra("PACKAGE", "com.android.phone") - .putExtra("TARGET_CLASS", "com.android.phone.MobileNetworkSettings") - .putExtra("TARGET_THEME", "Theme.Material.Settings"); + private static final Intent MOBILE_NETWORK_SETTINGS_MSIM + = new Intent("com.android.settings.sim.SIM_SUB_INFO_SETTINGS"); private final NetworkController mController; private final MobileDataController mDataController; @@ -92,6 +91,13 @@ public QSTileView createTileView(Context context) { return new SignalTileView(context); } + @Override + protected void handleUserSwitch(int newUserId) { + if (newUserId != UserHandle.USER_OWNER) { + refreshState(); + } + } + @Override protected void handleClick() { MetricsLogger.action(mContext, getMetricsCategory()); @@ -118,7 +124,8 @@ protected void handleLongClick() { @Override protected void handleUpdateState(SignalState state, Object arg) { - state.visible = mController.hasMobileDataFeature(); + state.visible = mController.hasMobileDataFeature() + && (ActivityManager.getCurrentUser() == UserHandle.USER_OWNER); if (!state.visible) return; CallbackInfo cb = (CallbackInfo) arg; if (cb == null) { @@ -140,7 +147,9 @@ protected void handleUpdateState(SignalState state, Object arg) { state.label = cb.enabled ? removeTrailingPeriod(cb.enabledDesc) - : r.getString(R.string.quick_settings_rssi_emergency_only); + : mDataController.isMobileDataSupported() ? + r.getString(R.string.data_sim_not_configured) : + r.getString(R.string.quick_settings_rssi_emergency_only); final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0) ? cb.signalContentDescription @@ -201,7 +210,7 @@ public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState q @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId) { + String description, boolean isWide, boolean showSeparateRoaming, int subId) { if (qsIcon == null) { // Not data sim, don't display. return; @@ -225,10 +234,14 @@ public void setNoSims(boolean show) { // Make sure signal gets cleared out when no sims. mInfo.mobileSignalIconId = 0; mInfo.dataTypeIconId = 0; - // Show a No SIMs description to avoid emergency calls message. + // Show a No SIMs description if we're incapable of supporting mobile data + // to avoid showing an emergency mode description. If we're still capable of + // supporting mobile data, notify the user that the data sim is not configured + // only relevant in MSIM scenario: CYNGNOS-2211 mInfo.enabled = true; - mInfo.enabledDesc = mContext.getString( - R.string.keyguard_missing_sim_message_short); + mInfo.enabledDesc = mDataController.isMobileDataSupported() ? + mContext.getString(R.string.data_sim_not_configured) + : mContext.getString(R.string.keyguard_missing_sim_message_short); mInfo.signalContentDescription = mInfo.enabledDesc; } refreshState(mInfo); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 04cc5dc333e6d..f49d97ee01372 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -39,7 +39,6 @@ public class ColorInversionTile extends QSTile { private final AnimationIcon mDisable = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation); private final SecureSetting mSetting; - private final UsageTracker mUsageTracker; private boolean mListening; @@ -50,29 +49,11 @@ public ColorInversionTile(Host host) { Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) { @Override protected void handleValueChanged(int value, boolean observedChange) { - if (value != 0 || observedChange) { - mUsageTracker.trackUsage(); - } if (mListening) { handleRefreshState(value); } } }; - mUsageTracker = new UsageTracker(host.getContext(), - Prefs.Key.COLOR_INVERSION_TILE_LAST_USED, ColorInversionTile.class, - R.integer.days_to_show_color_inversion_tile); - if (mSetting.getValue() != 0 && !mUsageTracker.isRecentlyUsed()) { - mUsageTracker.trackUsage(); - } - mUsageTracker.setListening(true); - mSetting.setListening(true); - } - - @Override - protected void handleDestroy() { - super.handleDestroy(); - mUsageTracker.setListening(false); - mSetting.setListening(false); } @Override @@ -82,7 +63,11 @@ protected BooleanState newTileState() { @Override public void setListening(boolean listening) { + if (mListening == listening) { + return; + } mListening = listening; + mSetting.setListening(mListening); } @Override @@ -101,25 +86,14 @@ protected void handleClick() { @Override protected void handleLongClick() { - if (mState.value) { - mHost.startActivityDismissingKeyguard(ACCESSIBILITY_SETTINGS); - } else { - final String title = mContext.getString( - R.string.quick_settings_reset_confirmation_title, mState.label); - mUsageTracker.showResetConfirmation(title, new Runnable() { - @Override - public void run() { - refreshState(); - } - }); - } + mHost.startActivityDismissingKeyguard(ACCESSIBILITY_SETTINGS); } @Override protected void handleUpdateState(BooleanState state, Object arg) { final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue(); final boolean enabled = value != 0; - state.visible = enabled || mUsageTracker.isRecentlyUsed(); + state.visible = true; state.value = enabled; state.label = mContext.getString(R.string.quick_settings_inversion_label); state.icon = enabled ? mEnable : mDisable; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java index f7af7f9002774..85790d144de4a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CompassTile.java @@ -23,15 +23,16 @@ import android.hardware.SensorManager; import android.widget.ImageView; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QSTileView; +import org.cyanogenmod.internal.logging.CMMetricsLogger; public class CompassTile extends QSTile implements SensorEventListener { private final static float ALPHA = 0.97f; private boolean mActive = false; + private boolean mListening = false; private SensorManager mSensorManager; private Sensor mAccelerationSensor; @@ -95,7 +96,7 @@ protected void handleUpdateState(BooleanState state, Object arg) { Float degrees = arg == null ? 0 :(float) arg; state.visible = true; - state.value = mActive; + state.value = mActive && mListening; if (state.value) { state.icon = ResourceIcon.get(R.drawable.ic_qs_compass_on); @@ -114,22 +115,22 @@ protected void handleUpdateState(BooleanState state, Object arg) { } } else { state.icon = ResourceIcon.get(R.drawable.ic_qs_compass_off); - state.label = mContext.getString(R.string.quick_settings_compass_off); + state.label = mContext.getString(R.string.quick_settings_compass_label); mImage.setRotation(0); } } @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_COMPASS; } @Override public void setListening(boolean listening) { - if (!listening) { - setListeningSensors(false); - mActive = false; - } + // setListening might get called multiple times with the same value, we check for it + // in setListeningSensors + mListening = listening; + setListeningSensors(mListening && mActive); } private String formatValueWithCardinalDirection(float degree) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java index 96cc51abdf886..40c7184ba43f5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java @@ -19,6 +19,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.ThemeConfig; import android.net.Uri; @@ -31,15 +32,12 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RemoteViews; import android.widget.TextView; -import com.android.internal.logging.MetricsLogger; - import com.android.systemui.qs.QSDetailItemsGrid; import com.android.systemui.qs.QSDetailItemsList; import cyanogenmod.app.CustomTile; @@ -47,22 +45,67 @@ import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; import java.util.Arrays; public class CustomQSTile extends QSTile { + private static final String HIDDEN_TILES_PREF_NAME = "user_hidden_qs_tiles"; + private CustomTile.ExpandedStyle mExpandedStyle; private PendingIntent mOnClick; + private PendingIntent mOnLongClick; private Uri mOnClickUri; private int mCurrentUserId; private StatusBarPanelCustomTile mTile; private CustomQSDetailAdapter mDetailAdapter; private boolean mCollapsePanel; + private boolean mUserRemoved; + private String mPersistedPlaceHolderKey; + + public CustomQSTile(Host host, String persistedSpec) { + super(host); + mTile = null; + mPersistedPlaceHolderKey = persistedSpec; + } public CustomQSTile(Host host, StatusBarPanelCustomTile tile) { super(host); mTile = tile; + mUserRemoved = getIsUserRemovedPersisted(); + } + + private String getPersistableKey() { + if (mPersistedPlaceHolderKey != null) { + return mPersistedPlaceHolderKey; + } else { + return getTile().persistableKey(); + } + } + + private boolean getIsUserRemovedPersisted() { + return getCustomQSTilePrefs(mContext).getBoolean(getPersistableKey(), false); + } + + public boolean isUserRemoved() { + return mUserRemoved; + } + + public void setUserRemoved(boolean removed) { + if (mUserRemoved != removed) { + if (removed) { + getCustomQSTilePrefs(mContext).edit().putBoolean(getPersistableKey(), true).apply(); + } else { + getCustomQSTilePrefs(mContext).edit().remove(getPersistableKey()).apply(); + } + mUserRemoved = removed; + refreshState(); + } + } + + public static SharedPreferences getCustomQSTilePrefs(Context context) { + return context.getSharedPreferences(HIDDEN_TILES_PREF_NAME, Context.MODE_PRIVATE); } @Override @@ -91,7 +134,16 @@ public void update(StatusBarPanelCustomTile customTile) { @Override protected void handleLongClick() { - if (mExpandedStyle == null) { + if (mOnLongClick != null) { + if (mOnLongClick.isActivity()) { + getHost().collapsePanels(); + } + try { + mOnLongClick.send(); + } catch (Throwable e) { + Log.w(TAG, "Error sending long click intent", e); + } + } else if (mExpandedStyle == null) { showDetail(true); } } @@ -119,15 +171,26 @@ protected void handleClick() { } } + public StatusBarPanelCustomTile getTile() { + return mTile; + } + @Override protected void handleUpdateState(State state, Object arg) { if (arg instanceof StatusBarPanelCustomTile) { mTile = (StatusBarPanelCustomTile) arg; + mPersistedPlaceHolderKey = null; + mUserRemoved = getIsUserRemovedPersisted(); + } + if (mTile == null) { + state.visible = false; + // nothing to show, it's a place holder for now + return; } final CustomTile customTile = mTile.getCustomTile(); state.contentDescription = customTile.contentDescription; state.label = customTile.label; - state.visible = true; + state.visible = !mUserRemoved; final int iconId = customTile.icon; if (iconId != 0 && (customTile.remoteIcon == null)) { final String iconPackage = mTile.getResPkg(); @@ -138,6 +201,7 @@ protected void handleUpdateState(State state, Object arg) { state.icon = new ExternalBitmapIcon(customTile.remoteIcon); } mOnClick = customTile.onClick; + mOnLongClick = customTile.onLongClick; mOnClickUri = customTile.onClickUri; mExpandedStyle = customTile.expandedStyle; mCollapsePanel = customTile.collapsePanel; @@ -146,7 +210,7 @@ protected void handleUpdateState(State state, Object arg) { @Override public int getMetricsCategory() { - return MetricsLogger.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_CUSTOM_QS; } private boolean isDynamicTile() { @@ -191,7 +255,7 @@ public void setToggleState(boolean state) { @Override public int getMetricsCategory() { - return MetricsLogger.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_CUSTOM_QS_DETAIL; } @Override @@ -282,4 +346,4 @@ private String getThemePackageName() { return themeConfig != null ? themeConfig.getOverlayForStatusBar() : null; } } -} \ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java index eaa5ff50e404d..7173786d0e815 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java @@ -16,11 +16,12 @@ package com.android.systemui.qs.tiles; -import com.android.internal.logging.MetricsLogger; import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import com.android.systemui.statusbar.policy.KeyguardMonitor; +import org.cyanogenmod.internal.logging.CMMetricsLogger; -public class EditTile extends QSTile { +public class EditTile extends QSTile implements KeyguardMonitor.Callback { private boolean mListening; @@ -53,7 +54,10 @@ protected void handleLongClick() { @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.visible = !getHost().getKeyguardMonitor().isShowing(); + final boolean showing = getHost().getKeyguardMonitor().isShowing(); + final boolean secure = getHost().getKeyguardMonitor().isSecure(); + state.visible = !showing || !secure; + state.enabled = !showing; state.label = mContext.getString(R.string.quick_settings_edit_label); if (arg instanceof Boolean) { @@ -66,7 +70,7 @@ protected void handleUpdateState(BooleanState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsLogger.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_EDIT; } @Override @@ -79,6 +83,16 @@ protected String composeChangeAnnouncement() { public void setListening(boolean listening) { if (mListening == listening) return; mListening = listening; + if (mListening) { + mHost.getKeyguardMonitor().addCallback(this); + } else { + mHost.getKeyguardMonitor().removeCallback(this); + } + refreshState(); + } + + @Override + public void onKeyguardChanged() { refreshState(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java new file mode 100644 index 0000000000000..d30bd91fb2ed3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles; + +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; +import android.provider.Settings.Global; + +import com.android.systemui.qs.GlobalSetting; +import com.android.systemui.qs.QSTile; +import com.android.systemui.R; + +import org.cyanogenmod.internal.logging.CMMetricsLogger; + +/** Quick settings tile: Heads up **/ +public class HeadsUpTile extends QSTile { + + private static final Intent NOTIFICATION_SETTINGS = + new Intent("android.settings.NOTIFICATION_MANAGER"); + + private final GlobalSetting mSetting; + + public HeadsUpTile(Host host) { + super(host); + + mSetting = new GlobalSetting(mContext, mHandler, Global.HEADS_UP_NOTIFICATIONS_ENABLED) { + @Override + protected void handleValueChanged(int value) { + handleRefreshState(value); + } + }; + } + + @Override + protected BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleClick() { + setEnabled(!mState.value); + refreshState(); + } + + @Override + protected void handleLongClick() { + mHost.startActivityDismissingKeyguard(NOTIFICATION_SETTINGS); + } + + private void setEnabled(boolean enabled) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, + enabled ? 1 : 0); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue(); + final boolean headsUp = value != 0; + state.value = headsUp; + state.visible = true; + state.label = mContext.getString(R.string.quick_settings_heads_up_label); + if (headsUp) { + state.icon = ResourceIcon.get(R.drawable.ic_qs_heads_up_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_heads_up_on); + } else { + state.icon = ResourceIcon.get(R.drawable.ic_qs_heads_up_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_heads_up_off); + } + } + + @Override + protected String composeChangeAnnouncement() { + if (mState.value) { + return mContext.getString(R.string.accessibility_quick_settings_heads_up_changed_on); + } else { + return mContext.getString(R.string.accessibility_quick_settings_heads_up_changed_off); + } + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.TILE_HEADS_UP; + } + + @Override + public void setListening(boolean listening) { + // Do nothing + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 4173efc236e4a..60803586e1a87 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -21,14 +21,21 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.wifi.WifiDevice; +import android.provider.Settings; import com.android.internal.logging.MetricsLogger; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.UsageTracker; +import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.HotspotController; +import java.util.List; + /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTile { @@ -41,19 +48,14 @@ public class HotspotTile extends QSTile { new AnimationIcon(R.drawable.ic_hotspot_disable_animation); private final HotspotController mController; private final Callback mCallback = new Callback(); - private final UsageTracker mUsageTracker; + private final ConnectivityManager mConnectivityManager; + private boolean mListening; + private int mNumConnectedClients = 0; public HotspotTile(Host host) { super(host); mController = host.getHotspotController(); - mUsageTracker = newUsageTracker(host.getContext()); - mUsageTracker.setListening(true); - } - - @Override - protected void handleDestroy() { - super.handleDestroy(); - mUsageTracker.setListening(false); + mConnectivityManager = host.getContext().getSystemService(ConnectivityManager.class); } @Override @@ -63,15 +65,31 @@ protected BooleanState newTileState() { @Override public void setListening(boolean listening) { + if (mListening == listening) return; if (listening) { mController.addCallback(mCallback); + mContext.registerReceiver(mTetherConnectStateChangedReceiver, + new IntentFilter(ConnectivityManager.TETHER_CONNECT_STATE_CHANGED)); } else { mController.removeCallback(mCallback); + mContext.unregisterReceiver(mTetherConnectStateChangedReceiver); } + mListening = listening; } @Override protected void handleClick() { + boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1); + if (airplaneMode) { + SystemUIDialog d = new SystemUIDialog(mContext); + d.setTitle(R.string.quick_settings_hotspot_label); + d.setMessage(R.string.hotspot_apm_message); + d.setPositiveButton(com.android.internal.R.string.ok, null); + d.setShowForAllUsers(true); + d.show(); + return; + } final boolean isEnabled = (Boolean) mState.value; MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled); mController.setHotspotEnabled(!isEnabled); @@ -81,30 +99,25 @@ protected void handleClick() { @Override protected void handleLongClick() { - if (mState.value) { - mHost.startActivityDismissingKeyguard(TETHER_SETTINGS); - } else { - final String title = mContext.getString( - R.string.quick_settings_reset_confirmation_title, mState.label); - mUsageTracker.showResetConfirmation(title, new Runnable() { - @Override - public void run() { - refreshState(); - } - }); - } + mHost.startActivityDismissingKeyguard(TETHER_SETTINGS); } @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed(); - state.label = mContext.getString(R.string.quick_settings_hotspot_label); + state.visible = mController.isHotspotSupported(); if (arg instanceof Boolean) { state.value = (boolean) arg; } else { state.value = mController.isHotspotEnabled(); } + if (state.visible && state.value) { + state.label = mContext.getResources().getQuantityString( + R.plurals.wifi_hotspot_connected_clients_label, mNumConnectedClients, + mNumConnectedClients); + } else { + state.label = mContext.getString(R.string.quick_settings_hotspot_label); + } state.icon = state.visible && state.value ? mEnable : mDisable; } @@ -122,10 +135,14 @@ protected String composeChangeAnnouncement() { } } - private static UsageTracker newUsageTracker(Context context) { - return new UsageTracker(context, Prefs.Key.HOTSPOT_TILE_LAST_USED, HotspotTile.class, - R.integer.days_to_show_hotspot_tile); - } + private BroadcastReceiver mTetherConnectStateChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final List clients = mConnectivityManager.getTetherConnectedSta(); + mNumConnectedClients = clients != null ? clients.size() : 0; + refreshState(); + } + }; private final class Callback implements HotspotController.Callback { @Override @@ -133,20 +150,4 @@ public void onHotspotChanged(boolean enabled) { refreshState(enabled); } }; - - /** - * This will catch broadcasts for changes in hotspot state so we can show - * the hotspot tile for a number of days after use. - */ - public static class APChangedReceiver extends BroadcastReceiver { - private UsageTracker mUsageTracker; - - @Override - public void onReceive(Context context, Intent intent) { - if (mUsageTracker == null) { - mUsageTracker = newUsageTracker(context); - } - mUsageTracker.trackUsage(); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java deleted file mode 100644 index 487bedbf814f6..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2015 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.tiles; - -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.database.ContentObserver; -import android.os.Handler; -import android.os.UserHandle; -import android.provider.Settings; - -import com.android.internal.logging.MetricsConstants; -import com.android.internal.util.ArrayUtils; -import com.android.systemui.R; -import com.android.systemui.qs.QSTile; - -import cyanogenmod.hardware.CMHardwareManager; -import cyanogenmod.providers.CMSettings; - -/** Quick settings tile: LiveDisplay mode switcher **/ -public class LiveDisplayTile extends QSTile { - - private static final Intent LIVEDISPLAY_SETTINGS = - new Intent("android.settings.LIVEDISPLAY_SETTINGS"); - - private final LiveDisplayObserver mObserver; - private final String[] mEntries; - private final String[] mDescriptionEntries; - private final String[] mAnnouncementEntries; - private final String[] mValues; - private final int[] mEntryIconRes; - - private boolean mListening; - - private static final int MODE_OUTDOOR = 3; - private static final int MODE_DAY = 4; - - private static final int OFF_TEMPERATURE = 6500; - - private int mDayTemperature; - - private final boolean mOutdoorModeAvailable; - private final int mDefaultDayTemperature; - - public LiveDisplayTile(Host host) { - super(host); - - Resources res = mContext.getResources(); - TypedArray typedArray = res.obtainTypedArray(R.array.live_display_drawables); - mEntryIconRes = new int[typedArray.length()]; - for (int i = 0; i < mEntryIconRes.length; i++) { - mEntryIconRes[i] = typedArray.getResourceId(i, 0); - } - typedArray.recycle(); - - mEntries = res.getStringArray(com.android.internal.R.array.live_display_entries); - mDescriptionEntries = res.getStringArray(R.array.live_display_description); - mAnnouncementEntries = res.getStringArray(R.array.live_display_announcement); - mValues = res.getStringArray(com.android.internal.R.array.live_display_values); - - mOutdoorModeAvailable = - CMHardwareManager.getInstance(mContext) - .isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT); - - mDefaultDayTemperature = mContext.getResources().getInteger( - com.android.internal.R.integer.config_dayColorTemperature); - loadDayTemperature(); - - mObserver = new LiveDisplayObserver(mHandler); - mObserver.startObserving(); - } - - @Override - protected LiveDisplayState newTileState() { - return new LiveDisplayState(); - } - - @Override - public void setListening(boolean listening) { - if (mListening == listening) - return; - mListening = listening; - if (listening) { - mObserver.startObserving(); - } else { - mObserver.endObserving(); - } - } - - @Override - protected void handleClick() { - changeToNextMode(); - } - - @Override - protected void handleLongClick() { - mHost.startActivityDismissingKeyguard(LIVEDISPLAY_SETTINGS); - } - - @Override - protected void handleUpdateState(LiveDisplayState state, Object arg) { - state.visible = true; - state.mode = arg == null ? getCurrentModeIndex() : (Integer) arg; - state.label = mEntries[state.mode]; - state.icon = ResourceIcon.get(mEntryIconRes[state.mode]); - state.contentDescription = mDescriptionEntries[state.mode]; - } - - @Override - public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; - } - - @Override - protected String composeChangeAnnouncement() { - return mAnnouncementEntries[getCurrentModeIndex()]; - } - - private int getCurrentModeIndex() { - return ArrayUtils.indexOf(mValues, - String.valueOf(CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_MODE, - 0, UserHandle.USER_CURRENT))); - } - - private void changeToNextMode() { - int next = getCurrentModeIndex() + 1; - - if (next >= mValues.length) { - next = 0; - } - - while (true) { - // Skip outdoor mode if it's unsupported, and skip the day setting - // if it's the same as the off setting - if ((!mOutdoorModeAvailable && - Integer.valueOf(mValues[next]) == MODE_OUTDOOR) || - (mDayTemperature == OFF_TEMPERATURE && - Integer.valueOf(mValues[next]) == MODE_DAY)) { - next++; - if (next >= mValues.length) { - next = 0; - } - } else { - break; - } - } - - CMSettings.System.putIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_MODE, - Integer.valueOf(mValues[next]), UserHandle.USER_CURRENT); - } - - private void loadDayTemperature() { - mDayTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_DAY, - mDefaultDayTemperature, - UserHandle.USER_CURRENT); - } - - private class LiveDisplayObserver extends ContentObserver { - public LiveDisplayObserver(Handler handler) { - super(handler); - } - - @Override - public void onChange(boolean selfChange) { - loadDayTemperature(); - refreshState(getCurrentModeIndex()); - } - - public void startObserving() { - mContext.getContentResolver().registerContentObserver( - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_MODE), - false, this, UserHandle.USER_ALL); - mContext.getContentResolver().registerContentObserver( - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY), - false, this, UserHandle.USER_ALL); - } - - public void endObserving() { - mContext.getContentResolver().unregisterContentObserver(this); - } - } - - public static class LiveDisplayState extends QSTile.State { - public int mode; - - @Override - public boolean copyTo(State other) { - final LiveDisplayState o = (LiveDisplayState) other; - final boolean changed = mode != o.mode; - return super.copyTo(other) || changed; - } - - @Override - protected StringBuilder toStringBuilder() { - final StringBuilder rt = super.toStringBuilder(); - rt.insert(rt.length() - 1, ",mode=" + mode); - return rt; - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java index 3b439d168f743..a147d30365668 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The CyanogenMod Project + * Copyright (C) 2015-2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,69 +16,58 @@ package com.android.systemui.qs.tiles; -import android.app.admin.DevicePolicyManager; -import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; - -import android.widget.Toast; -import com.android.internal.logging.MetricsLogger; +import android.os.UserHandle; import com.android.systemui.R; import com.android.systemui.SystemUIApplication; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSTile; import com.android.systemui.statusbar.policy.KeyguardMonitor; +import cyanogenmod.app.Profile; +import cyanogenmod.app.ProfileManager; +import cyanogenmod.providers.CMSettings; +import org.cyanogenmod.internal.logging.CMMetricsLogger; + public class LockscreenToggleTile extends QSTile implements KeyguardMonitor.Callback { - public static final String ACTION_APPLY_LOCKSCREEN_STATE = - "com.android.systemui.qs.tiles.action.APPLY_LOCKSCREEN_STATE"; - - private static final String KEY_ENABLED = "lockscreen_enabled"; - private static final Intent LOCK_SCREEN_SETTINGS = new Intent("android.settings.LOCK_SCREEN_SETTINGS"); - private KeyguardViewMediator mKeyguardViewMediator; private KeyguardMonitor mKeyguard; - private boolean mPersistedState; - private boolean mKeyguardBound; - private SharedPreferences mPrefs; - - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mKeyguardViewMediator != null) { - mKeyguardBound = mKeyguardViewMediator.isKeyguardBound(); - applyLockscreenState(); - refreshState(); - } - } - }; + private boolean mListening; + + private KeyguardViewMediator.LockscreenEnabledSettingsObserver mSettingsObserver; public LockscreenToggleTile(Host host) { super(host); - mPrefs = mContext.getSharedPreferences("quicksettings", Context.MODE_PRIVATE); mKeyguard = host.getKeyguardMonitor(); - mKeyguardViewMediator = - ((SystemUIApplication) - mContext.getApplicationContext()).getComponent(KeyguardViewMediator.class); - mPersistedState = getPersistedState(); - mKeyguardBound = mKeyguardViewMediator.isKeyguardBound(); - applyLockscreenState(); - mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_APPLY_LOCKSCREEN_STATE)); + mSettingsObserver = new KeyguardViewMediator.LockscreenEnabledSettingsObserver(mContext, + mUiHandler) { + + @Override + public void update() { + refreshState(); + } + }; + } @Override public void setListening(boolean listening) { + if (mListening == listening) { + return; + } + mListening = listening; if (listening) { + mSettingsObserver.observe(); mKeyguard.addCallback(this); + refreshState(); } else { + mSettingsObserver.unobserve(); mKeyguard.removeCallback(this); } } @@ -90,9 +79,9 @@ protected BooleanState newTileState() { @Override protected void handleClick() { - setPersistedState(!mPersistedState); - applyLockscreenState(); - refreshState(); + final boolean newState = !getState().value; + setPersistedState(newState); + refreshState(newState); } @Override @@ -102,30 +91,52 @@ protected void handleLongClick() { @Override protected void handleUpdateState(BooleanState state, Object arg) { - final boolean lockscreenEnforced = mKeyguardViewMediator.lockscreenEnforcedByDevicePolicy(); - final boolean lockscreenEnabled = lockscreenEnforced - || mPersistedState - || mKeyguardViewMediator.getKeyguardEnabledInternal(); - - state.value = lockscreenEnabled; - state.visible = !mKeyguard.isShowing() || !mKeyguard.isSecure(); - state.label = mContext.getString(lockscreenEnforced - ? R.string.quick_settings_lockscreen_label_enforced - : R.string.quick_settings_lockscreen_label); - if (lockscreenEnabled) { - state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_on); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_lock_screen_on); + KeyguardViewMediator mediator = ((SystemUIApplication) + mContext.getApplicationContext()).getComponent(KeyguardViewMediator.class); + + if (mediator == null) { + state.visible = false; + state.value = false; + state.enabled = false; } else { - state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_off); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_lock_screen_off); + final boolean lockscreenEnforced = mediator.lockscreenEnforcedByDevicePolicy(); + final boolean lockscreenEnabled = lockscreenEnforced || + arg != null ? (Boolean) arg : mediator.getKeyguardEnabledInternal(); + + state.visible = mediator.isKeyguardBound(); + + if (mediator.isProfileDisablingKeyguard()) { + state.value = false; + state.enabled = false; + state.label = mContext.getString( + R.string.quick_settings_lockscreen_label_locked_by_profile); + } else if (lockscreenEnforced) { + state.value = true; + state.enabled = false; + state.label = mContext.getString( + R.string.quick_settings_lockscreen_label_enforced); + } else { + state.value = lockscreenEnabled; + state.enabled = !mKeyguard.isShowing() || !mKeyguard.isSecure(); + + state.label = mContext.getString(R.string.quick_settings_lockscreen_label); + } + // update icon + if (lockscreenEnabled) { + state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_lock_screen_on); + } else { + state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_lock_screen_off); + } } } @Override public int getMetricsCategory() { - return MetricsLogger.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_LOCKSCREEN_TOGGLE; } @Override @@ -139,32 +150,14 @@ protected String composeChangeAnnouncement() { } } - @Override - protected void handleDestroy() { - super.handleDestroy(); - mContext.unregisterReceiver(mReceiver); - } - @Override public void onKeyguardChanged() { refreshState(); } - private void applyLockscreenState() { - if (!mKeyguardBound) { - // do nothing yet - return; - } - - mKeyguardViewMediator.setKeyguardEnabledInternal(mPersistedState); - } - - private boolean getPersistedState() { - return mPrefs.getBoolean(KEY_ENABLED, true); - } - private void setPersistedState(boolean enabled) { - mPrefs.edit().putBoolean(KEY_ENABLED, enabled).apply(); - mPersistedState = enabled; + CMSettings.Secure.putIntForUser(mContext.getContentResolver(), + CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED, + enabled ? 1 : 0, UserHandle.USER_CURRENT); } -} \ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java index a5be5351c8417..a5ffd23824acf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java @@ -22,12 +22,14 @@ import android.content.IntentFilter; import android.nfc.NfcAdapter; -import com.android.internal.logging.MetricsConstants; +import android.util.Log; import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; +import org.cyanogenmod.internal.util.QSUtils; public class NfcTile extends QSTile { - private NfcAdapter mNfcAdapter; + private boolean mListening; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -36,10 +38,11 @@ public void onReceive(Context context, Intent intent) { refreshState(); } }; + private final boolean mSupportsNfc; public NfcTile(Host host) { super(host); - mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext); + mSupportsNfc = QSUtils.deviceSupportsNfc(mContext); } @Override @@ -49,7 +52,9 @@ protected BooleanState newTileState() { @Override protected void handleClick() { - toggleState(); + boolean newState = !getState().value; + setState(newState); + refreshState(); } @Override @@ -57,23 +62,45 @@ protected void handleLongClick() { mHost.startActivityDismissingKeyguard(new Intent("android.settings.NFC_SETTINGS")); } - protected void toggleState() { - int state = getNfcState(); - switch (state) { - case NfcAdapter.STATE_TURNING_ON: - case NfcAdapter.STATE_ON: - mNfcAdapter.disable(); - break; - case NfcAdapter.STATE_TURNING_OFF: - case NfcAdapter.STATE_OFF: - mNfcAdapter.enable(); - break; + private void setState(boolean on) { + try { + NfcAdapter nfcAdapter = NfcAdapter.getNfcAdapter(mContext); + if (nfcAdapter == null) { + Log.e(TAG, "tried to set NFC state, but no NFC adapter was found"); + return; + } + if (on) { + nfcAdapter.enable(); + } else { + nfcAdapter.disable(); + } + } catch (UnsupportedOperationException e) { + // ignore + } + } + + private int getNfcAdapterState() { + try { + NfcAdapter nfcAdapter = NfcAdapter.getNfcAdapter(mContext); + if (nfcAdapter == null) { + Log.e(TAG, "tried to get NFC state, but no NFC adapter was found"); + return NfcAdapter.STATE_OFF; + } + return nfcAdapter.getAdapterState(); + } catch (UnsupportedOperationException e) { + // ignore + return NfcAdapter.STATE_OFF; } } - private boolean isEnabled() { - int state = getNfcState(); - switch (state) { + /** + * Helper method to encapsulate intermediate states (turning off/on) to help determine whether + * the adapter will be on or off. + * @param nfcState The current NFC adapter state. + * @return boolean representing what state the adapter is/will be in + */ + private static boolean isEnabled(int nfcState) { + switch (nfcState) { case NfcAdapter.STATE_TURNING_ON: case NfcAdapter.STATE_ON: return true; @@ -84,26 +111,36 @@ private boolean isEnabled() { } } - private int getNfcState() { - return mNfcAdapter.getAdapterState(); + /** + * Helper method to determine intermediate states + * @param nfcState The current NFC adapter state. + * @return boolean representing if the adapter is in an intermediate state + */ + private static boolean isEnablingDisabling(int nfcState) { + switch (nfcState) { + case NfcAdapter.STATE_TURNING_OFF: + case NfcAdapter.STATE_TURNING_ON: + return true; + default: + return false; + } } @Override protected void handleUpdateState(BooleanState state, Object arg) { - if (mNfcAdapter == null) { - mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext); - } - state.visible = mNfcAdapter != null; - state.value = mNfcAdapter != null && isEnabled(); + state.visible = mSupportsNfc; + final int nfcState = getNfcAdapterState(); + state.value = mSupportsNfc && isEnabled(nfcState); + state.enabled = mSupportsNfc && !isEnablingDisabling(nfcState); + state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_nfc_on : R.drawable.ic_qs_nfc_off); - state.label = mContext.getString(state.value - ? R.string.quick_settings_nfc : R.string.quick_settings_nfc_off); + state.label = mContext.getString(R.string.quick_settings_nfc_label); } @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_NFC; } @Override @@ -111,12 +148,9 @@ public void setListening(boolean listening) { if (mListening == listening) return; mListening = listening; if (listening) { - if (mNfcAdapter == null) { - mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext); - refreshState(); - } mContext.registerReceiver(mReceiver, new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED)); + refreshState(); } else { mContext.unregisterReceiver(mReceiver); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java index 0392efc3f2738..486368345245e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/PerfProfileTile.java @@ -29,11 +29,11 @@ import android.widget.ArrayAdapter; import android.widget.ListView; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSDetailItemsList; import com.android.systemui.qs.QSTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; import org.cyanogenmod.internal.util.QSUtils; import cyanogenmod.app.StatusBarPanelCustomTile; @@ -48,6 +48,7 @@ public class PerfProfileTile extends QSTile { private final String[] mDescriptionEntries; private final String[] mAnnouncementEntries; private final int[] mPerfProfileValues; + private final int mNumPerfProfiles; private final Icon mIcon; private final PowerManager mPm; @@ -61,16 +62,36 @@ public PerfProfileTile(Host host) { mObserver = new PerformanceProfileObserver(mHandler); mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mPerformanceManager = PerformanceManager.getInstance(mContext); + mNumPerfProfiles = mPerformanceManager.getNumberOfProfiles(); - Resources res = mContext.getResources(); - - mPerfProfileValues = res.getIntArray(org.cyanogenmod.platform.internal.R.array.perf_profile_values); - - mEntries = res.getStringArray(org.cyanogenmod.platform.internal.R.array.perf_profile_entries); - mDescriptionEntries = res.getStringArray(R.array.perf_profile_description); - mAnnouncementEntries = res.getStringArray(R.array.perf_profile_announcement); + mPerfProfileValues = new int[mNumPerfProfiles]; + mEntries = new String[mNumPerfProfiles]; + mDescriptionEntries = new String[mNumPerfProfiles]; + mAnnouncementEntries = new String[mNumPerfProfiles]; mIcon = ResourceIcon.get(R.drawable.ic_qs_perf_profile); + + // Filter out unsupported profiles + Resources res = mContext.getResources(); + final int[] perfProfileValues = res.getIntArray( + org.cyanogenmod.platform.internal.R.array.perf_profile_values); + final String[] entries = res.getStringArray( + org.cyanogenmod.platform.internal.R.array.perf_profile_entries); + final String[] descriptionEntries = res.getStringArray( + R.array.perf_profile_description); + final String[] announcementEntries = res.getStringArray( + R.array.perf_profile_announcement); + int i = 0; + + for (int j = 0; j < perfProfileValues.length; j++) { + if (perfProfileValues[j] < mNumPerfProfiles) { + mPerfProfileValues[i] = perfProfileValues[j]; + mEntries[i] = entries[j]; + mDescriptionEntries[i] = descriptionEntries[j]; + mAnnouncementEntries[i] = announcementEntries[j]; + i++; + } + } } @Override @@ -104,7 +125,7 @@ protected void handleUpdateState(ProfileState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_PERF_PROFILE; } @Override @@ -135,7 +156,7 @@ public void onChange(boolean selfChange) { public void startObserving() { mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(CMSettings.Secure.PERFORMANCE_PROFILE), + CMSettings.Secure.getUriFor(CMSettings.Secure.PERFORMANCE_PROFILE), false, this); } @@ -212,7 +233,7 @@ public void setToggleState(boolean state) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_PERF_PROFILE_DETAIL; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java index 42aa122ad8d65..6f65f6c4ee5eb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java @@ -32,7 +32,6 @@ import android.widget.CheckedTextView; import android.widget.ListView; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSDetailItemsList; import com.android.systemui.qs.QSTile; @@ -42,12 +41,13 @@ import cyanogenmod.app.ProfileManager; import cyanogenmod.app.StatusBarPanelCustomTile; import cyanogenmod.providers.CMSettings; +import org.cyanogenmod.internal.logging.CMMetricsLogger; import java.util.ArrayList; import java.util.List; import java.util.UUID; -public class ProfilesTile extends QSTile { +public class ProfilesTile extends QSTile implements KeyguardMonitor.Callback { private static final Intent PROFILES_SETTINGS = new Intent("android.settings.PROFILES_SETTINGS"); @@ -57,11 +57,19 @@ public class ProfilesTile extends QSTile { private ProfileManager mProfileManager; private QSDetailItemsList mDetails; private ProfileAdapter mAdapter; + private KeyguardMonitor mKeyguardMonitor; public ProfilesTile(Host host) { super(host); mProfileManager = ProfileManager.getInstance(mContext); mObserver = new ProfilesObserver(mHandler); + mKeyguardMonitor = host.getKeyguardMonitor(); + mKeyguardMonitor.addCallback(this); + } + + @Override + protected void handleDestroy() { + mKeyguardMonitor.removeCallback(this); } @Override @@ -82,6 +90,10 @@ protected void handleLongClick() { @Override protected void handleUpdateState(State state, Object arg) { state.visible = true; + + + + state.enabled = !mKeyguardMonitor.isShowing() || !mKeyguardMonitor.isSecure(); if (profilesEnabled()) { state.icon = ResourceIcon.get(R.drawable.ic_qs_profiles_on); state.label = mProfileManager.getActiveProfile().getName(); @@ -112,7 +124,7 @@ private boolean profilesEnabled() { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_PROFILES; } @Override @@ -125,6 +137,7 @@ public void setListening(boolean listening) { filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_SELECTED); filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_UPDATED); mContext.registerReceiver(mReceiver, filter); + refreshState(); } else { mObserver.endObserving(); mContext.unregisterReceiver(mReceiver); @@ -136,6 +149,11 @@ public DetailAdapter getDetailAdapter() { return new ProfileDetailAdapter(); } + @Override + public void onKeyguardChanged() { + refreshState(); + } + private class ProfileAdapter extends ArrayAdapter { public ProfileAdapter(Context context, List profiles) { super(context, android.R.layout.simple_list_item_single_choice, profiles); @@ -182,7 +200,7 @@ public Boolean getToggleState() { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_PROFILES_DETAIL; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java index 2399f5dfc5521..e933787f53966 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java @@ -31,11 +31,11 @@ import android.widget.ArrayAdapter; import android.widget.ListView; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSDetailItemsList; import com.android.systemui.qs.QSTile; import cyanogenmod.app.StatusBarPanelCustomTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; import java.util.ArrayList; import java.util.Arrays; @@ -61,9 +61,6 @@ public class ScreenTimeoutTile extends QSTile { new AnimationIcon(R.drawable.ic_qs_screen_timeout_long_reverse_avd); private String[] mEntries, mValues; - private boolean mShowingDetail; - ArrayList mAnimationList - = new ArrayList(); public ScreenTimeoutTile(Host host) { super(host); @@ -127,8 +124,6 @@ protected TimeoutState newTileState() { @Override protected void handleClick() { if (mEntries.length > 0) { - mShowingDetail = true; - mAnimationList.clear(); showDetail(true); } } @@ -190,10 +185,6 @@ public static Bucket getBucket(int value) { } @Override protected void handleUpdateState(final TimeoutState state, Object arg) { - if (mAnimationList.isEmpty() && mShowingDetail && arg == null) { - return; - } - int newTimeout = getScreenTimeout(); AnimationIcon d = null; @@ -247,7 +238,7 @@ protected void handleUpdateState(final TimeoutState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_SCREEN_TIME_OUT; } @Override @@ -309,7 +300,7 @@ public void setToggleState(boolean state) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_SCREEN_TIME_OUT_DETAIL; } @Override @@ -334,7 +325,6 @@ public void onViewDetachedFromWindow(View v) { mUiHandler.postDelayed(new Runnable() { @Override public void run() { - mShowingDetail = false; refreshState(true); } }, 100); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java index c37e0d525257d..7ffebc774c266 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SyncTile.java @@ -20,9 +20,9 @@ import android.content.Intent; import android.content.SyncStatusObserver; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; /** Quick settings tile: Sync **/ public class SyncTile extends QSTile { @@ -70,7 +70,7 @@ protected void handleUpdateState(BooleanState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_SYNC; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java index b3b013cf24fc3..12741956f69e4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UsbTetherTile.java @@ -24,9 +24,9 @@ import android.provider.Settings; import android.net.ConnectivityManager; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; /** * USB Tether quick settings tile @@ -114,6 +114,6 @@ protected void handleUpdateState(BooleanState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_USB_TETHER; } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java index ff254f0f8ad4f..ae29f1624ed35 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/VolumeTile.java @@ -21,9 +21,9 @@ import android.media.AudioManager; import android.provider.Settings; -import com.android.internal.logging.MetricsConstants; import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import org.cyanogenmod.internal.logging.CMMetricsLogger; public class VolumeTile extends QSTile { @@ -53,7 +53,7 @@ protected void handleUpdateState(BooleanState state, Object arg) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.TILE_VOLUME; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index b25390ee74176..abc9acd836dd1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.os.Looper; import android.provider.Settings; import android.util.Log; import android.view.View; @@ -131,16 +132,28 @@ protected void handleLongClick() { protected void handleUpdateState(SignalState state, Object arg) { state.visible = true; if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg); - CallbackInfo cb = (CallbackInfo) arg; - if (cb == null) { + final CallbackInfo cb; + if (arg == null) { cb = mSignalCallback.mInfo; + } else { + cb = (CallbackInfo) arg; } boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null); boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null); boolean enabledChanging = state.enabled != cb.enabled; if (enabledChanging) { - mDetailAdapter.setItemsVisible(cb.enabled); + if (Looper.myLooper() == Looper.getMainLooper()) { + // on main thread, bypass the handler + mDetailAdapter.setItemsVisible(cb.enabled); + } else { + mUiHandler.post(new Runnable() { + @Override + public void run() { + mDetailAdapter.setItemsVisible(cb.enabled); + } + }); + } fireToggleStateChanged(cb.enabled); } state.enabled = cb.enabled; diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index f1550a09b2e2c..b3a3dfd547b9e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.SystemClock; import android.os.UserHandle; +import android.provider.Settings; import android.util.MutableBoolean; import android.view.Display; import android.view.LayoutInflater; @@ -45,6 +46,7 @@ import com.android.systemui.RecentsComponent; import com.android.systemui.SystemUI; import com.android.systemui.SystemUIApplication; +import com.android.systemui.cm.UserContentObserver; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.model.RecentsTaskLoadPlan; @@ -60,6 +62,8 @@ import java.util.ArrayList; +import cyanogenmod.providers.CMSettings; + /** * Annotation for a method that is only called from the primary user's SystemUI process and will be * proxied to the current user. @@ -160,6 +164,35 @@ public void onReceive(Context context, Intent intent) { } } + class RecentsSettingsObserver extends UserContentObserver { + + public RecentsSettingsObserver(Handler handler) { + super(handler); + } + + @Override + protected void observe() { + super.observe(); + mContext.getContentResolver().registerContentObserver( + CMSettings.System.getUriFor(CMSettings.System.RECENTS_SHOW_SEARCH_BAR), + false, this); + update(); + } + + @Override + protected void unobserve() { + super.unobserve(); + mContext.getContentResolver().unregisterContentObserver(this); + } + + @Override + protected void update() { + if (mConfig.updateShowSearch(mContext)) { + reloadHeaderBarLayout(); + } + } + } + static RecentsComponent.Callbacks sRecentsComponentCallbacks; static RecentsTaskLoadPlan sInstanceLoadPlan; static Recents sInstance; @@ -170,6 +203,7 @@ public void onReceive(Context context, Intent intent) { TaskStackListenerImpl mTaskStackListener; RecentsOwnerEventProxyReceiver mProxyBroadcastReceiver; RecentsAppWidgetHost mAppWidgetHost; + RecentsSettingsObserver mSettingsObserver; boolean mBootCompleted; boolean mStartAnimationTriggered; boolean mCanReuseTaskStackViews = true; @@ -258,6 +292,9 @@ public void start() { // Load the header bar layout reloadHeaderBarLayout(); + mSettingsObserver = new RecentsSettingsObserver(mHandler); + mSettingsObserver.observe(); + // When we start, preload the data associated with the previous recent tasks. // We can use a new plan since the caches will be the same. RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); @@ -280,6 +317,12 @@ public void onBootCompleted() { @ProxyFromPrimaryToCurrentUser @Override public void showRecents(boolean triggeredFromAltTab, View statusBarView) { + // Ensure the device has been provisioned before allowing the user to interact with + // recents + if (!isDeviceProvisioned()) { + return; + } + if (mSystemServicesProxy.isForegroundUserOwner()) { showRecentsInternal(triggeredFromAltTab); } else { @@ -304,6 +347,12 @@ void showRecentsInternal(boolean triggeredFromAltTab) { @ProxyFromPrimaryToCurrentUser @Override public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { + // Ensure the device has been provisioned before allowing the user to interact with + // recents + if (!isDeviceProvisioned()) { + return; + } + if (mSystemServicesProxy.isForegroundUserOwner()) { hideRecentsInternal(triggeredFromAltTab, triggeredFromHomeKey); } else { @@ -330,6 +379,12 @@ void hideRecentsInternal(boolean triggeredFromAltTab, boolean triggeredFromHomeK @ProxyFromPrimaryToCurrentUser @Override public void toggleRecents(Display display, int layoutDirection, View statusBarView) { + // Ensure the device has been provisioned before allowing the user to interact with + // recents + if (!isDeviceProvisioned()) { + return; + } + if (mSystemServicesProxy.isForegroundUserOwner()) { toggleRecentsInternal(); } else { @@ -353,6 +408,12 @@ void toggleRecentsInternal() { @ProxyFromPrimaryToCurrentUser @Override public void preloadRecents() { + // Ensure the device has been provisioned before allowing the user to interact with + // recents + if (!isDeviceProvisioned()) { + return; + } + if (mSystemServicesProxy.isForegroundUserOwner()) { preloadRecentsInternal(); } else { @@ -469,6 +530,12 @@ void showRelativeAffiliatedTask(boolean showNextTask) { @Override public void showNextAffiliatedTask() { + // Ensure the device has been provisioned before allowing the user to interact with + // recents + if (!isDeviceProvisioned()) { + return; + } + // Keep track of when the affiliated task is triggered MetricsLogger.count(mContext, "overview_affiliated_task_next", 1); showRelativeAffiliatedTask(true); @@ -476,6 +543,12 @@ public void showNextAffiliatedTask() { @Override public void showPrevAffiliatedTask() { + // Ensure the device has been provisioned before allowing the user to interact with + // recents + if (!isDeviceProvisioned()) { + return; + } + // Keep track of when the affiliated task is triggered MetricsLogger.count(mContext, "overview_affiliated_task_prev", 1); showRelativeAffiliatedTask(false); @@ -512,7 +585,8 @@ void reloadHeaderBarLayout() { // Try and pre-emptively bind the search widget on startup to ensure that we // have the right thumbnail bounds to animate to. // Note: We have to reload the widget id before we get the task stack bounds below - if (mSystemServicesProxy.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) { + if (mConfig.searchBarEnabled && + mSystemServicesProxy.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) { mConfig.getSearchBarBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight, searchBarBounds); } @@ -887,6 +961,14 @@ static void onStartScreenPinning(Context context) { } } + /** + * @return whether this device is provisioned. + */ + private boolean isDeviceProvisioned() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 0) != 0; + } + /** * Returns the preloaded load plan and invalidates it. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 03869af68e112..9e08599ab5e13 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -25,11 +25,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; import android.os.Bundle; import android.os.SystemClock; import android.os.UserHandle; -import android.provider.Settings; import android.view.KeyEvent; import android.view.View; import android.view.ViewStub; @@ -38,7 +36,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.systemui.Prefs; import com.android.systemui.R; -import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.DebugTrigger; import com.android.systemui.recents.misc.ReferenceCountedTrigger; @@ -88,6 +85,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // Runnable to be executed after we paused ourselves Runnable mAfterPauseRunnable; + private ReferenceCountedTrigger mExitTrigger; + /** * A common Runnable to finish Recents either by calling finish() (with a custom animation) or * launching Home with some ActivityOptions. Generally we always launch home when we exit @@ -98,6 +97,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView class FinishRecentsRunnable implements Runnable { Intent mLaunchIntent; ActivityOptions mLaunchOpts; + boolean mAbort = false; /** * Creates a finish runnable that starts the specified intent, using the given @@ -108,8 +108,15 @@ public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) { mLaunchOpts = opts; } + public void setAbort(boolean run) { + this.mAbort = run; + } + @Override public void run() { + if (mAbort) { + return; + } // Finish Recents if (mLaunchIntent != null) { try { @@ -133,7 +140,7 @@ public void run() { /** * Broadcast receiver to handle messages from AlternateRecentsComponent. */ - private final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() { + final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -163,7 +170,7 @@ public void onReceive(Context context, Intent intent) { /** * Broadcast receiver to handle messages from the system */ - private final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() { + final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -182,7 +189,7 @@ public void onReceive(Context context, Intent intent) { /** * A custom debug trigger to listen for a debug key chord. */ - private final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() { + final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() { @Override public void run() { onDebugModeTriggered(); @@ -211,9 +218,7 @@ void updateRecentsTasks() { ArrayList stacks = plan.getAllTaskStacks(); mConfig.launchedWithNoRecentTasks = !plan.hasTasks(); - if (!mConfig.launchedWithNoRecentTasks) { - mRecentsView.setTaskStacks(stacks); - } + mRecentsView.setTaskStacks(stacks); // Create the home intent runnable Intent homeIntent = new Intent(Intent.ACTION_MAIN, null); @@ -222,10 +227,8 @@ void updateRecentsTasks() { Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, ActivityOptions.makeCustomAnimation(this, - mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_enter : - R.anim.recents_to_launcher_enter, - mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_exit : - R.anim.recents_to_launcher_exit)); + R.anim.recents_to_search_launcher_enter, + R.anim.recents_to_search_launcher_exit)); // Mark the task that is the launch target int taskStackCount = stacks.size(); @@ -252,33 +255,27 @@ void updateRecentsTasks() { mEmptyView = mEmptyViewStub.inflate(); } mEmptyView.setVisibility(View.VISIBLE); + mEmptyView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dismissRecentsToHome(true); + } + }); mRecentsView.setSearchBarVisibility(View.GONE); } else { if (mEmptyView != null) { mEmptyView.setVisibility(View.GONE); + mEmptyView.setOnClickListener(null); } - boolean showSearchBar = CMSettings.System.getInt(getContentResolver(), - CMSettings.System.RECENTS_SHOW_SEARCH_BAR, 1) == 1; - - if (mRecentsView.hasValidSearchBar()) { - if (showSearchBar) { + if (!mConfig.searchBarEnabled) { + mRecentsView.setSearchBarVisibility(View.GONE); + } else { + if (mRecentsView.hasValidSearchBar()) { mRecentsView.setSearchBarVisibility(View.VISIBLE); } else { - mRecentsView.setSearchBarVisibility(View.GONE); - } - } else { - if (showSearchBar) { refreshSearchWidgetView(); } } - - // Update search bar space height - if (showSearchBar) { - mConfig.searchBarSpaceHeightPx = getResources().getDimensionPixelSize( - R.dimen.recents_search_bar_space_height); - } else { - mConfig.searchBarSpaceHeightPx = 0; - } } // Animate the SystemUI scrims into view @@ -330,13 +327,26 @@ boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) { return false; } + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (!hasFocus && mExitTrigger != null && mExitTrigger.getCount() > 0) { + // we are animating recents out and the window has lost focus during the + // animation. we need to stop everything we're doing now and get out + // without any animations (since we were already animating) + mFinishLaunchHomeRunnable.setAbort(true); + finish(); + overridePendingTransition(0, 0); + } + } + /** Dismisses Recents directly to Home. */ void dismissRecentsToHomeRaw(boolean animated) { if (animated) { - ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this, + mExitTrigger = new ReferenceCountedTrigger(this, null, mFinishLaunchHomeRunnable, null); mRecentsView.startExitToHomeAnimation( - new ViewAnimation.TaskViewExitContext(exitTrigger)); + new ViewAnimation.TaskViewExitContext(mExitTrigger)); } else { mFinishLaunchHomeRunnable.run(); } @@ -451,6 +461,14 @@ protected void onStart() { } } + @Override + protected void onResume() { + if (mConfig.searchBarEnabled && mConfig.launchedFromHome) { + overridePendingTransition(0, 0); + } + super.onResume(); + } + @Override protected void onPause() { super.onPause(); @@ -463,6 +481,9 @@ protected void onPause() { @Override protected void onStop() { super.onStop(); + + mExitTrigger = null; + MetricsLogger.hidden(this, MetricsLogger.OVERVIEW_ACTIVITY); RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); SystemServicesProxy ssp = loader.getSystemServicesProxy(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 41d52b87fbd35..d7e8b9940d5a2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -31,6 +31,7 @@ import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; +import cyanogenmod.providers.CMSettings; /** A static Recents configuration for the current context * NOTE: We should not hold any references to a Context from a static instance */ @@ -73,6 +74,7 @@ public class RecentsConfiguration { public int maxNumTasksToLoad; /** Search bar */ + public boolean searchBarEnabled = true; public int searchBarSpaceHeightPx; /** Task stack */ @@ -279,6 +281,13 @@ void update(Context context) { svelteLevel = res.getInteger(R.integer.recents_svelte_level); } + public boolean updateShowSearch(Context context) { + boolean wasEnabled = searchBarEnabled; + searchBarEnabled = CMSettings.System.getInt(context.getContentResolver(), + CMSettings.System.RECENTS_SHOW_SEARCH_BAR, 1) == 1; + return wasEnabled != searchBarEnabled; + } + /** Updates the system insets */ public void updateSystemInsets(Rect insets) { systemInsets.set(insets); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 947c19cadce5c..2f11c563614ff 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -31,6 +31,7 @@ import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; +import android.util.EventLog; import android.view.LayoutInflater; import android.view.View; import android.view.WindowInsets; @@ -48,6 +49,8 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; +import com.android.systemui.EventLogTags; + import java.util.ArrayList; import java.util.List; @@ -267,6 +270,8 @@ public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) { stackView.startEnterRecentsAnimation(ctx); } ctx.postAnimationTrigger.decrement(); + + EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_EVENT, 1 /* opened */); } /** Requests all task stacks to start their exit-recents animation */ @@ -323,7 +328,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Get the search bar bounds and measure the search bar layout Rect searchBarSpaceBounds = new Rect(); - if (mSearchBar != null) { + if (mSearchBar != null && mConfig.searchBarEnabled) { mConfig.getSearchBarBounds(width, height, mConfig.systemInsets.top, searchBarSpaceBounds); mSearchBar.measure( MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY), @@ -360,7 +365,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // Get the search bar bounds so that we lay it out - if (mSearchBar != null) { + if (mSearchBar != null && mConfig.searchBarEnabled) { Rect searchBarSpaceBounds = new Rect(); mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), mConfig.systemInsets.top, searchBarSpaceBounds); @@ -620,6 +625,8 @@ public void run() { launchRunnable.run(); } } + + EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_EVENT, 3 /* chose task */); } @Override @@ -659,6 +666,7 @@ public void onAllTaskViewsDismissed(ArrayList removedTasks) { // Keep track of all-deletions MetricsLogger.count(getContext(), "overview_task_all_dismissed", 1); + EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_EVENT, 4 /* closed all */); } /** Final callback after Recents is finally hidden. */ @@ -670,6 +678,7 @@ public void onRecentsHidden() { TaskStackView stackView = stackViews.get(i); stackView.onRecentsHidden(); } + EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_EVENT, 2 /* closed */); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 43b9a3e1b20d4..454222c77f406 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -1018,8 +1018,9 @@ public void startLaunchTaskAnimation(TaskView tv, Runnable r, boolean lockToTask t.setClipViewInStack(false); t.startLaunchTaskAnimation(r, true, true, lockToTask); } else { - boolean occludesLaunchTarget = launchTargetTask.group.isTaskAboveTask(t.getTask(), - launchTargetTask); + boolean occludesLaunchTarget = launchTargetTask != null && + launchTargetTask.group != null && + launchTargetTask.group.isTaskAboveTask(t.getTask(), launchTargetTask); t.startLaunchTaskAnimation(null, false, occludesLaunchTarget, lockToTask); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 5213857ffaf5b..e958ee180b136 100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -45,6 +45,7 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; +import android.media.session.MediaController; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -117,6 +118,8 @@ import java.util.List; import java.util.Locale; +import cyanogenmod.providers.CMSettings; + import static com.android.keyguard.KeyguardHostView.OnDismissAction; public abstract class BaseStatusBar extends SystemUI implements @@ -154,6 +157,8 @@ public abstract class BaseStatusBar extends SystemUI implements private static final String BANNER_ACTION_SETUP = "com.android.systemui.statusbar.banner_action_setup"; + protected static final int SYSTEM_UI_VISIBILITY_MASK = 0xffffffff; + private static final Uri SPAM_MESSAGE_URI = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(SpamMessageProvider.AUTHORITY) @@ -221,6 +226,8 @@ public abstract class BaseStatusBar extends SystemUI implements protected WindowManager mWindowManager; protected IWindowManager mWindowManagerService; + private NotificationManager mNoMan; + protected abstract void refreshLayout(int layoutDirection); protected Display mDisplay; @@ -251,6 +258,10 @@ public abstract class BaseStatusBar extends SystemUI implements protected AssistManager mAssistManager; + // last theme that was applied in order to detect theme change (as opposed + // to some other configuration change). + protected ThemeConfig mCurrentTheme; + @Override // NotificationData.Environment public boolean isDeviceProvisioned() { return mDeviceProvisioned; @@ -259,8 +270,8 @@ public boolean isDeviceProvisioned() { protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { - final boolean provisioned = 0 != Settings.Global.getInt( - mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0); + final boolean provisioned = 0 != CMSettings.Secure.getInt( + mContext.getContentResolver(), CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 0); if (provisioned != mDeviceProvisioned) { mDeviceProvisioned = provisioned; updateNotifications(); @@ -423,9 +434,7 @@ public void onReceive(Context context, Intent intent) { } } } else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) { - NotificationManager noMan = (NotificationManager) - mContext.getSystemService(Context.NOTIFICATION_SERVICE); - noMan.cancel(R.id.notification_hidden); + mNoMan.cancel(R.id.notification_hidden); Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); @@ -554,6 +563,9 @@ private void updateCurrentProfilesCache() { public void start() { mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); + + mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); + mDisplay = mWindowManager.getDefaultDisplay(); mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService( Context.DEVICE_POLICY_SERVICE); @@ -570,8 +582,8 @@ public void start() { mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true, - mSettingsObserver); + CMSettings.Secure.getUriFor(CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED), false, + mSettingsObserver, UserHandle.USER_ALL); mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false, mSettingsObserver); @@ -620,7 +632,7 @@ public void start() { mSettingsObserver.onChange(false); // set up disable(switches[0], switches[6], false /* animate */); - setSystemUiVisibility(switches[1], 0xffffffff); + setSystemUiVisibility(switches[1], SYSTEM_UI_VISIBILITY_MASK); topAppWindowChanged(switches[2] != 0); // StatusBarManagerService has a back up of IME token and it's restored here. setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0); @@ -719,9 +731,7 @@ protected void notifyUserAboutHiddenNotifications() { mContext.getString(R.string.hidden_notifications_setup), setupIntent); - NotificationManager noMan = - (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - noMan.notify(R.id.notification_hidden, note.build()); + mNoMan.notify(R.id.notification_hidden, note.build()); } } @@ -765,6 +775,10 @@ public String getCurrentMediaNotificationKey() { return null; } + protected MediaController getCurrentMediaController() { + return null; + } + @Override public NotificationGroupManager getGroupManager() { return mGroupManager; @@ -943,7 +957,9 @@ public void onClick(View v) { } }); - filterButton.setVisibility(View.VISIBLE); + Notification notification = sbn.getNotification(); + filterButton.setVisibility(SpamFilter.hasFilterableContent(notification) + ? View.VISIBLE : View.GONE); filterButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { AsyncTask.execute(new Runnable() { @@ -1010,6 +1026,10 @@ public boolean onLongPress(View v, int x, int y) { } ExpandableNotificationRow row = (ExpandableNotificationRow) v; + if (v instanceof MediaExpandableNotificationRow + && !((MediaExpandableNotificationRow) v).inflateGuts()) { + return false; + } bindGuts(row); // Assume we are a status_bar_notification_row @@ -1276,6 +1296,20 @@ protected void workAroundBadLayerDrawableOpacity(View v) { } protected boolean inflateViews(Entry entry, ViewGroup parent) { + final StatusBarNotification sbn = entry.notification; + String themePackageName = mCurrentTheme != null + ? mCurrentTheme.getOverlayPkgNameForApp(sbn.getPackageName()) : null; + boolean inflated = inflateViews(entry, parent, true); + if (!inflated && themePackageName != null + && !ThemeConfig.SYSTEM_DEFAULT.equals(themePackageName)) { + Log.w(TAG, "Couldn't expand themed RemoteViews, trying unthemed for: " + sbn); + inflated = inflateViews(entry, mStackScroller, false); + } + + return inflated; + } + + protected boolean inflateViews(Entry entry, ViewGroup parent, boolean isThemeable) { PackageManager pmUser = getPackageManagerForUser( entry.notification.getUser().getIdentifier()); @@ -1316,8 +1350,19 @@ protected boolean inflateViews(Entry entry, ViewGroup parent) { // create the row view LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); - row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row, - parent, false); + + // cannot use isMediaNotification() + if (sbn.getNotification().category != null + && sbn.getNotification().category.equals(Notification.CATEGORY_TRANSPORT)) { + row = (MediaExpandableNotificationRow) inflater.inflate( + R.layout.status_bar_notification_row_media, parent, false); + ((MediaExpandableNotificationRow)row).setMediaController( + getCurrentMediaController()); + } else { + row = (ExpandableNotificationRow) inflater.inflate( + R.layout.status_bar_notification_row, + parent, false); + } row.setExpansionLogger(this, entry.notification.getKey()); row.setGroupManager(mGroupManager); } @@ -1341,28 +1386,52 @@ protected boolean inflateViews(Entry entry, ViewGroup parent) { View contentViewLocal = null; View bigContentViewLocal = null; View headsUpContentViewLocal = null; - final ThemeConfig themeConfig = mContext.getResources().getConfiguration().themeConfig; - String themePackageName = themeConfig != null ? - themeConfig.getOverlayPkgNameForApp(mContext.getPackageName()) : null; + String themePackageName = (isThemeable && mCurrentTheme != null) + ? mCurrentTheme.getOverlayPkgNameForApp(sbn.getPackageName()) + : ThemeConfig.SYSTEM_DEFAULT; + String statusBarThemePackageName = (isThemeable && mCurrentTheme != null) + ? mCurrentTheme.getOverlayForStatusBar() + : ThemeConfig.SYSTEM_DEFAULT; + try { contentViewLocal = contentView.apply( sbn.getPackageContext(mContext), contentContainer, mOnClickHandler, - themePackageName); + statusBarThemePackageName); + + final int platformTemplateRootViewId = + com.android.internal.R.id.status_bar_latest_event_content; + final String inflationThemePackageName; + if (themePackageName != null + && !TextUtils.equals(themePackageName, statusBarThemePackageName) + && contentViewLocal.getId() != platformTemplateRootViewId) { + // This notification uses custom RemoteViews, and its app uses a different + // theme than the status bar. Re-inflate the views using the app's theme, + // as the RemoteViews likely will contain resources of the app, not the platform + inflationThemePackageName = themePackageName; + contentViewLocal = contentView.apply( + sbn.getPackageContext(mContext), + contentContainer, + mOnClickHandler, + inflationThemePackageName); + } else { + inflationThemePackageName = statusBarThemePackageName; + } + if (bigContentView != null) { bigContentViewLocal = bigContentView.apply( sbn.getPackageContext(mContext), contentContainer, mOnClickHandler, - themePackageName); + inflationThemePackageName); } if (headsUpContentView != null) { headsUpContentViewLocal = headsUpContentView.apply( sbn.getPackageContext(mContext), contentContainer, mOnClickHandler, - themePackageName); + inflationThemePackageName); } } catch (RuntimeException e) { @@ -1413,8 +1482,10 @@ protected boolean inflateViews(Entry entry, ViewGroup parent) { } if (publicViewLocal == null) { + final Context layoutContext = isThemeable ? mContext + : maybeGetThemedContext(mContext, ThemeConfig.SYSTEM_DEFAULT); // Add a basic notification template - publicViewLocal = LayoutInflater.from(mContext).inflate( + publicViewLocal = LayoutInflater.from(layoutContext).inflate( R.layout.notification_public_default, contentContainerPublic, false); publicViewLocal.setIsRootNamespace(true); @@ -1427,49 +1498,12 @@ protected boolean inflateViews(Entry entry, ViewGroup parent) { title.setText(entry.notification.getPackageName()); } - final ImageView icon = (ImageView) publicViewLocal.findViewById(R.id.icon); - final ImageView profileBadge = (ImageView) publicViewLocal.findViewById( - R.id.profile_badge_line3); - - final StatusBarIcon ic = new StatusBarIcon( - entry.notification.getUser(), - entry.notification.getPackageName(), - entry.notification.getNotification().getSmallIcon(), - entry.notification.getNotification().iconLevel, - entry.notification.getNotification().number, - entry.notification.getNotification().tickerText); - - Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic); - icon.setImageDrawable(iconDrawable); - if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP - || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) { - icon.setBackgroundResource( - com.android.internal.R.drawable.notification_icon_legacy_bg); - int padding = mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.notification_large_icon_circle_padding); - icon.setPadding(padding, padding, padding, padding); - if (sbn.getNotification().color != Notification.COLOR_DEFAULT) { - icon.getBackground().setColorFilter( - sbn.getNotification().color, PorterDuff.Mode.SRC_ATOP); - } - } - - if (profileBadge != null) { - Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity( - entry.notification.getUser(), 0); - if (profileDrawable != null) { - profileBadge.setImageDrawable(profileDrawable); - profileBadge.setVisibility(View.VISIBLE); - } else { - profileBadge.setVisibility(View.GONE); - } - } + updatePublicViewProperties(publicViewLocal, entry); final View privateTime = contentViewLocal.findViewById(com.android.internal.R.id.time); final DateTimeView time = (DateTimeView) publicViewLocal.findViewById(R.id.time); if (privateTime != null && privateTime.getVisibility() == View.VISIBLE) { time.setVisibility(View.VISIBLE); - time.setTime(entry.notification.getNotification().when); } final TextView text = (TextView) publicViewLocal.findViewById(R.id.text); @@ -1886,7 +1920,18 @@ protected void updateRowStates() { } private boolean shouldShowOnKeyguard(StatusBarNotification sbn) { - return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey()); + if (!mShowLockscreenNotifications || mNotificationData.isAmbient(sbn.getKey())) { + return false; + } + final int showOnKeyguard = mNoMan.getShowNotificationForPackageOnKeyguard( + sbn.getPackageName(), sbn.getUid()); + boolean isKeyguardAllowedForApp = + (showOnKeyguard & Notification.SHOW_ALL_NOTI_ON_KEYGUARD) != 0; + if (isKeyguardAllowedForApp && sbn.isOngoing()) { + isKeyguardAllowedForApp = + (showOnKeyguard & Notification.SHOW_NO_ONGOING_NOTI_ON_KEYGUARD) == 0; + } + return isKeyguardAllowedForApp; } protected void setZenMode(int mode) { @@ -1938,8 +1983,9 @@ public void updateNotification(StatusBarNotification notification, RankingMap ra boolean shouldInterrupt = shouldInterrupt(entry, notification); boolean alertAgain = alertAgain(entry, n); + final StatusBarNotification oldNotification = entry.notification; entry.notification = notification; - mGroupManager.onEntryUpdated(entry, entry.notification); + mGroupManager.onEntryUpdated(entry, oldNotification); boolean updateSuccessful = false; if (applyInPlace) { @@ -1981,7 +2027,9 @@ public void updateNotification(StatusBarNotification notification, RankingMap ra entry.icon.set(ic); inflateViews(entry, mStackScroller); } - updateHeadsUp(key, entry, shouldInterrupt, alertAgain); + if (mUseHeadsUp) { + updateHeadsUp(key, entry, shouldInterrupt, alertAgain); + } mNotificationData.updateRanking(ranking); updateNotifications(); @@ -2075,6 +2123,7 @@ private void updateNotificationViews(Entry entry, StatusBarNotification notifica final Notification publicVersion = notification.getNotification().publicVersion; final RemoteViews publicContentView = publicVersion != null ? publicVersion.contentView : null; + final View publicLocalView = entry.getPublicContentView(); // Reapply the RemoteViews contentView.reapply(mContext, entry.getContentView(), mOnClickHandler); @@ -2088,9 +2137,13 @@ private void updateNotificationViews(Entry entry, StatusBarNotification notifica headsUpContentView.reapply(notification.getPackageContext(mContext), headsUpChild, mOnClickHandler); } - if (publicContentView != null && entry.getPublicContentView() != null) { - publicContentView.reapply(notification.getPackageContext(mContext), - entry.getPublicContentView(), mOnClickHandler); + if (publicLocalView != null) { + if (publicContentView != null) { + publicContentView.reapply(notification.getPackageContext(mContext), + publicLocalView, mOnClickHandler); + } else { + updatePublicViewProperties(publicLocalView, entry); + } } // update the contentIntent mNotificationClicker.register(entry.row, notification); @@ -2105,6 +2158,55 @@ protected void notifyHeadsUpScreenOff() { maybeEscalateHeadsUp(); } + private void updatePublicViewProperties(View publicView, Entry entry) { + final StatusBarNotification n = entry.notification; + final ImageView icon = (ImageView) publicView.findViewById(R.id.icon); + final ImageView profileBadge = + (ImageView) publicView.findViewById(R.id.profile_badge_line3); + final DateTimeView time = (DateTimeView) publicView.findViewById(R.id.time); + + if (icon != null) { + final StatusBarIcon ic = new StatusBarIcon( + n.getUser(), n.getPackageName(), + n.getNotification().getSmallIcon(), + n.getNotification().iconLevel, + n.getNotification().number, + n.getNotification().tickerText); + + Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic); + icon.setImageDrawable(iconDrawable); + if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP + || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) { + icon.setBackgroundResource( + com.android.internal.R.drawable.notification_icon_legacy_bg); + int padding = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.notification_large_icon_circle_padding); + icon.setPadding(padding, padding, padding, padding); + if (n.getNotification().color != Notification.COLOR_DEFAULT) { + icon.getBackground().setColorFilter( + n.getNotification().color, PorterDuff.Mode.SRC_ATOP); + } + } else { + icon.setBackgroundDrawable(null); + } + } + + if (time != null) { + time.setTime(entry.notification.getNotification().when); + } + + if (profileBadge != null) { + Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity( + n.getUser(), 0); + if (profileDrawable != null) { + profileBadge.setImageDrawable(profileDrawable); + profileBadge.setVisibility(View.VISIBLE); + } else { + profileBadge.setVisibility(View.GONE); + } + } + } + private boolean alertAgain(Entry oldEntry, Notification newNotification) { return oldEntry == null || !oldEntry.hasInterrupted() || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0; @@ -2240,4 +2342,24 @@ public void startAssist(Bundle args) { mAssistManager.startAssist(args); } } + + /** + * Returns a context with the given theme applied or the original context if we fail to get a + * themed context. + */ + private Context maybeGetThemedContext(Context context, String themePkg) { + Context themedContext; + try { + ApplicationInfo ai = context.getPackageManager().getApplicationInfo( + context.getPackageName(), 0); + themedContext = context.createApplicationContext(ai, themePkg, + 0); + } catch (PackageManager.NameNotFoundException e) { + themedContext = null; + } + if (themedContext == null) { + themedContext = context; + } + return themedContext; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java b/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java index 4be72921c66cd..42974baf1b183 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CustomTileData.java @@ -29,7 +29,7 @@ public static final class Entry { public final StatusBarPanelCustomTile sbc; public Entry(StatusBarPanelCustomTile sbc) { - this.key = sbc.getKey(); + this.key = sbc.persistableKey(); this.sbc = sbc; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index c964ca7bcbf4a..be51e57531dac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -64,7 +64,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private boolean mShowingPublic; private boolean mSensitive; private boolean mShowingPublicInitialized; - private boolean mHideSensitiveForIntrinsicHeight; + protected boolean mHideSensitiveForIntrinsicHeight; /** * Is this notification expanded by the system. The expansion state can be overridden by the @@ -77,10 +77,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { */ private boolean mExpansionDisabled; - private NotificationContentView mPublicLayout; - private NotificationContentView mPrivateLayout; - private int mMaxExpandHeight; - private int mHeadsUpHeight; + protected NotificationContentView mPublicLayout; + protected NotificationContentView mPrivateLayout; + protected int mMaxExpandHeight; + protected int mHeadsUpHeight; private View mVetoButton; private boolean mClearable; private ExpansionLogger mLogger; @@ -101,7 +101,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private ValueAnimator mChildExpandAnimator; private float mChildrenExpandProgress; private float mExpandButtonStart; - private ViewStub mGutsStub; + protected ViewStub mGutsStub; private boolean mHasExpandAction; private boolean mIsSystemChildExpanded; private boolean mIsPinned; @@ -443,10 +443,11 @@ public void onInflate(ViewStub stub, View inflated) { mVetoButton = findViewById(R.id.veto); } - public void inflateGuts() { + public boolean inflateGuts() { if (mGuts == null) { mGutsStub.inflate(); } + return false; } private void updateChildrenVisibility(boolean animated) { @@ -645,7 +646,7 @@ public int getIntrinsicHeight() { } else if (mChildrenExpanded) { maxContentHeight = mChildrenContainer.getIntrinsicHeight(); } else { - maxContentHeight = getMaxExpandHeight(); + maxContentHeight = mMaxExpandHeight; } return maxContentHeight + getBottomDecorHeight(); } @@ -669,7 +670,7 @@ protected boolean canHaveBottomDecor() { * * @return whether the view state is currently expanded. */ - private boolean isExpanded() { + protected boolean isExpanded() { return !mExpansionDisabled && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded()) || isUserExpanded()); @@ -703,7 +704,7 @@ protected boolean isChildInvisible(View child) { return super.isChildInvisible(child) || isInvisibleChildContainer; } - private void updateMaxHeights() { + protected void updateMaxHeights() { int intrinsicBefore = getIntrinsicHeight(); View expandedChild = mPrivateLayout.getExpandedChild(); if (expandedChild == null) { @@ -902,10 +903,6 @@ public static void applyTint(View v, int color) { } } - public int getMaxExpandHeight() { - return mMaxExpandHeight; - } - @Override public boolean isContentExpandable() { NotificationContentView showingLayout = getShowingLayout(); @@ -961,7 +958,7 @@ public boolean isMaxExpandHeightInitialized() { return mMaxExpandHeight != 0; } - private NotificationContentView getShowingLayout() { + protected NotificationContentView getShowingLayout() { return mShowingPublic ? mPublicLayout : mPrivateLayout; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 71baf57821097..76858abf6d8ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -42,7 +42,7 @@ public abstract class ExpandableView extends FrameLayout { private boolean mDark; private ArrayList mMatchParentViews = new ArrayList(); private int mClipTopOptimization; - private static Rect mClipRect = new Rect(); + private Rect mClipRect = new Rect(); private boolean mWillBeGone; private int mMinClipTopAmount = 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java index 26b9c8ee6bf2b..1f7e687a654c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java @@ -187,7 +187,7 @@ public void setPreviewView(View v) { if (mPreviewView != null) { mPreviewView.setVisibility(mLaunchingAffordance ? oldPreviewView.getVisibility() : INVISIBLE); - mPreviewView.setVisibility(INVISIBLE); + mPreviewView.setVisibility(GONE); addOverlay(); } } @@ -283,7 +283,7 @@ public void onAnimationEnd(Animator animation) { }); animatorToRadius.start(); setImageAlpha(0, true); - if (mPreviewView != null) { + if (mPreviewView != null && mPreviewView.getVisibility() == View.VISIBLE) { mPreviewView.setVisibility(View.VISIBLE); mPreviewClipper = ViewAnimationUtils.createCircularReveal( mPreviewView, getLeft() + mCenterX, getTop() + mCenterY, mCircleRadius, @@ -386,7 +386,7 @@ private void setCircleRadius(float circleRadius, boolean slowAnimation, boolean invalidate(); if (nowHidden) { if (mPreviewView != null) { - mPreviewView.setVisibility(View.INVISIBLE); + mPreviewView.setVisibility(View.GONE); } } } else if (!mCircleWillBeHidden) { @@ -425,7 +425,7 @@ mPreviewView, getLeft() + mCenterX, getTop() + mCenterY, mCircleRadius, mPreviewClipper.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mPreviewView.setVisibility(View.INVISIBLE); + mPreviewView.setVisibility(View.GONE); } }); mPreviewClipper.start(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index fd84345e9f775..e4a019635375a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Color; import android.hardware.fingerprint.FingerprintManager; @@ -74,16 +75,20 @@ public class KeyguardIndicationController { private int mChargingSpeed; private int mChargingCurrent; private String mMessageToShowOnScreenOn; + private IndicationDirection mIndicationDirection; + private boolean mScreenOnHintsEnabled; public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView, LockIcon lockIcon) { mContext = context; mTextView = textView; mLockIcon = lockIcon; + mIndicationDirection = IndicationDirection.NONE; Resources res = context.getResources(); mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold); mFastThreshold = res.getInteger(R.integer.config_chargingFastThreshold); + mScreenOnHintsEnabled = res.getBoolean(R.bool.config_showScreenOnLockScreenHints); mBatteryInfo = IBatteryStats.Stub.asInterface( @@ -118,6 +123,20 @@ public void hideTransientIndicationDelayed(long delayMs) { mHandler.obtainMessage(MSG_HIDE_TRANSIENT), delayMs); } + /** + * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. + */ + public void showTransientIndication(int transientIndication, IndicationDirection direction) { + showTransientIndication(mContext.getResources().getString(transientIndication), direction); + } + + /** + * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. + */ + public void showTransientIndication(String transientIndication, IndicationDirection direction) { + showTransientIndication(transientIndication, Color.WHITE, direction); + } + /** * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. */ @@ -129,15 +148,24 @@ public void showTransientIndication(int transientIndication) { * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. */ public void showTransientIndication(String transientIndication) { - showTransientIndication(transientIndication, Color.WHITE); + showTransientIndication(transientIndication, Color.WHITE, IndicationDirection.NONE); } /** * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. */ public void showTransientIndication(String transientIndication, int textColor) { + showTransientIndication(transientIndication, textColor, IndicationDirection.NONE); + } + + /** + * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. + */ + public void showTransientIndication(String transientIndication, int textColor, + IndicationDirection direction) { mTransientIndication = transientIndication; mTransientTextColor = textColor; + mIndicationDirection = direction; mHandler.removeMessages(MSG_HIDE_TRANSIENT); updateIndication(); } @@ -153,10 +181,38 @@ public void hideTransientIndication() { } } + public void cleanup() { + KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor); + mContext.unregisterReceiver(mReceiver); + } + private void updateIndication() { if (mVisible) { + final int color = computeColor(); mTextView.switchIndication(computeIndication()); - mTextView.setTextColor(computeColor()); + mTextView.setTextColor(color); + int top = 0, left = 0, right = 0; + // pad the bottom using ic_empty_space to keep text vertically aligned if needed + int bottom = mScreenOnHintsEnabled ? R.drawable.ic_empty_space : 0; + switch (mIndicationDirection) { + case UP: + top = R.drawable.ic_keyboard_arrow_up; + break; + case DOWN: + bottom = R.drawable.ic_keyboard_arrow_down; + break; + case LEFT: + left = R.drawable.ic_keyboard_arrow_left; + break; + case RIGHT: + right = R.drawable.ic_keyboard_arrow_right; + break; + case NONE: + default: + break; + } + mTextView.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); + mTextView.setCompoundDrawableTintList(ColorStateList.valueOf(color)); } } @@ -171,6 +227,7 @@ private String computeIndication() { if (!TextUtils.isEmpty(mTransientIndication)) { return mTransientIndication; } + mIndicationDirection = IndicationDirection.NONE; if (mPowerPluggedIn) { String indication = computePowerIndication(); if (DEBUG_CHARGING_CURRENT) { @@ -321,4 +378,12 @@ public void setStatusBarKeyguardViewManager( StatusBarKeyguardViewManager statusBarKeyguardViewManager) { mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; } + + public enum IndicationDirection { + NONE, + UP, + DOWN, + LEFT, + RIGHT + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaExpandableNotificationRow.java new file mode 100644 index 0000000000000..c25f14609f17f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaExpandableNotificationRow.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.systemui.statusbar; + +import android.content.Context; +import android.content.res.Resources; +import android.media.session.MediaController; +import android.os.Build; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.android.systemui.R; +import com.android.systemui.cm.UserContentObserver; + +import cyanogenmod.providers.CMSettings; + +public class MediaExpandableNotificationRow extends ExpandableNotificationRow { + + private static final String TAG = MediaExpandableNotificationRow.class.getSimpleName(); + public static final boolean DEBUG = false; + + public static final int MAX_QUEUE_ENTRIES = 3; + + private QueueView mQueue; + + private int mMaxQueueHeight; + private int mRowHeight; + private int mShadowHeight; + private int mDisplayedRows; + + private SettingsObserver mSettingsObserver; + private boolean mQueueEnabled; + + public MediaExpandableNotificationRow(Context context, AttributeSet attrs) { + super(context, attrs); + mSettingsObserver = new SettingsObserver(new Handler()); + mQueueEnabled = isQueueEnabled(context); + + Resources res = mContext.getResources(); + + // 3 * queue_row_height + shadow height + mRowHeight = res.getDimensionPixelSize(R.dimen.queue_row_height); + mShadowHeight = res.getDimensionPixelSize(R.dimen.queue_top_shadow); + } + + public boolean inflateGuts() { + if (getGuts() == null) { + mGutsStub.inflate(); + } + if (!mQueueEnabled) { + return true; + } + return !mQueue.isUserSelectingRow(); + } + + @Override + protected void updateMaxHeights() { + // update queue height based on number of rows + int rows = mQueue != null ? mQueue.getCurrentQueueRowCount() : 0; + if (rows != mDisplayedRows) { + mMaxQueueHeight = rows * mRowHeight; + if (mMaxQueueHeight > 0) { + mMaxQueueHeight += mShadowHeight; + } + mDisplayedRows = rows; + } + + int intrinsicBefore = getIntrinsicHeight(); + View expandedChild = mPrivateLayout.getExpandedChild(); + if (expandedChild == null) { + expandedChild = mPrivateLayout.getContractedChild(); + } + mMaxExpandHeight = expandedChild.getHeight() + mMaxQueueHeight; + + View headsUpChild = mPrivateLayout.getHeadsUpChild(); + if (headsUpChild == null) { + headsUpChild = mPrivateLayout.getContractedChild(); + } + mHeadsUpHeight = headsUpChild.getHeight(); + if (intrinsicBefore != getIntrinsicHeight()) { + notifyHeightChanged(false /* needsAnimation */); + } + invalidateOutline(); + } + + @Override + public int getIntrinsicHeight() { + if (getGuts() != null && getGuts().isShown()) { + return getGuts().getActualHeight(); + } + if (!mQueueEnabled) { + return super.getIntrinsicHeight(); + } + if (mHideSensitiveForIntrinsicHeight) { + return getMinHeight(); + } + if (isUserLocked()) { + return getActualHeight(); + } + boolean inExpansionState = isExpanded(); + if (!inExpansionState) { + // not expanded, so we return the collapsed size + return getMinHeight(); + } + return getMaxContentHeight(); + } + + @Override + public int getMaxContentHeight() { + /** + * calls into NotificationContentView.getMaxHeight() + */ + return getShowingLayout().getMaxHeight() + mMaxQueueHeight; + } + + @Override + public void setHeightRange(int rowMinHeight, int rowMaxHeight) { + super.setHeightRange(rowMinHeight, rowMaxHeight); + mMaxViewHeight = Math.max(rowMaxHeight, getMaxContentHeight()); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mQueue = (QueueView) findViewById(R.id.queue_view); + mQueue.setQueueEnabled(mQueueEnabled); + mQueue.setVisibility(mQueueEnabled ? View.VISIBLE : View.GONE); + } + + public void setMediaController(MediaController mediaController) { + if (DEBUG) Log.d(TAG, "setMediaController() called with " + + "mediaController = [" + mediaController + "]"); + if (mQueue.setController(mediaController) && mQueueEnabled) { + notifyHeightChanged(true); + } + } + + @Override + public boolean dispatchGenericMotionEvent(MotionEvent ev) { + if (filterMotionEvent(ev)) { + return super.dispatchGenericMotionEvent(ev); + } + return false; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (filterMotionEvent(ev)) { + return super.dispatchTouchEvent(ev); + } + return false; + } + + @Override + protected boolean filterMotionEvent(MotionEvent event) { + if (!mQueueEnabled) { + return super.filterMotionEvent(event); + } + if (isExpanded() && mQueue.isUserSelectingRow() + && event.getActionMasked() != MotionEvent.ACTION_DOWN + && event.getActionMasked() != MotionEvent.ACTION_UP + && event.getActionMasked() != MotionEvent.ACTION_CANCEL) { + // this is for hotspot propogation? + return false; + } + return super.filterMotionEvent(event); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mSettingsObserver.observe(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mSettingsObserver.unobserve(); + } + + private class SettingsObserver extends UserContentObserver { + + public SettingsObserver(Handler handler) { + super(handler); + } + + @Override + protected void observe() { + super.observe(); + mContext.getContentResolver().registerContentObserver( + CMSettings.System.getUriFor(CMSettings.System.NOTIFICATION_PLAY_QUEUE), + true, this); + } + + @Override + protected void unobserve() { + super.unobserve(); + mContext.getContentResolver().unregisterContentObserver(this); + } + + @Override + protected void update() { + mQueueEnabled = isQueueEnabled(mContext); + mQueue.setQueueEnabled(mQueueEnabled); + mQueue.setVisibility(mQueueEnabled ? View.VISIBLE : View.GONE); + requestLayout(); + } + } + + public static boolean isQueueEnabled(Context context) { + return CMSettings.System.getInt(context.getContentResolver(), + CMSettings.System.NOTIFICATION_PLAY_QUEUE, 1) == 1; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaNotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaNotificationGuts.java new file mode 100644 index 0000000000000..14ce8e19b6462 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaNotificationGuts.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.Switch; +import android.widget.TextView; +import com.android.systemui.R; +import cyanogenmod.providers.CMSettings; + +/** + * The guts of a media notification revealed when performing a long press. + */ +public class MediaNotificationGuts extends NotificationGuts { + + private static final String TAG = MediaNotificationGuts.class.getSimpleName(); + + private ViewGroup mQueueGroup; + private TextView mText; + private Switch mSwitch; + + public MediaNotificationGuts(Context context, AttributeSet attrs) { + super(context, attrs); + + setWillNotDraw(true); + } + + @Override + protected void onDraw(Canvas canvas) { + // do nothing! + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mQueueGroup = (ViewGroup) findViewById(R.id.queue_group); + mSwitch = (Switch) findViewById(R.id.queue_switch); + mSwitch.setChecked(MediaExpandableNotificationRow.isQueueEnabled(getContext())); + mText = (TextView) findViewById(R.id.switch_label); + mText.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mSwitch.toggle(); + } + }); + mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + buttonView.setChecked(isChecked); + CMSettings.System.putInt(getContext().getContentResolver(), + CMSettings.System.NOTIFICATION_PLAY_QUEUE, + isChecked ? 1 : 0); + } + }); + } + + + @Override + public void setActualHeight(int actualHeight) { + super.setActualHeight(actualHeight); + } + + @Override + public int getActualHeight() { + return getHeight(); + } + + @Override + public boolean hasOverlappingRendering() { + + // Prevents this view from creating a layer when alpha is animating. + return false; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index 46e0bf86fd36c..23912c40c0ed1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -28,9 +28,9 @@ */ public class NotificationGuts extends FrameLayout { - private Drawable mBackground; - private int mClipTopAmount; - private int mActualHeight; + protected Drawable mBackground; + protected int mClipTopAmount; + protected int mActualHeight; public NotificationGuts(Context context, AttributeSet attrs) { super(context, attrs); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/QueueView.java b/packages/SystemUI/src/com/android/systemui/statusbar/QueueView.java new file mode 100644 index 0000000000000..1da2e5e50180f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/QueueView.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.systemui.statusbar; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.media.MediaDescription; +import android.media.MediaMetadata; +import android.media.session.MediaController; +import android.media.session.MediaSession; +import android.media.session.PlaybackState; +import android.os.Handler; +import android.provider.Settings; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; +import android.widget.ListView; +import com.android.systemui.R; +import com.android.systemui.cm.UserContentObserver; + +import java.util.ArrayList; +import java.util.List; + +public class QueueView extends LinearLayout implements + QueueViewRow.UserRowInteractionListener, AdapterView.OnItemClickListener, + AdapterView.OnItemLongClickListener { + + private static final String TAG = QueueView.class.getSimpleName(); + private static final boolean DEBUG = MediaExpandableNotificationRow.DEBUG; + + private MediaController mController; + + private List mQueue = new ArrayList<>(getMaxQueueRowCount()); + + private QueueItemAdapter mAdapter; + private ListView mList; + private boolean mQueueEnabled; + + long mLastUserInteraction = -1; + + private MediaController.Callback mCallback = new MediaController.Callback() { + @Override + public void onPlaybackStateChanged(@NonNull PlaybackState state) { + super.onPlaybackStateChanged(state); + + if (getParent() != null && updateQueue(mController.getQueue())) { + getParent().requestLayout(); + } + } + + @Override + public void onSessionDestroyed() { + if (DEBUG) Log.d(TAG, "onSessionDestroyed() called with " + ""); + super.onSessionDestroyed(); + setController(null); + } + }; + + public QueueView(Context context, AttributeSet attrs) { + super(context, attrs); + mAdapter = new QueueItemAdapter(context); + setClipToOutline(false); + setClipToPadding(false); + } + + public void setQueueEnabled(boolean enabled) { + mQueueEnabled = enabled; + mAdapter.notifyDataSetChanged(); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mList = (ListView) findViewById(R.id.queue_list); + mList.setItemsCanFocus(true); + mList.setDrawSelectorOnTop(true); + mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + mList.setAdapter(mAdapter); + mList.setOnItemLongClickListener(this); + mList.setOnItemClickListener(this); + mList.setVerticalScrollBarEnabled(false); + } + + private class QueueItemAdapter extends ArrayAdapter { + + public QueueItemAdapter(Context context) { + super(context, R.layout.queue_adapter_row, mQueue); + } + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public long getItemId(int position) { + if (position > getCount() - 1) { + return -1; + } + return getItem(position).getQueueId(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final MediaSession.QueueItem queueItem = getItem(position); + + if (convertView == null) { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.queue_adapter_row, parent, false); + } + + QueueViewRow row = (QueueViewRow) convertView; + row.setHotSpotChangeListener(QueueView.this); + + row.setQueueItem(queueItem); + + return convertView; + } + + @Override + public int getCount() { + if (!mQueueEnabled) { + return 0; + } + return super.getCount(); + } + } + + public boolean isUserSelectingRow() { + final long delta = System.currentTimeMillis() - mLastUserInteraction; + if (DEBUG) Log.i(TAG, "isUserSelectingRow() delta=" + delta); + + if (mLastUserInteraction > 0 && delta < 500) { + if (DEBUG) Log.w(TAG, "user selecting row bc of hotspot change."); + return true; + } + + return false; + } + + public int getMaxQueueRowCount() { + return MediaExpandableNotificationRow.MAX_QUEUE_ENTRIES; + } + + public int getCurrentQueueRowCount() { + if (mAdapter == null) { + return 0; + } + return mAdapter.getCount(); + } + + @Override + public void onHotSpotChanged(float x, float y) { + mLastUserInteraction = System.currentTimeMillis(); + } + + @Override + public void onDrawableStateChanged() { + mLastUserInteraction = System.currentTimeMillis(); + } + + /** + * @param queue + * @return whether the queue size has changed + */ + public boolean updateQueue(List queue) { + int queueSizeBefore = mAdapter.getCount(); + + mQueue.clear(); + + if (queue != null) { + // add everything *after* the currently playing item + boolean foundNowPlaying = false; + + final PlaybackState playbackState = mController.getPlaybackState(); + + long activeQueueId = -1; + if (playbackState != null) { + activeQueueId = playbackState.getActiveQueueItemId(); + } + + for (int i = 0; i < queue.size() && mQueue.size() < getMaxQueueRowCount(); i++) { + final MediaSession.QueueItem item = queue.get(i); + if (!foundNowPlaying + && activeQueueId != -1 + && activeQueueId == item.getQueueId()) { + foundNowPlaying = true; + continue; + } + if (foundNowPlaying) { + mQueue.add(item); + } + } + + // add everything + if (!foundNowPlaying) { + for(int i = 0; i < getMaxQueueRowCount() && i < queue.size(); i++) { + mQueue.add(queue.get(i)); + } + } + } + mAdapter.notifyDataSetChanged(); + + return mAdapter.getCount() != queueSizeBefore; + } + + public boolean setController(MediaController controller) { + if (mController != null) { + mController.unregisterCallback(mCallback); + } + mController = controller; + if (mController != null) { + mController.registerCallback(mCallback); + } + + return updateQueue(mController != null + ? mController.getQueue() : null); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final MediaSession.QueueItem itemAtPosition = (MediaSession.QueueItem) + parent.getItemAtPosition(position); + if (itemAtPosition != null && mController != null) { + mController.getTransportControls().skipToQueueItem(itemAtPosition.getQueueId()); + } + mAdapter.notifyDataSetChanged(); + } + + @Override + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + return true; + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/QueueViewRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/QueueViewRow.java new file mode 100644 index 0000000000000..dab89ff38d70e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/QueueViewRow.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.systemui.statusbar; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.media.MediaDescription; +import android.media.session.MediaSession; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import com.android.systemui.R; + +public class QueueViewRow extends RelativeLayout { + + private static final String TAG = QueueViewRow.class.getSimpleName(); + + private UserRowInteractionListener mHotSpotChangeListener; + + private ImageView mArt; + private TextView mTitle; + private TextView mSummary; + + public QueueViewRow(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mArt = (ImageView) findViewById(R.id.art); + mTitle = (TextView) findViewById(R.id.title); + mSummary = (TextView) findViewById(R.id.summary); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + if (mHotSpotChangeListener != null) { + mHotSpotChangeListener.onDrawableStateChanged(); + } + } + + @Override + public void dispatchDrawableHotspotChanged(float x, float y) { + super.dispatchDrawableHotspotChanged(x, y); + if (mHotSpotChangeListener != null) { + mHotSpotChangeListener.onHotSpotChanged(x, y); + } + } + + public void setHotSpotChangeListener(UserRowInteractionListener listener) { + mHotSpotChangeListener = listener; + } + + public TextView getTitle() { + return mTitle; + } + + public TextView getSummary() { + return mSummary; + } + + public void setQueueItem(MediaSession.QueueItem queueItem) { + setTag(queueItem); + + MediaDescription metadata = queueItem.getDescription(); + + final Bitmap bitmap = metadata.getIconBitmap(); + mArt.setImageBitmap(bitmap); + mArt.setVisibility(bitmap != null ? View.VISIBLE : View.GONE); + + mTitle.setText(metadata.getTitle()); + mSummary.setText(metadata.getSubtitle()); + } + + /* package */ interface UserRowInteractionListener { + public void onHotSpotChanged(float x, float y); + public void onDrawableStateChanged(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index b0fc398e9e749..ecaa809e3d271 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -136,9 +136,14 @@ public void setNetworkController(NetworkControllerImpl nc) { public void setSecurityController(SecurityController sc) { if (DEBUG) Log.d(TAG, "SecurityController=" + sc); + if (sc == null && mSC != null) { + mSC.removeCallback(this); + } mSC = sc; - mSC.addCallback(this); - mVpnVisible = mSC.isVpnEnabled(); + if (mSC != null) { + mSC.addCallback(this); + mVpnVisible = mSC.isVpnEnabled(); + } } @Override @@ -198,8 +203,10 @@ public void onStateChanged() { post(new Runnable() { @Override public void run() { - mVpnVisible = mSC.isVpnEnabled(); - apply(); + if (mSC != null) { + mVpnVisible = mSC.isVpnEnabled(); + apply(); + } } }); } @@ -217,7 +224,7 @@ public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState q @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId) { + String description, boolean isWide, boolean showRoamingIndicator, int subId) { PhoneState state = getState(subId); if (state == null) { return; @@ -228,6 +235,7 @@ public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int state.mMobileDescription = statusIcon.contentDescription; state.mMobileTypeDescription = typeContentDescription; state.mIsMobileTypeIconWide = statusType != 0 && isWide; + state.mShowRoamingIndicator = showRoamingIndicator; apply(); } @@ -345,10 +353,13 @@ public void onRtlPropertiesChanged(int layoutDirection) { for (PhoneState state : mPhoneStates) { if (state.mMobile != null) { + state.maybeStopAnimatableDrawable(state.mMobile); state.mMobile.setImageDrawable(null); + state.mLastMobileStrengthId = -1; } if (state.mMobileType != null) { state.mMobileType.setImageDrawable(null); + state.mLastMobileTypeId = -1; } } @@ -476,11 +487,15 @@ private class PhoneState { private final int mSubId; private boolean mMobileVisible = false; private int mMobileStrengthId = 0, mMobileTypeId = 0; + private int mLastMobileStrengthId = -1; + private int mLastMobileTypeId = -1; private boolean mIsMobileTypeIconWide; private String mMobileDescription, mMobileTypeDescription; + private boolean mShowRoamingIndicator; private ViewGroup mMobileGroup; private ImageView mMobile, mMobileDark, mMobileType; + private ImageView mMobileRoaming; public PhoneState(int subId, Context context) { ViewGroup root = (ViewGroup) LayoutInflater.from(context) @@ -494,32 +509,25 @@ public void setViews(ViewGroup root) { mMobile = (ImageView) root.findViewById(R.id.mobile_signal); mMobileDark = (ImageView) root.findViewById(R.id.mobile_signal_dark); mMobileType = (ImageView) root.findViewById(R.id.mobile_type); + mMobileRoaming = (ImageView) root.findViewById(R.id.mobile_roaming); } public boolean apply(boolean isSecondaryIcon) { if (mMobileVisible && !mIsAirplaneMode) { - mMobile.setImageResource(mMobileStrengthId); - Drawable mobileDrawable = mMobile.getDrawable(); - if (mobileDrawable instanceof Animatable) { - Animatable ad = (Animatable) mobileDrawable; - if (!ad.isRunning()) { - ad.start(); - } + if (mLastMobileStrengthId != mMobileStrengthId) { + updateAnimatableIcon(mMobile, mMobileStrengthId); + updateAnimatableIcon(mMobileDark, mMobileStrengthId); + mLastMobileStrengthId = mMobileStrengthId; } - mMobileDark.setImageResource(mMobileStrengthId); - Drawable mobileDarkDrawable = mMobileDark.getDrawable(); - if (mobileDarkDrawable instanceof Animatable) { - Animatable ad = (Animatable) mobileDarkDrawable; - if (!ad.isRunning()) { - ad.start(); - } + if (mLastMobileTypeId != mMobileTypeId) { + mMobileType.setImageResource(mMobileTypeId); + mLastMobileTypeId = mMobileTypeId; } - - mMobileType.setImageResource(mMobileTypeId); mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription); mMobileGroup.setVisibility(View.VISIBLE); + mMobileRoaming.setVisibility(mShowRoamingIndicator ? View.VISIBLE : View.GONE); } else { mMobileGroup.setVisibility(View.GONE); } @@ -540,6 +548,32 @@ public boolean apply(boolean isSecondaryIcon) { return mMobileVisible; } + private void updateAnimatableIcon(ImageView view, int resId) { + maybeStopAnimatableDrawable(view); + view.setImageResource(resId); + maybeStartAnimatableDrawable(view); + } + + private void maybeStopAnimatableDrawable(ImageView view) { + Drawable drawable = view.getDrawable(); + if (drawable instanceof Animatable) { + Animatable ad = (Animatable) drawable; + if (ad.isRunning()) { + ad.stop(); + } + } + } + + private void maybeStartAnimatableDrawable(ImageView view) { + Drawable drawable = view.getDrawable(); + if (drawable instanceof Animatable) { + Animatable ad = (Animatable) drawable; + if (!ad.isRunning()) { + ad.start(); + } + } + } + public void populateAccessibilityEvent(AccessibilityEvent event) { if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null) { @@ -550,6 +584,7 @@ public void populateAccessibilityEvent(AccessibilityEvent event) { public void setIconTint(int tint, float darkIntensity) { applyDarkIntensity(darkIntensity, mMobile, mMobileDark); setTint(mMobileType, tint); + setTint(mMobileRoaming, tint); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 4371ccece5f0f..857cb081f310e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -90,7 +90,7 @@ public StatusBarIconView(Context context, String slot, Notification notification public void setNotification(Notification notification) { mNotification = notification; mShowNotificationCount = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.STATUS_BAR_NOTIF_COUNT, 0, UserHandle.USER_CURRENT) == 1; + CMSettings.System.STATUS_BAR_NOTIF_COUNT, 1, UserHandle.USER_CURRENT) == 1; setContentDescription(notification); } @@ -388,7 +388,7 @@ protected void unobserve() { @Override public void update() { boolean showIconCount = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.STATUS_BAR_NOTIF_COUNT, 0, UserHandle.USER_CURRENT) == 1; + CMSettings.System.STATUS_BAR_NOTIF_COUNT, 1, UserHandle.USER_CURRENT) == 1; for (StatusBarIconView sbiv : mIconViews) { sbiv.mShowNotificationCount = showIconCount; sbiv.set(sbiv.mIcon, true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java index cbf5e5b32b9cc..538140c7179d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java @@ -26,18 +26,18 @@ import android.os.AsyncTask; import android.os.Handler; import android.os.UserHandle; -import android.provider.Settings; import android.support.v7.graphics.Palette; import android.util.AttributeSet; +import android.util.Log; import android.view.View; + import com.android.systemui.cm.UserContentObserver; -import com.android.systemui.statusbar.policy.KeyguardMonitor; import cyanogenmod.providers.CMSettings; -import java.util.Arrays; +public class VisualizerView extends View implements Palette.PaletteAsyncListener { -public class VisualizerView extends View implements Palette.PaletteAsyncListener, - KeyguardMonitor.Callback { + private static final String TAG = VisualizerView.class.getSimpleName(); + private static final boolean DEBUG = false; private Paint mPaint; private Visualizer mVisualizer; @@ -46,6 +46,7 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener private ValueAnimator[] mValueAnimators; private float[] mFFTPoints; + private int mStatusBarState; private boolean mVisualizerEnabled = false; private boolean mVisible = false; private boolean mPlaying = false; @@ -57,7 +58,6 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener private int mColor; private Bitmap mCurrentBitmap; - private KeyguardMonitor mKeyguardMonitor; private SettingsObserver mObserver; private Visualizer.OnDataCaptureListener mVisualizerListener = @@ -89,9 +89,14 @@ public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate private final Runnable mLinkVisualizer = new Runnable() { @Override public void run() { + if (DEBUG) { + Log.w(TAG, "+++ mLinkVisualizer run()"); + } + try { mVisualizer = new Visualizer(0); } catch (Exception e) { + Log.e(TAG, "error initializing visualizer", e); return; } @@ -101,17 +106,33 @@ public void run() { false, true); mVisualizer.setEnabled(true); + if (DEBUG) { + Log.w(TAG, "--- mLinkVisualizer run()"); + } + } + }; + + private final Runnable mAsyncUnlinkVisualizer = new Runnable() { + @Override + public void run() { + AsyncTask.execute(mUnlinkVisualizer); } }; private final Runnable mUnlinkVisualizer = new Runnable() { @Override public void run() { + if (DEBUG) { + Log.w(TAG, "+++ mUnlinkVisualizer run(), mVisualizer: " + mVisualizer); + } if (mVisualizer != null) { mVisualizer.setEnabled(false); mVisualizer.release(); mVisualizer = null; } + if (DEBUG) { + Log.w(TAG, "--- mUninkVisualizer run()"); + } } }; @@ -148,22 +169,19 @@ public VisualizerView(Context context) { this(context, null, 0); } - @Override - public void onKeyguardChanged() { - updateViewVisibility(); - } - private void updateViewVisibility() { - setVisibility(mKeyguardMonitor != null && mKeyguardMonitor.isShowing() - && mVisualizerEnabled ? View.VISIBLE : View.GONE); + final int curVis = getVisibility(); + final int newVis = mStatusBarState != StatusBarState.SHADE + && mVisualizerEnabled ? View.VISIBLE : View.GONE; + if (curVis != newVis) { + setVisibility(newVis); + checkStateChanged(); + } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (mKeyguardMonitor != null) { - mKeyguardMonitor.addCallback(this); - } mObserver = new SettingsObserver(new Handler()); mObserver.observe(); mObserver.update(); @@ -172,22 +190,11 @@ protected void onAttachedToWindow() { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (mKeyguardMonitor != null) { - mKeyguardMonitor.removeCallback(this); - } mObserver.unobserve(); mObserver = null; mCurrentBitmap = null; } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - final int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); - setMeasuredDimension(size, size); - } - @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); @@ -206,7 +213,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { @Override public boolean hasOverlappingRendering() { - return mVisualizerEnabled && mDisplaying; + return false; } @Override @@ -218,17 +225,11 @@ protected void onDraw(Canvas canvas) { } } - public void setKeyguardMonitor(KeyguardMonitor kgm) { - mKeyguardMonitor = kgm; - if (isAttachedToWindow()) { - // otherwise we might never register ourselves - mKeyguardMonitor.addCallback(this); - updateViewVisibility(); - } - } - public void setVisible(boolean visible) { if (mVisible != visible) { + if (DEBUG) { + Log.i(TAG, "setVisible() called with visible = [" + visible + "]"); + } mVisible = visible; checkStateChanged(); } @@ -236,6 +237,9 @@ public void setVisible(boolean visible) { public void setDozing(boolean dozing) { if (mDozing != dozing) { + if (DEBUG) { + Log.i(TAG, "setDozing() called with dozing = [" + dozing + "]"); + } mDozing = dozing; checkStateChanged(); } @@ -243,6 +247,9 @@ public void setDozing(boolean dozing) { public void setPlaying(boolean playing) { if (mPlaying != playing) { + if (DEBUG) { + Log.i(TAG, "setPlaying() called with playing = [" + playing + "]"); + } mPlaying = playing; checkStateChanged(); } @@ -250,6 +257,9 @@ public void setPlaying(boolean playing) { public void setPowerSaveMode(boolean powerSaveMode) { if (mPowerSaveMode != powerSaveMode) { + if (DEBUG) { + Log.i(TAG, "setPowerSaveMode() called with powerSaveMode = [" + powerSaveMode + "]"); + } mPowerSaveMode = powerSaveMode; checkStateChanged(); } @@ -257,11 +267,21 @@ public void setPowerSaveMode(boolean powerSaveMode) { public void setOccluded(boolean occluded) { if (mOccluded != occluded) { + if (DEBUG) { + Log.i(TAG, "setOccluded() called with occluded = [" + occluded + "]"); + } mOccluded = occluded; checkStateChanged(); } } + public void setStatusBarState(int statusBarState) { + if (mStatusBarState != statusBarState) { + mStatusBarState = statusBarState; + updateViewVisibility(); + } + } + public void setBitmap(Bitmap bitmap) { if (mCurrentBitmap == bitmap) { return; @@ -316,8 +336,8 @@ private void setColor(int color) { } private void checkStateChanged() { - if (mVisible && mPlaying && !mDozing && !mPowerSaveMode && mVisualizerEnabled - && !mOccluded) { + if (getVisibility() == View.VISIBLE && mVisible && mPlaying && !mDozing && !mPowerSaveMode + && mVisualizerEnabled && !mOccluded) { if (!mDisplaying) { mDisplaying = true; AsyncTask.execute(mLinkVisualizer); @@ -332,13 +352,12 @@ private void checkStateChanged() { if (mVisible) { animate() .alpha(0f) - .withEndAction(mUnlinkVisualizer) + .withEndAction(mAsyncUnlinkVisualizer) .setDuration(600); } else { - AsyncTask.execute(mUnlinkVisualizer); animate(). alpha(0f) - .withEndAction(null) + .withEndAction(mAsyncUnlinkVisualizer) .setDuration(0); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java index 47b34638fe6e8..84eeb311fa00e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java @@ -142,4 +142,8 @@ public void updateFontSize() { FontSizeUtils.updateFontSize(mActiveClock, R.dimen.status_bar_clock_size); } } + + public void cleanup() { + mSettingsObserver.unobserve(); + } } \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java index 29129638fc6cb..7135836afba9c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java @@ -173,7 +173,7 @@ public void onFingerprintAuthenticated(int userId) { if (DEBUG_FP_WAKELOCK) { Log.i(TAG, "fp wakelock: Authenticated, waking up..."); } - mPowerManager.wakeUp(SystemClock.uptimeMillis()); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT"); } releaseFingerprintWakeLock(); switch (mMode) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java index 60ebfdf639efb..e1a345fb7f943 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -49,7 +49,7 @@ public class KeyguardAffordanceHelper { private VelocityTracker mVelocityTracker; private boolean mSwipingInProgress; private float mInitialTouchX; - private float mInitialTouchY; + private float mInitialTouchYRaw; private float mTranslation; private float mTranslationOnDown; private int mTouchSlop; @@ -128,7 +128,7 @@ public boolean onTouchEvent(MotionEvent event) { if (mMotionCancelled && action != MotionEvent.ACTION_DOWN) { return false; } - final float y = event.getY(); + final float y = event.getRawY(); final float x = event.getX(); boolean isUp = false; @@ -146,7 +146,7 @@ public boolean onTouchEvent(MotionEvent event) { } startSwiping(targetView); mInitialTouchX = x; - mInitialTouchY = y; + mInitialTouchYRaw = y; mTranslationOnDown = mTranslation; initVelocityTracker(); trackMovement(event); @@ -159,7 +159,7 @@ public boolean onTouchEvent(MotionEvent event) { case MotionEvent.ACTION_MOVE: trackMovement(event); float xDist = x - mInitialTouchX; - float yDist = y - mInitialTouchY; + float yDist = y - mInitialTouchYRaw; float distance = (float) Math.hypot(xDist, yDist); if (!mTouchSlopExeeded && distance > mTouchSlop) { mTouchSlopExeeded = true; @@ -211,8 +211,9 @@ public boolean isOnAffordanceIcon(float x, float y) { } private boolean isOnIcon(View icon, float x, float y) { + int[] location = icon.getLocationOnScreen(); float iconX = icon.getX() + icon.getWidth() / 2.0f; - float iconY = icon.getY() + icon.getHeight() / 2.0f; + float iconY = location[1] + icon.getHeight() / 2.0f; double distance = Math.hypot(x - iconX, y - iconY); return distance <= mTouchTargetSize / 2; } @@ -241,6 +242,13 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } + public boolean isOnLockIcon(MotionEvent event) { + final float x = event.getX(); + final float y = event.getRawY(); + + return isOnIcon(mCenterIcon, x, y); + } + public void startHintAnimation(boolean right, Runnable onFinishedListener) { cancelAnimation(); @@ -488,7 +496,7 @@ private float getCurrentVelocity(float lastX, float lastY) { float aX = mVelocityTracker.getXVelocity(); float aY = mVelocityTracker.getYVelocity(); float bX = lastX - mInitialTouchX; - float bY = lastY - mInitialTouchY; + float bY = lastY - mInitialTouchYRaw; float bLen = (float) Math.hypot(bX, bY); // Project the velocity onto the distance vector: a * b / |b| float projectedVelocity = (aX * bX + aY * bY) / bLen; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index f79e05164fc47..b244e26cb6617 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -29,14 +29,10 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; -import android.hardware.fingerprint.FingerprintManager; -import android.content.res.Resources; -import android.graphics.Bitmap; +import android.graphics.PixelFormat; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.hardware.fingerprint.FingerprintManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.IBinder; @@ -50,8 +46,11 @@ import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -73,6 +72,8 @@ import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.PreviewInflater; +import java.util.Objects; + import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; @@ -89,6 +90,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance"; public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture"; public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap"; + public static final String CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE = "screen_gesture"; public static final String EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"; @@ -126,6 +128,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private boolean mUserSetupComplete; private boolean mPrewarmBound; private Messenger mPrewarmMessenger; + private final WindowManager mWindowManager; + private boolean mBottomAreaAttached; + private final WindowManager.LayoutParams mWindowLayoutParams; + private OnInterceptTouchEventListener mInterceptTouchListener; + private BroadcastReceiver mDevicePolicyReceiver; + private Intent mLastCameraIntent; + private final ServiceConnection mPrewarmConnection = new ServiceConnection() { @Override @@ -139,6 +148,48 @@ public void onServiceDisconnected(ComponentName name) { } }; + @Override + public void setVisibility(int visibility) { + if (visibility == View.VISIBLE) { + if (!mBottomAreaAttached) { + addKeyguardBottomArea(false); + } + } else if (mBottomAreaAttached) { + removeKeyguardBottomArea(); + } + super.setVisibility(visibility); + } + + public void expand(boolean expand) { + addKeyguardBottomArea(expand); + } + + private void addKeyguardBottomArea(boolean fullyExpand) { + mWindowLayoutParams.height = fullyExpand ? WindowManager.LayoutParams.MATCH_PARENT : + WindowManager.LayoutParams.WRAP_CONTENT; + if (!mBottomAreaAttached) { + try { + mWindowManager.addView(this, mWindowLayoutParams); + } catch (IllegalStateException e) { + Log.e(TAG, e.getMessage()); + } + mBottomAreaAttached = true; + } else { + mWindowManager.updateViewLayout(this, mWindowLayoutParams); + } + } + + private void removeKeyguardBottomArea() { + if (mBottomAreaAttached) { + try { + mWindowManager.removeView(this); + } catch (IllegalArgumentException e) { + Log.e(TAG, e.getMessage()); + } + mBottomAreaAttached = false; + } + } + private AssistManager mAssistManager; public KeyguardBottomAreaView(Context context) { @@ -161,6 +212,20 @@ public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleA ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); mGrayScaleFilter = new ColorMatrixColorFilter(cm); + mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + + mWindowLayoutParams = new WindowManager.LayoutParams(); + mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; + mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + mWindowLayoutParams.privateFlags = + WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; + mWindowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; + mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + mWindowLayoutParams.format = PixelFormat.TRANSPARENT; + mWindowLayoutParams.setTitle("KeyguardBottomArea"); + mWindowLayoutParams.gravity = Gravity.BOTTOM; } private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { @@ -221,6 +286,7 @@ protected void onFinishInflate() { mShortcutHelper = new LockscreenShortcutsHelper(mContext, this); watchForCameraPolicyChanges(); updateCameraVisibility(); + updateLeftButtonVisibility(); mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); mUnlockMethodCache.addListener(this); mLockIcon.update(); @@ -257,6 +323,7 @@ private void updateRightAffordanceIcon() { mCameraImageView.setContentDescription(contentDescription); mCameraImageView.setDefaultFilter(shouldGrayScale ? mGrayScaleFilter : null); updateCameraVisibility(); + updateLeftButtonVisibility(); } private void initAccessibility() { @@ -299,11 +366,13 @@ public void setAccessibilityController(AccessibilityController accessibilityCont public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) { mPhoneStatusBar = phoneStatusBar; updateCameraVisibility(); // in case onFinishInflate() was called too early + updateLeftButtonVisibility(); } public void setUserSetupComplete(boolean userSetupComplete) { mUserSetupComplete = userSetupComplete; updateCameraVisibility(); + updateLeftButtonVisibility(); updateLeftAffordanceIcon(); } @@ -324,6 +393,21 @@ public ResolveInfo resolveCameraIntent() { KeyguardUpdateMonitor.getCurrentUser()); } + private void updateLeftButtonVisibility() { + if (mLeftAffordanceView == null) { + return; + } + boolean visible = mUserSetupComplete; + if (visible) { + if (isTargetCustom(Shortcuts.LEFT_SHORTCUT)) { + visible = !mShortcutHelper.isTargetEmpty(Shortcuts.LEFT_SHORTCUT); + } else { + // Display left shortcut + } + } + mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE); + } + private void updateCameraVisibility() { if (mCameraImageView == null) { // Things are not set up yet; reply hazy, ask again later @@ -364,6 +448,7 @@ private void updateLeftAffordanceIcon() { mLeftAffordanceView.setImageDrawable(drawable); mLeftAffordanceView.setContentDescription(contentDescription); mLeftAffordanceView.setDefaultFilter(shouldGrayScale ? mGrayScaleFilter : null); + updateLeftButtonVisibility(); } public boolean isLeftVoiceAssist() { @@ -397,6 +482,7 @@ private boolean isCameraDisabledByDpm() { private void watchForCameraPolicyChanges() { final IntentFilter filter = new IntentFilter(); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); + mDevicePolicyReceiver = new DevicePolicyBroadcastReceiver(); getContext().registerReceiverAsUser(mDevicePolicyReceiver, UserHandle.ALL, filter, null, null); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); @@ -484,7 +570,9 @@ public void unbindCameraPrewarmService(boolean launched) { public void launchCamera(String source) { final Intent intent; - if (!mShortcutHelper.isTargetCustom(LockscreenShortcutsHelper.Shortcuts.RIGHT_SHORTCUT)) { + if (source.equals(CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) || + source.equals(CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) || + !mShortcutHelper.isTargetCustom(LockscreenShortcutsHelper.Shortcuts.RIGHT_SHORTCUT)) { intent = getCameraIntent(); } else { intent = mShortcutHelper.getIntent(LockscreenShortcutsHelper.Shortcuts.RIGHT_SHORTCUT); @@ -592,6 +680,7 @@ protected void onVisibilityChanged(View changedView, int visibility) { if (changedView == this && visibility == VISIBLE) { mLockIcon.update(); updateCameraVisibility(); + updateLeftButtonVisibility(); } } @@ -628,16 +717,26 @@ public boolean hasOverlappingRendering() { public void onUnlockMethodStateChanged() { mLockIcon.update(); updateCameraVisibility(); + updateLeftButtonVisibility(); } private void inflateCameraPreview() { if (isTargetCustom(Shortcuts.RIGHT_SHORTCUT)) { mPreviewContainer.removeView(mCameraPreview); } else { - mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent()); + Intent cameraIntent = getCameraIntent(); + if (!Objects.equals(cameraIntent, mLastCameraIntent)) { + if (mCameraPreview != null) { + mPreviewContainer.removeView(mCameraPreview); + } + mCameraPreview = mPreviewInflater.inflatePreview(cameraIntent); + if (mCameraPreview != null) { + mPreviewContainer.addView(mCameraPreview); + } + } + mLastCameraIntent = cameraIntent; if (mCameraPreview != null) { - mPreviewContainer.addView(mCameraPreview); - mCameraPreview.setVisibility(View.INVISIBLE); + mCameraPreview.setVisibility(View.GONE); } } } @@ -659,7 +758,7 @@ private void updateLeftPreview() { } if (mLeftPreview != null) { mPreviewContainer.addView(mLeftPreview); - mLeftPreview.setVisibility(View.INVISIBLE); + mLeftPreview.setVisibility(View.GONE); } } @@ -692,13 +791,18 @@ private void startFinishDozeAnimationElement(View element, long delay) { .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); } - private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { + public void cleanup() { + removeKeyguardBottomArea(); + } + + private final class DevicePolicyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { post(new Runnable() { @Override public void run() { updateCameraVisibility(); + updateLeftButtonVisibility(); } }); } @@ -709,6 +813,7 @@ public void run() { @Override public void onUserSwitchComplete(int userId) { updateCameraVisibility(); + updateLeftButtonVisibility(); } @Override @@ -809,4 +914,44 @@ public boolean isTargetCustom(LockscreenShortcutsHelper.Shortcuts shortcut) { public void onChange() { updateCustomShortcuts(); } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mAccessibilityController != null) { + mAccessibilityController.addStateChangedCallback(this); + } + mShortcutHelper.registerAndFetchTargets(); + updateCustomShortcuts(); + mUnlockMethodCache.addListener(this); + watchForCameraPolicyChanges(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mAccessibilityController.removeStateChangedCallback(this); + if (mDevicePolicyReceiver != null) { + mContext.unregisterReceiver(mDevicePolicyReceiver); + mDevicePolicyReceiver = null; + } + mShortcutHelper.cleanup(); + mUnlockMethodCache.removeListener(this); + } + + public interface OnInterceptTouchEventListener { + boolean onInterceptTouchEvent(MotionEvent e); + } + + public void setOnInterceptTouchListener(OnInterceptTouchEventListener listener) { + mInterceptTouchListener = listener; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (mInterceptTouchListener != null) { + return mInterceptTouchListener.onInterceptTouchEvent(ev); + } + return super.onInterceptTouchEvent(ev); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 395f3501856a5..d992b171c5c99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -32,6 +32,8 @@ import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.DejankUtils; +import org.cyanogenmod.internal.util.CmLockPatternUtils; + import static com.android.keyguard.KeyguardHostView.OnDismissAction; import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; @@ -40,15 +42,21 @@ */ public class KeyguardBouncer { + public static final int UNLOCK_SEQUENCE_DEFAULT = 0; + public static final int UNLOCK_SEQUENCE_BOUNCER_FIRST = 1; + public static final int UNLOCK_SEQUENCE_FORCE_BOUNCER = 2; + private Context mContext; private ViewMediatorCallback mCallback; private LockPatternUtils mLockPatternUtils; + private CmLockPatternUtils mCmLockPatternUtils; private ViewGroup mContainer; private StatusBarWindowManager mWindowManager; private KeyguardHostView mKeyguardView; private ViewGroup mRoot; private boolean mShowingSoon; private int mBouncerPromptReason; + private PhoneStatusBar mPhoneStatusBar; private KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -59,12 +67,14 @@ public void onStrongAuthStateChanged(int userId) { public KeyguardBouncer(Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager, - ViewGroup container) { + ViewGroup container, PhoneStatusBar phoneStatusBar) { mContext = context; mCallback = callback; mLockPatternUtils = lockPatternUtils; mContainer = container; mWindowManager = windowManager; + mCmLockPatternUtils = new CmLockPatternUtils(mContext); + mPhoneStatusBar = phoneStatusBar; KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); } @@ -78,7 +88,15 @@ public void show(boolean resetSecuritySelection) { if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) { return; } - + // ensure external keyguard view does not have focus + mPhoneStatusBar.unfocusKeyguardExternalView(); + mPhoneStatusBar.getScrimController().forceHideScrims(false); + // Don't hide bottom area if we are in the middle of a affordance + // launch transition, since once the animation is finished, NPV + // will take care of setting it invisible. + if (!mPhoneStatusBar.mNotificationPanel.isLaunchTransitionRunning()) { + mPhoneStatusBar.mKeyguardBottomArea.setVisibility(View.GONE); + } // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole // Keyguard. If we need to authenticate, show the bouncer. if (!mKeyguardView.dismiss()) { @@ -207,28 +225,42 @@ public boolean onBackPressed() { } /** - * @return True if and only if the security method should be shown before showing the - * notifications on Keyguard, like SIM PIN/PUK. + * @return Whether the bouncer should be shown first, this could be because of SIM PIN/PUK + * or it just could be chosen to be shown first. */ - public boolean needsFullscreenBouncer() { + public int needsFullscreenBouncer() { ensureView(); if (mKeyguardView != null) { SecurityMode mode = mKeyguardView.getSecurityMode(); - return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; + if (mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk) + return UNLOCK_SEQUENCE_FORCE_BOUNCER; + // "Bouncer first" mode currently only available to some security methods. + else if ((mode == SecurityMode.Pattern || mode == SecurityMode.Password + || mode == SecurityMode.PIN) && (mLockPatternUtils != null && + mCmLockPatternUtils.shouldPassToSecurityView( + KeyguardUpdateMonitor.getCurrentUser()))) + return UNLOCK_SEQUENCE_BOUNCER_FIRST; } - return false; + return UNLOCK_SEQUENCE_DEFAULT; } /** * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which * makes this method much faster. */ - public boolean isFullscreenBouncer() { + public int isFullscreenBouncer() { if (mKeyguardView != null) { SecurityMode mode = mKeyguardView.getCurrentSecurityMode(); - return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; + if (mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk) + return UNLOCK_SEQUENCE_FORCE_BOUNCER; + // "Bouncer first" mode currently only available to some security methods. + else if ((mode == SecurityMode.Pattern || mode == SecurityMode.Password + || mode == SecurityMode.PIN) && (mLockPatternUtils != null && + mCmLockPatternUtils.shouldPassToSecurityView( + KeyguardUpdateMonitor.getCurrentUser()))) + return UNLOCK_SEQUENCE_BOUNCER_FIRST; } - return false; + return UNLOCK_SEQUENCE_DEFAULT; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index db378d190b52f..ec307de9d4e88 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project - * + * Copyright (C) 2016 The CyanogenMod 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 @@ -31,8 +31,10 @@ import com.android.systemui.BatteryLevelTextView; import com.android.systemui.BatteryMeterView; +import com.android.systemui.DockBatteryMeterView; import com.android.systemui.R; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.DockBatteryController; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -49,13 +51,15 @@ public class KeyguardStatusBarView extends RelativeLayout { private MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; private BatteryLevelTextView mBatteryLevel; + private BatteryLevelTextView mDockBatteryLevel; - private BatteryController mBatteryController; private KeyguardUserSwitcher mKeyguardUserSwitcher; private int mSystemIconsSwitcherHiddenExpandedMargin; private Interpolator mFastOutSlowInInterpolator; + private UserInfoController mUserInfoController; + public KeyguardStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -67,6 +71,7 @@ protected void onFinishInflate() { mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch); mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar); mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text); + mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text); mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text); loadDimens(); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(), @@ -85,6 +90,14 @@ protected void onConfigurationChanged(Configuration newConfig) { com.android.internal.R.dimen.text_size_small_material)); } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mUserInfoController != null) { + mUserInfoController.removeListener(mUserInfoChangedListener); + } + } + private void loadDimens() { mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize( R.dimen.system_icons_switcher_hidden_expanded_margin); @@ -100,6 +113,9 @@ private void updateVisibilities() { removeView(mMultiUserSwitch); } mBatteryLevel.setVisibility(View.VISIBLE); + if (mDockBatteryLevel != null) { + mDockBatteryLevel.setVisibility(View.VISIBLE); + } } private void updateSystemIconsLayoutParams() { @@ -120,22 +136,43 @@ private void updateUserSwitcher() { } public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; - ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController); - mBatteryLevel.setBatteryController(batteryController); + BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery)); + v.setBatteryStateRegistar(batteryController); + v.setBatteryController(batteryController); + mBatteryLevel.setBatteryStateRegistar(batteryController); + } + + public void setDockBatteryController(DockBatteryController dockBatteryController) { + DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery)); + if (dockBatteryController != null) { + v.setBatteryStateRegistar(dockBatteryController); + mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController); + } else { + if (v != null ) { + removeView(v); + } + if (mDockBatteryLevel != null) { + removeView(mDockBatteryLevel); + mDockBatteryLevel = null; + } + } } public void setUserSwitcherController(UserSwitcherController controller) { mMultiUserSwitch.setUserSwitcherController(controller); } + private UserInfoController.OnUserInfoChangedListener mUserInfoChangedListener = + new UserInfoController.OnUserInfoChangedListener() { + @Override + public void onUserInfoChanged(String name, Drawable picture) { + mMultiUserAvatar.setImageDrawable(picture); + } + }; + public void setUserInfoController(UserInfoController userInfoController) { - userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() { - @Override - public void onUserInfoChanged(String name, Drawable picture) { - mMultiUserAvatar.setImageDrawable(picture); - } - }); + mUserInfoController = userInfoController; + userInfoController.addListener(mUserInfoChangedListener); } public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index 8e58d14a6e14f..cf396556881a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -61,7 +61,8 @@ public LockIcon(Context context, AttributeSet attrs) { @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); - if (isShown()) { + if (isShown() && + KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive()) { mTrustDrawable.start(); } else { mTrustDrawable.stop(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java index 3287f8f8632f2..e89cd3f72838f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java @@ -30,6 +30,7 @@ import com.android.systemui.R; import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; +import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; /** @@ -37,6 +38,8 @@ */ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener { + public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile"; + private QSPanel mQsPanel; private KeyguardUserSwitcher mKeyguardUserSwitcher; private boolean mKeyguardMode; @@ -48,6 +51,7 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener private final int[] mTmpInt2 = new int[2]; private UserSwitcherController mUserSwitcherController; + private UserInfoController mUserInfoController; public MultiUserSwitch(Context context, AttributeSet attrs) { super(context, attrs); @@ -125,9 +129,15 @@ public void onClick(View v) { mTmpInt2); } } else { - Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent( - getContext(), v, ContactsContract.Profile.CONTENT_URI, - ContactsContract.QuickContact.MODE_LARGE, null); + Intent intent; + if (mUserInfoController == null || mUserInfoController.isProfileSetup()) { + intent = ContactsContract.QuickContact.composeQuickContactsIntent( + getContext(), v, ContactsContract.Profile.CONTENT_URI, + ContactsContract.QuickContact.MODE_LARGE, null); + } else { + intent = new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI); + intent.putExtra(INTENT_EXTRA_NEW_LOCAL_PROFILE, true); + } if (mActivityStarter != null) { mActivityStarter.startActivity(intent, true /* dismissShade */); } else { @@ -180,4 +190,7 @@ public boolean hasOverlappingRendering() { return false; } + public void setUserInfoController(UserInfoController userInfoController) { + mUserInfoController = userInfoController; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java new file mode 100644 index 0000000000000..2028132cadbf1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarInsetLayout.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.os.Handler; +import android.os.IBinder; +import android.os.UserHandle; +import android.util.AttributeSet; +import android.view.View; +import android.view.WindowManager; +import android.view.WindowManagerGlobal; +import android.widget.FrameLayout; +import com.android.systemui.R; +import com.android.systemui.cm.UserContentObserver; +import com.android.systemui.statusbar.BaseStatusBar; +import cyanogenmod.providers.CMSettings; + +public class NavBarInsetLayout extends FrameLayout { + public static final String TAG = "NavBarInsetLayout"; + public static final boolean DEBUG = BaseStatusBar.DEBUG; + + boolean mLeftInsetMode = false; + + private int mLeftInset = 0; + private int mRightInset = 0; + + private final Paint mTransparentSrcPaint = new Paint(); + + private SettingsObserver mSettingsObserver; + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mSettingsObserver.observe(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mSettingsObserver.unobserve(); + } + + public NavBarInsetLayout(Context context, AttributeSet attrs) { + super(context, attrs); + setMotionEventSplittingEnabled(false); + mTransparentSrcPaint.setColor(0); + mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + + mSettingsObserver = new SettingsObserver(new Handler()); + } + + @Override + protected boolean fitSystemWindows(Rect insets) { + if (getFitsSystemWindows()) { + boolean paddingChanged; + + if (mLeftInsetMode) { + paddingChanged = insets.right != getPaddingRight() + || insets.top != getPaddingTop() + || insets.bottom != getPaddingBottom(); + + if (insets.left != mLeftInset) { + mLeftInset = insets.left; + applyMargins(); + } + } else { + paddingChanged = insets.left != getPaddingLeft() + || insets.top != getPaddingTop() + || insets.bottom != getPaddingBottom(); + + if (insets.right != mRightInset) { + mRightInset = insets.right; + applyMargins(); + } + } + + // Drop top inset, apply left inset and pass through bottom inset. + if (paddingChanged) { + setPadding(mLeftInsetMode ? 0 : insets.left, + 0, + mLeftInsetMode ? insets.right : 0, + 0); + } + insets.left = 0; + insets.top = 0; + insets.right = 0; + } else { + boolean applyMargins = false; + if (mLeftInset != 0) { + mLeftInset = 0; + applyMargins = true; + } + if (mRightInset != 0) { + mRightInset = 0; + applyMargins = true; + } + if (applyMargins) { + applyMargins(); + } + boolean changed = getPaddingLeft() != 0 + || getPaddingRight() != 0 + || getPaddingTop() != 0 + || getPaddingBottom() != 0; + if (changed) { + setPadding(0, 0, 0, 0); + } + insets.top = 0; + } + return false; + } + + private void applyMargins() { + final int N = getChildCount(); + for (int i = 0; i < N; i++) { + View child = getChildAt(i); + if (child.getLayoutParams() instanceof InsetLayoutParams) { + InsetLayoutParams lp = (InsetLayoutParams) child.getLayoutParams(); + if (!lp.ignoreRightInset) { + if (mLeftInsetMode && lp.leftMargin != mLeftInset) { + lp.leftMargin = mLeftInset; + if (lp.rightMargin != 0) { + lp.rightMargin = 0; + } + } else if (lp.rightMargin != mRightInset) { + lp.rightMargin = mRightInset; + if (lp.leftMargin != 0) { + lp.leftMargin = 0; + } + } + child.requestLayout(); + } + } + } + } + + @Override + public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new InsetLayoutParams(getContext(), attrs); + } + + @Override + protected FrameLayout.LayoutParams generateDefaultLayoutParams() { + return new InsetLayoutParams(InsetLayoutParams.MATCH_PARENT, + InsetLayoutParams.MATCH_PARENT); + } + + private class SettingsObserver extends UserContentObserver { + + public SettingsObserver(Handler handler) { + super(handler); + } + + @Override + protected void observe() { + super.observe(); + mContext.getContentResolver().registerContentObserver( + CMSettings.System.getUriFor(CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE), false, + this, UserHandle.USER_CURRENT); + update(); + } + + @Override + protected void unobserve() { + super.unobserve(); + mContext.getContentResolver().unregisterContentObserver(this); + } + + @Override + protected void update() { + boolean before = mLeftInsetMode; + mLeftInsetMode = CMSettings.System.getIntForUser(mContext.getContentResolver(), + CMSettings.System.NAVBAR_LEFT_IN_LANDSCAPE, 0, UserHandle.USER_CURRENT) == 1; + if (mLeftInsetMode != before) { + applyMargins(); + } + } + } + + public static class InsetLayoutParams extends FrameLayout.LayoutParams { + + public boolean ignoreRightInset; + + public InsetLayoutParams(int width, int height) { + super(width, height); + } + + public InsetLayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + + TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout); + ignoreRightInset = a.getBoolean( + R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false); + a.recycle(); + } + } +} + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java index 87f0e8c021c5e..7b4d7f94fa7e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java @@ -19,6 +19,7 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.res.Resources; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.os.UserHandle; @@ -90,6 +91,8 @@ public class NavbarEditor implements View.OnTouchListener { // just to avoid reallocations private static final int[] sLocation = new int[2]; + private Resources mResources; + /** * Longpress runnable to assign buttons in edit mode */ @@ -151,11 +154,12 @@ public void run() { private static final String DEFAULT_SETTING_STRING = "empty|back|home|recent|empty|menu0"; - public NavbarEditor (View parent, boolean orientation, boolean isRtl) { + public NavbarEditor (View parent, boolean orientation, boolean isRtl, Resources res) { mContext = parent.getContext(); mParent = parent; mVertical = orientation; mRtl = isRtl; + mResources = res; mButtonViews = new ArrayList(); @@ -277,7 +281,8 @@ public boolean onTouch(final View view, MotionEvent event) { if (!mLongPressed && !view.getTag().equals(NAVBAR_HOME) && !view.getTag().equals(NAVBAR_RECENT) && !view.getTag().equals(NAVBAR_BACK)) { final boolean isSmallButton = ArrayUtils.contains(SMALL_BUTTON_IDS, view.getId()); - final ButtonAdapter list = new ButtonAdapter(mContext, mButtonViews, isSmallButton); + final ButtonAdapter list = new ButtonAdapter(mContext, mButtonViews, isSmallButton, + getResources()); AlertDialog.Builder builder = new AlertDialog.Builder(mContext) .setTitle(mContext.getString(R.string.navbar_dialog_title)) @@ -388,7 +393,7 @@ protected void updateKeys() { } } - buttonView.setInfo(button, mVertical, isSmallButton); + buttonView.setInfo(button, mVertical, isSmallButton, getResources()); if (button != NAVBAR_EMPTY && !isSmallButton) { visibleCount++; } @@ -462,6 +467,14 @@ protected void updateLowLights(int visibleCount) { } } + private Resources getResources() { + return mResources != null ? mResources : mContext.getResources(); + } + + public void updateResources(Resources res) { + mResources = res; + } + /** * Class to store info about supported buttons */ @@ -501,9 +514,10 @@ public String toString() { private static class ButtonAdapter extends ArrayAdapter { private ArrayList mTakenItems; + private Resources mResources; public ButtonAdapter(Context context, - ArrayList buttons, boolean smallButtons) { + ArrayList buttons, boolean smallButtons, Resources resources) { super(context, R.layout.navigation_bar_edit_menu_item, R.id.key_text, buildItems(smallButtons)); @@ -514,6 +528,7 @@ public ButtonAdapter(Context context, mTakenItems.add(info); } } + mResources = resources; } private static List buildItems(boolean smallButtons) { @@ -545,7 +560,7 @@ public View getView(int position, View convertView, ViewGroup parent) { text.setEnabled(enabled); ImageView icon = (ImageView) view.findViewById(R.id.key_icon); - icon.setImageResource(info.portResource); + icon.setImageDrawable(mResources.getDrawable(info.portResource)); icon.setColorFilter(new PorterDuffColorFilter( text.getCurrentTextColor(), PorterDuff.Mode.SRC_IN)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 1262f260ac88e..c10f45b73e83a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -34,15 +34,14 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; import android.view.Display; -import android.view.Gravity; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -50,18 +49,15 @@ import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import com.android.systemui.R; -import com.android.systemui.cm.UserContentObserver; import com.android.systemui.statusbar.policy.DeadZone; import com.android.systemui.statusbar.policy.KeyButtonView; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.ArrayList; import cyanogenmod.providers.CMSettings; @@ -216,7 +212,7 @@ public NavigationBarView(Context context, AttributeSet attrs) { mDisplay = ((WindowManager)context.getSystemService( Context.WINDOW_SERVICE)).getDefaultDisplay(); - final Resources res = getContext().getResources(); + final Resources res = getResources(); mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size); mVertical = false; mShowMenu = false; @@ -227,7 +223,8 @@ public NavigationBarView(Context context, AttributeSet attrs) { mBarTransitions = new NavigationBarTransitions(this); mNavBarReceiver = new NavBarReceiver(); - getContext().registerReceiver(mNavBarReceiver, new IntentFilter(NAVBAR_EDIT_ACTION)); + getContext().registerReceiverAsUser(mNavBarReceiver, UserHandle.ALL, + new IntentFilter(NAVBAR_EDIT_ACTION), null, null); mSettingsObserver = new SettingsObserver(new Handler()); } @@ -308,7 +305,7 @@ public View getImeSwitchButton() { private void getIcons(Resources res) { mBackIcon = new BackButtonDrawable(res.getDrawable(R.drawable.ic_sysbar_back)); - mBackLandIcon = mBackIcon; + mBackLandIcon = mBackIcon; mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent); mRecentLandIcon = mRecentIcon; mHomeIcon = res.getDrawable(R.drawable.ic_sysbar_home); @@ -325,6 +322,9 @@ public void updateResources(Resources res) { updateLightsOutResources(container); } } + if (mEditBar != null) { + mEditBar.updateResources(res); + } } private void updateLightsOutResources(ViewGroup container) { @@ -348,7 +348,7 @@ private void updateLightsOutResources(ViewGroup container) { @Override public void setLayoutDirection(int layoutDirection) { - getIcons(mThemedResources != null ? mThemedResources : getContext().getResources()); + getIcons(getResources()); super.setLayoutDirection(layoutDirection); } @@ -422,6 +422,19 @@ public void setNavigationIconHints(int hints, boolean force) { setSideButtonVisibility(false, -1); } } + } else { + setVisibleOrGone(getCurrentView().findViewById(R.id.dpad_left), false); + setVisibleOrGone(getCurrentView().findViewById(R.id.dpad_right), false); + View one = getCurrentView().findViewById(mVertical ? R.id.six : R.id.one); + View six = getCurrentView().findViewById(mVertical ? R.id.one : R.id.six); + if (getSideButtonVisibility(true) != -1) { + one.setVisibility(getSideButtonVisibility(true)); + setSideButtonVisibility(true, - 1); + } + if (getSideButtonVisibility(false) != -1) { + six.setVisibility(getSideButtonVisibility(false)); + setSideButtonVisibility(false, -1); + } } } @@ -570,9 +583,11 @@ public void setMenuVisibility(final boolean show, final boolean force) { @Override public void onFinishInflate() { - mRotatedViews[Configuration.ORIENTATION_PORTRAIT] = findViewById(R.id.rot0); - mRotatedViews[Configuration.ORIENTATION_LANDSCAPE] = findViewById(R.id.rot90); - mCurrentView = mRotatedViews[getResources().getConfiguration().orientation]; + mRotatedViews[Surface.ROTATION_0] = + mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0); + mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90); + mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90]; + mCurrentView = mRotatedViews[Surface.ROTATION_0]; getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener); @@ -589,10 +604,11 @@ public void setLeftInLandscape(boolean leftInLandscape) { } public void reorient() { - int orientation = getResources().getConfiguration().orientation; - mRotatedViews[Configuration.ORIENTATION_PORTRAIT].setVisibility(View.GONE); - mRotatedViews[Configuration.ORIENTATION_LANDSCAPE].setVisibility(View.GONE); - mCurrentView = mRotatedViews[orientation]; + final int rot = mDisplay.getRotation(); + for (int i=0; i<4; i++) { + mRotatedViews[i].setVisibility(View.GONE); + } + mCurrentView = mRotatedViews[rot]; mCurrentView.setVisibility(View.VISIBLE); updateLayoutTransitionsEnabled(); @@ -603,7 +619,7 @@ public void reorient() { } else { mVertical = getWidth() > 0 && getHeight() > getWidth(); } - mEditBar = new NavbarEditor(mCurrentView, mVertical, mIsLayoutRtl); + mEditBar = new NavbarEditor(mCurrentView, mVertical, mIsLayoutRtl, getResources()); updateSettings(); getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener); @@ -697,7 +713,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { private String getResourceName(int resId) { if (resId != 0) { - final android.content.res.Resources res = getContext().getResources(); + final android.content.res.Resources res = getResources(); try { return res.getResourceName(resId); } catch (android.content.res.Resources.NotFoundException ex) { @@ -843,9 +859,9 @@ private void setButtonWithTagVisibility(Object tag, boolean visible) { } } - // TODO LINK TO THIS ONCE THEMES GOES IN - protected void updateResources() { - getIcons(mContext.getResources()); + @Override + public Resources getResources() { + return mThemedResources != null ? mThemedResources : getContext().getResources(); } public class NavBarReceiver extends BroadcastReceiver { @@ -873,19 +889,17 @@ public void updateSettings() { mEditBar.updateKeys(); removeButtonListeners(); updateButtonListeners(); - setDisabledFlags(mDisabledFlags, true /* force */); + updateShowDpadKeys(); setMenuVisibility(mShowMenu, true); } - private class SettingsObserver extends UserContentObserver { + private class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); } - @Override public void observe() { - super.observe(); ContentResolver resolver = getContext().getContentResolver(); resolver.registerContentObserver( CMSettings.System.getUriFor(CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS), @@ -895,23 +909,20 @@ public void observe() { onChange(false); } - @Override public void unobserve() { - super.unobserve(); getContext().getContentResolver().unregisterContentObserver(this); } @Override - protected void update() { - mShowDpadArrowKeys = CMSettings.System.getIntForUser(getContext().getContentResolver(), - CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0; - // reset saved side button visibilities - for (int i = 0; i < mSideButtonVisibilities.length; i++) { - for (int j = 0; j < mSideButtonVisibilities[i].length; j++) { - mSideButtonVisibilities[i][j] = -1; - } - } - setNavigationIconHints(mNavigationIconHints, true); + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + updateShowDpadKeys(); } } + + private void updateShowDpadKeys() { + mShowDpadArrowKeys = CMSettings.System.getIntForUser(getContext().getContentResolver(), + CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0; + setNavigationIconHints(mNavigationIconHints, true); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index a75fb3eea965f..e4e02a74184ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -18,6 +18,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.ArgbEvaluator; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; @@ -25,25 +26,33 @@ import android.app.ActivityManager; import android.app.StatusBarManager; import android.content.Context; +import android.content.SharedPreferences; import android.content.pm.ResolveInfo; import android.content.res.Configuration; +import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Point; import android.graphics.Rect; import android.net.Uri; import android.os.Handler; import android.os.PowerManager; -import android.provider.Settings; +import android.os.RemoteException; +import android.preference.PreferenceManager; import android.util.AttributeSet; import android.util.MathUtils; +import android.view.Display; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewTreeObserver; import android.view.WindowInsets; +import android.view.WindowManager; +import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -57,8 +66,9 @@ import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.R; +import com.android.systemui.SwipeHelper; import com.android.systemui.qs.QSContainer; -import com.android.systemui.qs.QSPanel; +import com.android.systemui.qs.QSDragPanel; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.FlingAnimationUtils; @@ -68,19 +78,22 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; +import com.android.systemui.statusbar.policy.LiveLockScreenController; +import com.android.systemui.statusbar.policy.WeatherController; +import com.android.systemui.statusbar.policy.WeatherControllerImpl; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.StackStateAnimator; + import cyanogenmod.providers.CMSettings; +import cyanogenmod.weather.util.WeatherUtils; import java.util.List; -import cyanogenmod.providers.CMSettings; - public class NotificationPanelView extends PanelView implements ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener, View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener, KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener, - HeadsUpManager.OnHeadsUpChangedListener { + HeadsUpManager.OnHeadsUpChangedListener, WeatherController.Callback { private static final boolean DEBUG = false; @@ -98,14 +111,26 @@ public class NotificationPanelView extends PanelView implements private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1); + private static final long SLIDE_PANEL_IN_ANIMATION_DURATION = 300; + + private static final String KEY_USER_EXPANDED_NOTIFICATIONS_IN_KEYGUARD = + "user_expanded_notifications_in_keyguard"; + private static final String KEY_USER_INTERACTED_WITH_LLS = + "user_interacted_with_lls"; + private static final String KEY_USER_UNLOCKED = + "user_unlocked"; + private static final String KEY_USER_RETURNED_FROM_LLS = + "user_returned_from_lls"; + public static final long DOZE_ANIMATION_DURATION = 700; + private KeyguardAffordanceHelper mAfforanceHelper; private StatusBarHeaderView mHeader; private KeyguardUserSwitcher mKeyguardUserSwitcher; private KeyguardStatusBarView mKeyguardStatusBar; private QSContainer mQsContainer; - private QSPanel mQsPanel; + private QSDragPanel mQsPanel; private KeyguardStatusView mKeyguardStatusView; private ObservableScrollView mScrollView; private TextView mClockView; @@ -230,11 +255,112 @@ public void run() { private Handler mHandler = new Handler(); private SettingsObserver mSettingsObserver; - private boolean mOneFingerQuickSettingsIntercept; + private int mOneFingerQuickSettingsIntercept; private boolean mDoubleTapToSleepEnabled; private int mStatusBarHeaderHeight; private GestureDetector mDoubleTapGesture; + // Used to identify whether showUnlock() can dismiss the keyguard + // or not. + // TODO - add a new state to make it easier to identify keyguard vs + // LiveLockscreen + public boolean mCanDismissKeyguard; + + // Used to track which direction the user is currently + // interacting with and ensure they don't alternate back + // and forth. Reset every MOTION_UP/MOTION_CANCEL + private SwipeLockedDirection mLockedDirection; + + private SwipeHelper mSwipeHelper; + private final int mMinimumFlingVelocity; + private final int mScreenHeight; + private LiveLockScreenController mLiveLockscreenController; + private final GestureDetector mGestureDetector; + private ViewLinker mViewLinker; + private final UnlockMethodCache mUnlockMethodCache; + private boolean mDetailScrollLock; + + private boolean mKeyguardWeatherEnabled; + private TextView mKeyguardWeatherInfo; + private WeatherControllerImpl mWeatherController; + + // Keep track of common user interactions on the lock screen + private boolean mUserUnlocked; + private boolean mUserExpandedNotifications; + private boolean mUserInteractedWithLiveLockScreen; + private boolean mUserReturnedFromLiveLockScreen; + + private boolean mScreenOnHintsEnabled; + + private enum SwipeLockedDirection { + UNKNOWN, + HORIZONTAL, + VERTICAL + } + + // Handles swiping to the LiveLockscreen from keyguard + SwipeHelper.SimpleCallback mSwipeCallback = new SwipeHelper.SimpleCallback() { + @Override + public View getChildAtPosition(MotionEvent ev) { + return mViewLinker.getParent(); + } + + @Override + public View getChildContentView(View v) { + return mViewLinker.getParent(); + } + + @Override + public boolean canChildBeDismissed(View v) { + return true; + } + + @Override + public void onChildDismissed(View v) { + mCanDismissKeyguard = false; + mStatusBar.focusKeyguardExternalView(); + mLiveLockscreenController.onLiveLockScreenFocusChanged(true /* hasFocus */); + if (!mUserInteractedWithLiveLockScreen) { + mUserInteractedWithLiveLockScreen = true; + saveUserInteractedWithLls(true); + } + if (!mUserReturnedFromLiveLockScreen) { + startShowNotificationsHintAnimation(); + } + resetAlphaTranslation(); + // Enables the left edge gesture to allow user + // to return to keyguard + try { + WindowManagerGlobal.getWindowManagerService() + .setLiveLockscreenEdgeDetector(true); + } catch (RemoteException e){ + e.printStackTrace(); + } + } + + @Override + public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) { + // Let live lockscreen know of swipe progress to allow + // them to translate content in. + mLiveLockscreenController.getLiveLockScreenView() + .onLockscreenSlideOffsetChanged(swipeProgress); + + // Fade out scrim background + float alpha = ScrimController.SCRIM_BEHIND_ALPHA_KEYGUARD - (1f - swipeProgress); + alpha = Math.max(0, alpha); + mStatusBar.getScrimController().setScrimBehindColor(alpha); + return false; + } + + private void resetAlphaTranslation() { + mNotificationStackScroller.setTranslationX(0); + mNotificationStackScroller.setAlpha(1f); + + mKeyguardStatusView.setTranslationX(0); + mKeyguardStatusView.setAlpha(1f); + } + }; + public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(!DEBUG); @@ -249,12 +375,78 @@ public boolean onDoubleTap(MotionEvent e) { return true; } }); + + Resources res = getContext().getResources(); + final int gradientStart = res.getColor(R.color.live_lockscreen_gradient_start); + final int gradientEnd = res.getColor(R.color.live_lockscreen_gradient_end); + mGestureDetector = new GestureDetector(getContext(), + new GestureDetector.SimpleOnGestureListener() { + private float mDown; + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + // Ensure we only capture swipes in the up direction + if (velocityY > 0 || Math.abs(velocityY) <= mMinimumFlingVelocity) { + return false; + } + mCanDismissKeyguard = true; + mStatusBar.showBouncer(); + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + float delta = mDown - e2.getRawY(); + delta = Math.max(0, delta); + float screenHeightHalf = (float) mScreenHeight / 2f; + int color = (Integer) ArgbEvaluator.getInstance() + .evaluate(delta / screenHeightHalf, gradientStart, gradientEnd); + mKeyguardBottomArea.setBackgroundColor(color); + return super.onScroll(e1, e2, distanceX, distanceY); + } + + @Override + public boolean onDown(MotionEvent e) { + mDown = e.getRawY(); + mKeyguardBottomArea.expand(true); + return true; + } + }); + + mSwipeHelper = new SwipeHelper(SwipeHelper.X, + SwipeHelper.SWIPE_ZONE_LEFT, mSwipeCallback, mContext); + mSwipeHelper.setSwipeProgressFadeEnd(1.0f); + mMinimumFlingVelocity = ViewConfiguration.get(getContext()) + .getScaledMinimumFlingVelocity(); + + WindowManager windowManager = (WindowManager) mContext + .getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + Point point = new Point(); + display.getSize(point); + mScreenHeight = point.y; + mUnlockMethodCache = UnlockMethodCache.getInstance(context); + + mScreenOnHintsEnabled = res.getBoolean(R.bool.config_showScreenOnLockScreenHints); + mUserUnlocked = getUserUnlocked(); + mUserExpandedNotifications = getUserExpandedNotificationsInKeyguard(); + mUserInteractedWithLiveLockScreen = getUserInteractedWithLls(); + mUserReturnedFromLiveLockScreen = getUserReturnedFromLls(); } public void setStatusBar(PhoneStatusBar bar) { mStatusBar = bar; } + public void setLiveController(LiveLockScreenController liveController) { + mLiveLockscreenController = liveController; + } + + public void setWeatherController(WeatherControllerImpl weatherController) { + mWeatherController = weatherController; + mWeatherController.addCallback(this); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -263,10 +455,10 @@ protected void onFinishInflate() { mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header); mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view); mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container); - mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel); + mQsPanel = (QSDragPanel) findViewById(R.id.quick_settings_panel); + mQsPanel.setPanelView(this); mClockView = (TextView) findViewById(R.id.clock_view); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); - mScrollView.setListener(this); mScrollView.setFocusable(false); mReserveNotificationSpace = findViewById(R.id.reserve_notification_space); mNotificationContainerParent = (NotificationsQuickSettingsContainer) @@ -283,7 +475,64 @@ protected void onFinishInflate() { android.R.interpolator.fast_out_linear_in); mDozeAnimationInterpolator = AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.linear_out_slow_in); - mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area); + + mViewLinker = new ViewLinker(mNotificationStackScroller, + new ViewLinker.LinkInfo(mKeyguardStatusBar, ViewLinker.LINK_ALPHA), + new ViewLinker.LinkInfo(mKeyguardStatusView, ViewLinker.LINK_ALPHA + | ViewLinker.LINK_TRANSLATION)); + + mKeyguardBottomArea = (KeyguardBottomAreaView) View.inflate(getContext(), + R.layout.keyguard_bottom_area, null); + /** Keyguard bottom area lives in a separate window, and as such, + * we must redirect its touch events through the proper flow + */ + mKeyguardBottomArea.setOnInterceptTouchListener(new KeyguardBottomAreaView.OnInterceptTouchEventListener() { + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + boolean intercept = false; + if (mLiveLockscreenController.getLiveLockScreenHasFocus()) { + // Handles swipe up to fade/dismiss when showing + // live lock screen + intercept = mAfforanceHelper.onInterceptTouchEvent(e); + if (!intercept) { + intercept = mGestureDetector.onTouchEvent(e); + } + } else { + intercept = NotificationPanelView.this.onInterceptTouchEvent(e); + } + return intercept; + } + }); + mKeyguardBottomArea.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent e) { + int action = e.getAction(); + + boolean isCancelOrUp = action == MotionEvent.ACTION_UP || + action == MotionEvent.ACTION_CANCEL; + if (isCancelOrUp) { + mKeyguardBottomArea.setBackground(null); + } + + boolean intercept = false; + if (mLiveLockscreenController.getLiveLockScreenHasFocus()) { + intercept = mAfforanceHelper.onTouchEvent(e); + // If the touch did not originate on the affordance helper, + // we must collapse the panel here since we can't rely on + // the swipe callbacks from being invoked. + if (isCancelOrUp && !isAffordanceSwipeInProgress()) { + mKeyguardBottomArea.expand(false); + } + if (!intercept) { + intercept = mGestureDetector.onTouchEvent(e); + } + } else { + intercept = NotificationPanelView.this.onTouchEvent(e); + } + return intercept; + } + }); + mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim); mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext()); mLastOrientation = getResources().getConfiguration().orientation; @@ -300,18 +549,26 @@ public void onLayoutChange(View v, int left, int top, int right, int bottom, } } }); + + mKeyguardWeatherInfo = (TextView) mKeyguardStatusView.findViewById(R.id.weather_info); + } + + public boolean isAffordanceSwipeInProgress() { + return mAfforanceHelper.isSwipingInProgress(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mSettingsObserver.observe(); + mScrollView.setListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mSettingsObserver.unobserve(); + mWeatherController.removeCallback(this); } @Override @@ -591,6 +848,10 @@ public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent eve @Override public boolean onInterceptTouchEvent(MotionEvent event) { + // Reset locked direction + mLockedDirection = SwipeLockedDirection.UNKNOWN; + mCanDismissKeyguard = true; + if (mBlockTouches) { return false; } @@ -601,10 +862,26 @@ public boolean onInterceptTouchEvent(MotionEvent event) { MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1); return true; } + if (mQsPanel.isOnSettingsPage() && isInQsArea(event.getX(), event.getY(), false) + && mQsExpanded) { + mIntercepting = false; + // we explicitly do not intercept the touch event here to let the qs settings page + // scroll as necessary while not blocking horizontal swipes and allowing the panel + // to be collapsed when grabbed below the qs settings page as well. + return false; + } if (!isFullyCollapsed() && onQsIntercept(event)) { return true; } - return super.onInterceptTouchEvent(event); + + if (isKeyguardInteractiveAndShowing() || mStatusBar.isKeyguardShowingMedia() || + (mUnlockMethodCache.isTrustManaged() && mAfforanceHelper.isOnLockIcon(event))) { + return super.onInterceptTouchEvent(event); + } + + // We want both, we really do + return mSwipeHelper.onInterceptTouchEvent(event) + & super.onInterceptTouchEvent(event); } private boolean onQsIntercept(MotionEvent event) { @@ -759,6 +1036,12 @@ public boolean onTouchEvent(MotionEvent event) { if (mBlockTouches) { return false; } + + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + mKeyguardBottomArea.setBackground(null); + } + if (mDoubleTapToSleepEnabled && mStatusBarState == StatusBarState.KEYGUARD && event.getY() < mStatusBarHeaderHeight) { @@ -772,7 +1055,8 @@ public boolean onTouchEvent(MotionEvent event) { } if ((!mIsExpanding || mHintAnimationRunning) && !mQsExpanded - && mStatusBar.getBarState() != StatusBarState.SHADE) { + && (mStatusBar.getBarState() != StatusBarState.SHADE + || mLiveLockscreenController.getLiveLockScreenHasFocus())) { mAfforanceHelper.onTouchEvent(event); } if (mOnlyAffordanceInThisMotion) { @@ -786,10 +1070,39 @@ public boolean onTouchEvent(MotionEvent event) { MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1); updateVerticalPanelPosition(event.getX()); } - super.onTouchEvent(event); + + if (isKeyguardInteractiveAndShowing() || mStatusBar.isKeyguardShowingMedia() || + (mUnlockMethodCache.isTrustManaged() && mAfforanceHelper.isOnLockIcon(event))) { + super.onTouchEvent(event); + return true; + } + + if ((!mIsExpanding || mHintAnimationRunning) + && !mQsExpanded + && mLockedDirection != SwipeLockedDirection.VERTICAL + && mStatusBar.getBarState() != StatusBarState.SHADE) { + mSwipeHelper.onTouchEvent(event); + if (mSwipeHelper.isDragging()) { + mLockedDirection = SwipeLockedDirection.HORIZONTAL; + } + if (mLockedDirection == SwipeLockedDirection.HORIZONTAL) { + requestDisallowInterceptTouchEvent(true); + return true; + } + } + + if (super.onTouchEvent(event)) { + mLockedDirection = SwipeLockedDirection.VERTICAL; + } return true; } + private boolean isKeyguardInteractiveAndShowing() { + return mLiveLockscreenController.getLiveLockScreenHasFocus() || + mStatusBar.getBarState() != StatusBarState.KEYGUARD || + !mLiveLockscreenController.isLiveLockScreenInteractive(); + } + private boolean handleQsTouch(MotionEvent event) { final int action = event.getActionMasked(); if (action == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f @@ -821,7 +1134,8 @@ private boolean handleQsTouch(MotionEvent event) { mTwoFingerQsExpandPossible = true; } if (mTwoFingerQsExpandPossible && isOpenQsEvent(event) - && event.getY(event.getActionIndex()) < mStatusBarMinHeight) { + && event.getY(event.getActionIndex()) < mStatusBarMinHeight + && mExpandedHeight <= mQsPeekHeight) { MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1); mQsExpandImmediate = true; requestPanelHeightUpdate(); @@ -834,9 +1148,14 @@ private boolean handleQsTouch(MotionEvent event) { } private boolean isInQsArea(float x, float y) { + return isInQsArea(x, y, true); + } + + private boolean isInQsArea(float x, float y, boolean includeNotifications) { return (x >= mScrollView.getX() && x <= mScrollView.getX() + mScrollView.getWidth()) && - (y <= mNotificationStackScroller.getBottomMostNotificationBottom() - || y <= mQsContainer.getY() + mQsContainer.getHeight()); + ((includeNotifications + && y <= mNotificationStackScroller.getBottomMostNotificationBottom()) + || y <= mQsContainer.getY() + mQsContainer.getHeight()); } private boolean isOpenQsEvent(MotionEvent event) { @@ -857,16 +1176,24 @@ private boolean isOpenQsEvent(MotionEvent event) { final float w = getMeasuredWidth(); final float x = event.getX(); float region = (w * (1.f/4.f)); // TODO overlay region fraction? - final boolean showQsOverride = mOneFingerQuickSettingsIntercept && - (isLayoutRtl() ? (x < region) : (w - region < x) - && mStatusBarState == StatusBarState.SHADE); + boolean showQsOverride = false; + + switch (mOneFingerQuickSettingsIntercept) { + case 1: // Right side pulldown + showQsOverride = isLayoutRtl() ? (x < region) : (w - region < x); + break; + case 2: // Left side pulldown + showQsOverride = isLayoutRtl() ? (w - region < x) : (x < region); + break; + } + showQsOverride &= mStatusBarState == StatusBarState.SHADE; return twoFingerDrag || showQsOverride || stylusButtonClickDrag || mouseButtonClickDrag; } private void handleQsDown(MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN - && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) { + && shouldQuickSettingsIntercept(event.getX(), event.getRawY(), -1)) { mQsTracking = true; onQsExpansionStarted(); mInitialHeightOnTouch = mQsExpansionHeight; @@ -948,8 +1275,13 @@ private void onQsTouch(MotionEvent event) { mTrackingPointer = -1; trackMovement(event); float fraction = getQsExpansionFraction(); - if ((fraction != 0f || y >= mInitialTouchY) - && (fraction != 1f || y <= mInitialTouchY)) { + final boolean fling = (fraction != 0f || y >= mInitialTouchY) + && (fraction != 1f || y <= mInitialTouchY); + final boolean flingExpand = Math.abs(getCurrentVelocity()) + > mFlingAnimationUtils.getMinVelocityPxPerSecond(); + final boolean detailFling = mDetailScrollLock && mQsExpanded + && flingExpand; + if ((fling && !mDetailScrollLock) || detailFling) { flingQsWithCurrentVelocity(y, event.getActionMasked() == MotionEvent.ACTION_CANCEL); } else { @@ -1050,9 +1382,17 @@ public void setBarState(int statusBarState, boolean keyguardFadingAway, mStatusBarState = statusBarState; mKeyguardShowing = keyguardShowing; + if (oldState != statusBarState && statusBarState == StatusBarState.KEYGUARD) { + mCanDismissKeyguard = true; + } - if (goingToFullShade || (oldState == StatusBarState.KEYGUARD - && statusBarState == StatusBarState.SHADE_LOCKED)) { + boolean keyguardToShadeLocked = oldState == StatusBarState.KEYGUARD + && statusBarState == StatusBarState.SHADE_LOCKED; + if (goingToFullShade || keyguardToShadeLocked) { + if (keyguardToShadeLocked && !mUserExpandedNotifications) { + mUserExpandedNotifications = true; + saveUserExpandedNotificationsInKeyguard(true); + } animateKeyguardStatusBarOut(); animateHeaderSlidingIn(); } else if (oldState == StatusBarState.SHADE_LOCKED @@ -1067,7 +1407,13 @@ public void setBarState(int statusBarState, boolean keyguardFadingAway, mAfforanceHelper.updatePreviews(); } } - if (keyguardShowing) { + if (oldState != StatusBarState.SHADE && statusBarState == StatusBarState.SHADE && + !mUserUnlocked) { + mUserUnlocked = true; + saveUserUnlocked(true); + } + if (statusBarState == StatusBarState.KEYGUARD || + statusBarState == StatusBarState.SHADE_LOCKED) { updateDozingVisibilities(false /* animate */); } resetVerticalPanelPosition(); @@ -1344,8 +1690,7 @@ private void setQsExpansion(float height) { if (mKeyguardShowing) { updateHeaderKeyguard(); } - if (mStatusBarState == StatusBarState.SHADE_LOCKED - || mStatusBarState == StatusBarState.KEYGUARD) { + if (mStatusBarState == StatusBarState.KEYGUARD) { updateKeyguardBottomAreaAlpha(); } if (mStatusBarState == StatusBarState.SHADE && mQsExpanded @@ -1526,7 +1871,8 @@ private boolean shouldQuickSettingsIntercept(float x, float y, float yDiff) { && y >= header.getTop() && y <= header.getBottom(); if (mQsExpanded) { - return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y); + return onHeader || mDetailScrollLock + || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y); } else { return onHeader; } @@ -1616,7 +1962,7 @@ private void updatePanelExpanded() { */ private int getTempQsMaxExpansion() { int qsTempMaxExpansion = mQsMaxExpansionHeight; - if (mScrollYOverride != -1) { + if (mScrollYOverride != -1 && !mDetailScrollLock) { qsTempMaxExpansion -= mScrollYOverride; } return qsTempMaxExpansion; @@ -1783,12 +2129,14 @@ private float getKeyguardContentsAlpha() { } private void updateHeaderKeyguardAlpha() { + if (mSwipeHelper.isDragging()) { + return; + } float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2); mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion) * mKeyguardStatusBarAnimateAlpha); mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f && !mDozing ? VISIBLE : INVISIBLE); - mStatusBar.getVisualizer().setAlpha(mKeyguardStatusBar.getAlpha()); } private void updateHeaderKeyguard() { @@ -1798,6 +2146,9 @@ private void updateHeaderKeyguard() { private void updateKeyguardBottomAreaAlpha() { float alpha = Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction()); + if (mLiveLockscreenController.getLiveLockScreenHasFocus()) { + alpha = 1f; + } mKeyguardBottomArea.setAlpha(alpha); mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS @@ -2021,10 +2372,12 @@ public void onAnimationToSideEnded() { mLaunchAnimationEndRunnable.run(); mLaunchAnimationEndRunnable = null; } + mKeyguardBottomArea.setVisibility(View.GONE); } @Override protected void startUnlockHintAnimation() { + mKeyguardBottomArea.expand(true); super.startUnlockHintAnimation(); startHighlightIconAnimation(getCenterIcon()); } @@ -2059,11 +2412,13 @@ public void onSwipingStarted(boolean rightIcon) { requestDisallowInterceptTouchEvent(true); mOnlyAffordanceInThisMotion = true; mQsTracking = false; + mKeyguardBottomArea.expand(true); } @Override public void onSwipingAborted() { mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */); + mKeyguardBottomArea.expand(false); } @Override @@ -2072,6 +2427,8 @@ public void onIconClicked(boolean rightIcon) { return; } mHintAnimationRunning = true; + mKeyguardBottomArea.expand(true); + mKeyguardBottomArea.getIndicationView().animate().cancel(); mAfforanceHelper.startHintAnimation(rightIcon, new Runnable() { @Override public void run() { @@ -2252,11 +2609,6 @@ private void updateEmptyShadeView() { // Hide "No notifications" in QS. mNotificationStackScroller.updateEmptyShadeView(mShadeEmpty && !mQsExpanded); - if (mStatusBarState == StatusBarState.KEYGUARD - && (!mQsExpanded || mQsExpandImmediate || mIsExpanding - && mQsExpandedWhenExpandingStarted)) { - positionClockAndNotifications(); - } } public void setQsScrimEnabled(boolean qsScrimEnabled) { @@ -2280,6 +2632,11 @@ public void run() { public void onScreenTurningOn() { mKeyguardStatusView.refreshTime(); + if (shouldShowScreenOnHints()) { + startScreenOnHintAnimation(mLiveLockscreenController.isLiveLockScreenInteractive() && + !mUserInteractedWithLiveLockScreen, + !mUserUnlocked, !mUserExpandedNotifications); + } } @Override @@ -2399,7 +2756,7 @@ private void setClosingWithAlphaFadeout(boolean closing) { * @param x the x-coordinate the touch event */ private void updateVerticalPanelPosition(float x) { - if (mNotificationStackScroller.getWidth() * 1.75f > getWidth()) { + if (mNotificationStackScroller.getWidth() * 1.75f >= getWidth()) { resetVerticalPanelPosition(); return; } @@ -2441,6 +2798,10 @@ protected boolean isPanelVisibleBecauseOfHeadsUp() { return mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway; } + public KeyguardBottomAreaView getKeyguardBottomArea() { + return mKeyguardBottomArea; + } + class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); @@ -2452,6 +2813,8 @@ void observe() { CMSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN), false, this); resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE), false, this); + resolver.registerContentObserver(CMSettings.Secure.getUriFor( + CMSettings.Secure.LOCK_SCREEN_WEATHER_ENABLED), false, this); update(); } @@ -2473,9 +2836,17 @@ public void onChange(boolean selfChange, Uri uri) { public void update() { ContentResolver resolver = mContext.getContentResolver(); mOneFingerQuickSettingsIntercept = CMSettings.System.getInt( - resolver, CMSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN, 1) == 1; + resolver, CMSettings.System.STATUS_BAR_QUICK_QS_PULLDOWN, 1); mDoubleTapToSleepEnabled = CMSettings.System.getInt( resolver, CMSettings.System.DOUBLE_TAP_SLEEP_GESTURE, 1) == 1; + + boolean wasKeyguardWeatherEnabled = mKeyguardWeatherEnabled; + mKeyguardWeatherEnabled = CMSettings.Secure.getInt( + resolver, CMSettings.Secure.LOCK_SCREEN_WEATHER_ENABLED, 0) == 1; + if (mWeatherController != null + && wasKeyguardWeatherEnabled != mKeyguardWeatherEnabled) { + onWeatherChanged(mWeatherController.getWeatherInfo()); + } } } @@ -2489,6 +2860,8 @@ public void launchCamera(boolean animate, int source) { mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP; } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) { mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE; + } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE; } else { // Default. @@ -2498,7 +2871,8 @@ public void launchCamera(boolean animate, int source) { // If we are launching it when we are occluded already we don't want it to animate, // nor setting these flags, since the occluded state doesn't change anymore, hence it's // never reset. - if (!isFullyCollapsed()) { + if (!isFullyCollapsed() && mLastCameraLaunchSource == + KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE) { mLaunchingAffordance = true; setLaunchingAffordance(true); } else { @@ -2546,4 +2920,159 @@ private boolean isForegroundApp(String pkgName) { List tasks = am.getRunningTasks(1); return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName()); } + + public void setDetailRequestedScrollLock(boolean detailScrollFlag) { + if (mDetailScrollLock != detailScrollFlag) { + if (mStatusBarState != StatusBarState.SHADE) { + mDetailScrollLock = false; + } else { + mDetailScrollLock = detailScrollFlag; + } + if (!detailScrollFlag && getQsExpansionFraction() > 0.3f) { + flingSettings(getCurrentVelocity(), true, new Runnable() { + @Override + public void run() { + mStackScrollerOverscrolling = false; + mQsExpansionFromOverscroll = false; + updateQsState(); + updateHeader(); + updateMaxHeadsUpTranslation(); + updatePanelExpanded(); + requestLayout(); + } + }, false); + } else { + requestLayout(); + } + } + } + + @Override + public void onWeatherChanged(WeatherController.WeatherInfo info) { + if (!mKeyguardWeatherEnabled || Double.isNaN(info.temp) || info.condition == null) { + mKeyguardWeatherInfo.setVisibility(GONE); + } else { + mKeyguardWeatherInfo.setText(mContext.getString( + R.string.keyguard_status_view_weather_format, + WeatherUtils.formatTemperature(info.temp, info.tempUnit), + info.condition)); + mKeyguardWeatherInfo.setVisibility(VISIBLE); + } + } + + private class SlideInAnimationListener implements ValueAnimator.AnimatorUpdateListener, + ValueAnimator.AnimatorListener { + @Override + public void onAnimationStart(Animator animator) {} + + @Override + public void onAnimationEnd(Animator animator) { + animationFinished(animator); + } + + @Override + public void onAnimationCancel(Animator animator) { + animationFinished(animator); + } + + @Override + public void onAnimationRepeat(Animator animator) {} + + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + View statusBarView = mStatusBar.getStatusBarWindow(); + if (valueAnimator.getAnimatedFraction() > 0 && + statusBarView.getVisibility() != View.VISIBLE) { + statusBarView.setVisibility(View.VISIBLE); + } + float translationX = (Float) valueAnimator.getAnimatedValue(); + float alpha = valueAnimator.getAnimatedFraction(); + + mViewLinker.getParent().setTranslationX(translationX); + mViewLinker.getParent().setAlpha(alpha); + + float alpha1 = ScrimController.SCRIM_BEHIND_ALPHA_KEYGUARD * alpha; + alpha1 = Math.max(0, alpha1); + mStatusBar.getScrimController().setScrimBehindColor(alpha1); + mLiveLockscreenController.getLiveLockScreenView() + .onLockscreenSlideOffsetChanged(alpha); + } + + private void animationFinished(Animator animator) { + mLiveLockscreenController.onLiveLockScreenFocusChanged(false); + } + } + + private SlideInAnimationListener mSlideInAnimationListener = new SlideInAnimationListener(); + + public void slideLockScreenIn() { + mNotificationStackScroller.setVisibility(View.VISIBLE); + mNotificationStackScroller.setAlpha(0f); + mNotificationStackScroller.setTranslationX(-mNotificationStackScroller.getWidth()); + mKeyguardStatusView.setVisibility(View.VISIBLE); + mKeyguardStatusView.setAlpha(0f); + mKeyguardStatusView.setTranslationX(mNotificationStackScroller.getTranslationX()); + mKeyguardStatusBar.setAlpha(0f); + + mStatusBar.getScrimController().setScrimBehindColor(0f); + ValueAnimator animator = ValueAnimator.ofFloat( + mNotificationStackScroller.getTranslationX(), + 0f); + animator.setDuration(SLIDE_PANEL_IN_ANIMATION_DURATION); + animator.addUpdateListener(mSlideInAnimationListener); + animator.addListener(mSlideInAnimationListener); + animator.start(); + + if (!mUserReturnedFromLiveLockScreen) { + mUserReturnedFromLiveLockScreen = true; + saveUserReturnedFromLls(true); + } + } + + private void saveBooleanSharedPreference(String key, boolean value) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); + prefs.edit().putBoolean(key, value).apply(); + } + + private boolean getSharedPreferenceBoolean(String key, boolean defValue) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); + return prefs.getBoolean(key, defValue); + } + + private void saveUserExpandedNotificationsInKeyguard(boolean expanded) { + saveBooleanSharedPreference(KEY_USER_EXPANDED_NOTIFICATIONS_IN_KEYGUARD, expanded); + } + + private boolean getUserExpandedNotificationsInKeyguard() { + return getSharedPreferenceBoolean(KEY_USER_EXPANDED_NOTIFICATIONS_IN_KEYGUARD, false); + } + + private void saveUserInteractedWithLls(boolean interacted) { + saveBooleanSharedPreference(KEY_USER_INTERACTED_WITH_LLS, interacted); + } + + private boolean getUserInteractedWithLls() { + return getSharedPreferenceBoolean(KEY_USER_INTERACTED_WITH_LLS, false); + } + + private void saveUserUnlocked(boolean unlocked) { + saveBooleanSharedPreference(KEY_USER_UNLOCKED, unlocked); + } + + private boolean getUserUnlocked() { + return getSharedPreferenceBoolean(KEY_USER_UNLOCKED, false); + } + + private void saveUserReturnedFromLls(boolean revealed) { + saveBooleanSharedPreference(KEY_USER_RETURNED_FROM_LLS, revealed); + } + + private boolean getUserReturnedFromLls() { + return getSharedPreferenceBoolean(KEY_USER_RETURNED_FROM_LLS, false); + } + + public boolean shouldShowScreenOnHints() { + return mScreenOnHintsEnabled && mStatusBar.isDeviceProvisioned() && + mStatusBarState == StatusBarState.KEYGUARD; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 9a8fa98f7840b..3a2c84cf6ba9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -19,6 +19,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; @@ -26,6 +27,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; +import android.view.View; import android.view.ViewConfiguration; import android.view.ViewTreeObserver; import android.view.animation.AnimationUtils; @@ -40,8 +42,6 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.HeadsUpManager; -import cyanogenmod.power.PerformanceManager; - import java.io.FileDescriptor; import java.io.PrintWriter; @@ -49,6 +49,9 @@ public abstract class PanelView extends FrameLayout { public static final boolean DEBUG = PanelBar.DEBUG; public static final String TAG = PanelView.class.getSimpleName(); + private static final long ANIMATION_FADE_DURATION = 1000L; + private static final long HINT_DELAY_DURATION = 1500L; + private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); } @@ -88,7 +91,19 @@ private final void logf(String fmt, Object... args) { private VelocityTrackerInterface mVelocityTracker; private FlingAnimationUtils mFlingAnimationUtils; - private final PerformanceManager mPerf; + private boolean mUpdateExpandOnLayout; + private View.OnLayoutChangeListener mLayoutChangeListener = new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + // update expand height + if (mHeightAnimator != null && mExpanding && mUpdateExpandOnLayout && !mJustPeeked) { + final int maxPanelHeight = getMaxPanelHeight(); + final PropertyValuesHolder[] values = mHeightAnimator.getValues(); + values[0].setFloatValues(maxPanelHeight); + } + } + }; /** * Whether an instant expand request is currently pending and we are just waiting for layout. @@ -109,6 +124,9 @@ private final void logf(String fmt, Object... args) { private boolean mPeekPending; private boolean mCollapseAfterPeek; + private boolean mShowExpandHint; + private boolean mShowUnlockHint; + private boolean mScreenOnHintAnimationRunning; /** * Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time. @@ -206,8 +224,6 @@ public PanelView(Context context, AttributeSet attrs) { mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); mBounceInterpolator = new BounceInterpolator(); - - mPerf = PerformanceManager.getInstance(context); } protected void loadDimens() { @@ -641,7 +657,7 @@ protected void fling(float vel, boolean expand, float collapseSpeedUpFactor, flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing); } - protected void flingToHeight(float vel, boolean expand, float target, + protected void flingToHeight(float vel, final boolean expand, float target, float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) { // Hack to make the expand transition look nice when clear all button is visible - we make // the animation only to the last notification, and then jump to the maximum panel height so @@ -662,8 +678,9 @@ && mExpandedHeight < getMaxPanelHeight() - getClearAllHeight() if (expandBecauseOfFalsing) { vel = 0; } + mUpdateExpandOnLayout = isFullyCollapsed(); mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight()); - if (expandBecauseOfFalsing) { + if (expandBecauseOfFalsing && vel == 0) { animator.setDuration(350); } } else { @@ -678,11 +695,14 @@ && mExpandedHeight < getMaxPanelHeight() - getClearAllHeight() } } - mPerf.cpuBoost((int)animator.getDuration() * 1000); - animator.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; + @Override + public void onAnimationStart(Animator animation) { + if (expand) PanelView.this.addOnLayoutChangeListener(mLayoutChangeListener); + } + @Override public void onAnimationCancel(Animator animation) { mCancelled = true; @@ -690,6 +710,7 @@ public void onAnimationCancel(Animator animation) { @Override public void onAnimationEnd(Animator animation) { + if (expand) PanelView.this.removeOnLayoutChangeListener(mLayoutChangeListener); if (clearAllExpandHack && !mCancelled) { setExpandedHeightInternal(getMaxPanelHeight()); } @@ -913,6 +934,7 @@ public void instantCollapse() { private void abortAnimations() { cancelPeek(); cancelHeightAnimator(); + mKeyguardBottomArea.getIndicationView().animate().cancel(); removeCallbacks(mPostCollapseRunnable); removeCallbacks(mFlingCollapseRunnable); } @@ -931,6 +953,8 @@ protected void startUnlockHintAnimation() { } cancelPeek(); notifyExpandingStarted(); + mKeyguardBottomArea.getIndicationView().animate().cancel(); + mStatusBar.onUnlockHintStarted(); startUnlockHintAnimationPhase1(new Runnable() { @Override public void run() { @@ -939,8 +963,8 @@ public void run() { mHintAnimationRunning = false; } }); - mStatusBar.onUnlockHintStarted(); mHintAnimationRunning = true; + mShowExpandHint = false; } /** @@ -974,6 +998,7 @@ public void onAnimationEnd(Animator animation) { mKeyguardBottomArea.getIndicationView().animate() .translationY(-mHintDistance) .setDuration(250) + .setStartDelay(0) .setInterpolator(mFastOutSlowInInterpolator) .withEndAction(new Runnable() { @Override @@ -996,17 +1021,213 @@ private void startUnlockHintAnimationPhase2(final Runnable onAnimationFinished) animator.setDuration(450); animator.setInterpolator(mBounceInterpolator); animator.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + @Override public void onAnimationEnd(Animator animation) { mHeightAnimator = null; - onAnimationFinished.run(); - notifyBarPanelExpansionChanged(); + if (mCancelled) { + onAnimationFinished.run(); + } else { + if (mShowExpandHint) { + startUnlockHintFadeOutAnimationPhase(onAnimationFinished); + } else { + onAnimationFinished.run(); + notifyBarPanelExpansionChanged(); + } + } } }); animator.start(); mHeightAnimator = animator; } + /** + * Fade in unlock hint + */ + private void startUnlockHintFadeInAnimationPhase(final Runnable onAnimationFinished) { + mStatusBar.onUnlockHintStarted(); + mKeyguardBottomArea.getIndicationView().animate() + .alpha(1) + .setDuration(ANIMATION_FADE_DURATION) + .setStartDelay(0) + .setInterpolator(null) + .withEndAction(new Runnable() { + @Override + public void run() { + if (mShowExpandHint) { + startUnlockHintFadeOutAnimationPhase(onAnimationFinished); + } else { + onAnimationFinished.run(); + notifyBarPanelExpansionChanged(); + } + } + }) + .start(); + } + + /** + * Fade out unlock hint + */ + private void startUnlockHintFadeOutAnimationPhase(final Runnable onAnimationFinished) { + mKeyguardBottomArea.getIndicationView().animate() + .alpha(0) + .setDuration(ANIMATION_FADE_DURATION) + .setStartDelay(HINT_DELAY_DURATION) + .setInterpolator(null) + .withEndAction(new Runnable() { + @Override + public void run() { + startExpandHintAnimation(onAnimationFinished); + } + }) + .start(); + } + + /** + * Fade in Lls hint + */ + private void startLlsHintFadeInAnimationPhase(final Runnable onAnimationFinished) { + mKeyguardBottomArea.getIndicationView().setAlpha(0); + mKeyguardBottomArea.getIndicationView().animate() + .alpha(1) + .setDuration(ANIMATION_FADE_DURATION) + .setStartDelay(0) + .setInterpolator(null) + .withEndAction(new Runnable() { + @Override + public void run() { + if (mShowUnlockHint || mShowExpandHint) { + startLlsHintFadeOutAnimationPhase(onAnimationFinished); + } else { + onAnimationFinished.run();; + } + } + }) + .start(); + } + + /** + * Fade out Lls hint + */ + private void startLlsHintFadeOutAnimationPhase(final Runnable onAnimationFinished) { + mKeyguardBottomArea.getIndicationView().animate() + .alpha(0) + .setDuration(ANIMATION_FADE_DURATION) + .setStartDelay(HINT_DELAY_DURATION) + .setInterpolator(null) + .withEndAction(new Runnable() { + @Override + public void run() { + if (mShowUnlockHint) { + startUnlockHintFadeInAnimationPhase(onAnimationFinished); + } else if (mShowExpandHint) { + startExpandHintAnimation(onAnimationFinished); + } else { + onAnimationFinished.run(); + } + } + }) + .start(); + } + + /** + * Fade in expand hint + */ + private void startExpandHintAnimation(final Runnable onAnimationFinished) { + mStatusBar.onExpandHintStarted(); + mKeyguardBottomArea.getIndicationView().animate() + .alpha(1) + .setDuration(ANIMATION_FADE_DURATION) + .setStartDelay(0) + .setInterpolator(null) + .withEndAction(new Runnable() { + @Override + public void run() { + onAnimationFinished.run(); + } + }) + .start(); + } + + /** + * Show notifications hint (swipe right hint) + */ + protected void startShowNotificationsHintAnimation() { + cancelPeek(); + mStatusBar.onNotificationsHintStarted(); + mHintAnimationRunning = true; + mKeyguardBottomArea.getIndicationView().setAlpha(0); + mKeyguardBottomArea.getIndicationView().animate() + .alpha(1) + .setDuration(ANIMATION_FADE_DURATION) + .setInterpolator(null) + .withEndAction(new Runnable() { + @Override + public void run() { + mStatusBar.onHintFinished(); + mHintAnimationRunning = false; + } + }) + .start(); + } + + protected void startScreenOnHintAnimation(boolean showSwipeLeftHint, boolean showUnlockHint, + boolean showExpandHint) { + // We don't need to hint the user if an animation is already running or the user is changing + // the expansion. + if (mHintAnimationRunning || mScreenOnHintAnimationRunning) return; + + final View indicationView = mKeyguardBottomArea.getIndicationView(); + indicationView.animate().cancel(); + indicationView.animate().setListener( + new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { } + + @Override + public void onAnimationEnd(Animator animation) { } + + @Override + public void onAnimationCancel(Animator animation) { + mScreenOnHintAnimationRunning = false; + indicationView.setAlpha(1f); + } + + @Override + public void onAnimationRepeat(Animator animation) { } + }); + + Runnable r = new Runnable() { + @Override + public void run() { + mStatusBar.onHintFinished(); + mScreenOnHintAnimationRunning = false; + } + }; + if (showSwipeLeftHint) { + mStatusBar.onLlsHintStarted(); + startLlsHintFadeInAnimationPhase(r); + } else if (showUnlockHint) { + mStatusBar.onUnlockHintStarted(); + startUnlockHintFadeInAnimationPhase(r); + } else if (showExpandHint) { + mStatusBar.onExpandHintStarted(); + startExpandHintAnimation(r); + } else { + return; + } + indicationView.setAlpha(0); + mShowUnlockHint = showUnlockHint; + mShowExpandHint = showExpandHint; + mScreenOnHintAnimationRunning = true; + } + private ValueAnimator createHeightAnimator(float targetHeight) { ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index bee29cbbe48bd..7df83466afde6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -17,14 +17,11 @@ package com.android.systemui.statusbar.phone; -import static com.android.systemui.settings.BrightnessController.BRIGHTNESS_ADJ_RESOLUTION; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerNative; -import android.app.ActivityOptions; import android.app.IActivityManager; import android.app.Notification; import android.app.PendingIntent; @@ -42,7 +39,6 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; -import android.content.res.ThemeChangeRequest.RequestType; import android.content.res.ThemeConfig; import android.content.res.Resources; import android.database.ContentObserver; @@ -65,6 +61,7 @@ import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.AsyncTask; +import android.os.BatteryManager; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -103,13 +100,13 @@ import android.view.ViewStub; import android.view.ViewTreeObserver; import android.view.WindowManager; -import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.animation.PathInterpolator; +import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -125,6 +122,7 @@ import com.android.systemui.BatteryMeterView; import com.android.systemui.BatteryLevelTextView; import com.android.systemui.DemoMode; +import com.android.systemui.DockBatteryMeterView; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.Prefs; @@ -135,9 +133,7 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSDragPanel; -import com.android.systemui.qs.QSPanel; import com.android.systemui.recents.ScreenPinningRequest; -import com.android.systemui.settings.BrightnessController; import com.android.systemui.statusbar.ActivatableNotificationView; import com.android.systemui.statusbar.BackDropView; import com.android.systemui.statusbar.BaseStatusBar; @@ -148,27 +144,31 @@ import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.KeyguardIndicationController; +import com.android.systemui.statusbar.MediaExpandableNotificationRow; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.NotificationOverflowContainer; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.SpeedBumpView; +import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.VisualizerView; import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; +import com.android.systemui.statusbar.policy.BatteryStateRegistar.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.CastControllerImpl; +import com.android.systemui.statusbar.policy.DockBatteryController; import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.HotspotControllerImpl; import com.android.systemui.statusbar.policy.KeyButtonView; import com.android.systemui.statusbar.policy.KeyguardMonitor; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; +import com.android.systemui.statusbar.policy.LiveLockScreenController; import com.android.systemui.statusbar.policy.LocationControllerImpl; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NetworkControllerImpl; @@ -186,6 +186,7 @@ import com.android.systemui.statusbar.stack.StackStateAnimator; import com.android.systemui.statusbar.stack.StackViewState; import com.android.systemui.volume.VolumeComponent; +import cyanogenmod.app.CMContextConstants; import cyanogenmod.app.CustomTileListenerService; import cyanogenmod.app.StatusBarPanelCustomTile; @@ -214,6 +215,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; import cyanogenmod.providers.CMSettings; +import cyanogenmod.themes.IThemeService; public class PhoneStatusBar extends BaseStatusBar implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, @@ -239,7 +241,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private static final int MSG_CLOSE_PANELS = 1001; private static final int MSG_OPEN_SETTINGS_PANEL = 1002; private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; - private static final int MSG_UPDATE_NOTIFICATIONS = 1004; // 1020-1040 reserved for BaseStatusBar // Time after we abort the launch transition. @@ -295,7 +296,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // These are no longer handled by the policy, because we need custom strategies for them BluetoothControllerImpl mBluetoothController; SecurityControllerImpl mSecurityController; + BatteryManager mBatteryManager; BatteryController mBatteryController; + DockBatteryController mDockBatteryController; LocationControllerImpl mLocationController; NetworkControllerImpl mNetworkController; HotspotControllerImpl mHotspotController; @@ -314,6 +317,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, WeatherControllerImpl mWeatherController; SuControllerImpl mSuController; FingerprintUnlockController mFingerprintUnlockController; + LiveLockScreenController mLiveLockScreenController; int mNaturalBarHeight = -1; @@ -322,7 +326,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, StatusBarWindowView mStatusBarWindow; FrameLayout mStatusBarWindowContent; - PhoneStatusBarView mStatusBarView; + private PhoneStatusBarView mStatusBarView; private int mStatusBarWindowState = WINDOW_STATE_SHOWING; private StatusBarWindowManager mStatusBarWindowManager; private UnlockMethodCache mUnlockMethodCache; @@ -345,6 +349,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // settings private QSDragPanel mQSPanel; + private QSTileHost mQSTileHost; private DevForceNavbarObserver mDevForceNavbarObserver; // top bar @@ -393,9 +398,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, int mInitialTouchX; int mInitialTouchY; - // last theme that was applied in order to detect theme change (as opposed - // to some other configuration change). - ThemeConfig mCurrentTheme; private boolean mRecreating = false; // for disabling the status bar @@ -420,6 +422,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private int mNavigationIconHints = 0; private HandlerThread mHandlerThread; + private IThemeService mThemeService; + private long mLastThemeChangeTime = 0; + Runnable mLongPressBrightnessChange = new Runnable() { @Override public void run() { @@ -489,6 +494,10 @@ public void update() { } } + public void setStatusBarViewVisibility(boolean visible) { + mStatusBarView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); + } + class DevForceNavbarObserver extends UserContentObserver { DevForceNavbarObserver(Handler handler) { super(handler); @@ -498,14 +507,14 @@ class DevForceNavbarObserver extends UserContentObserver { protected void observe() { super.observe(); ContentResolver resolver = mContext.getContentResolver(); - resolver.registerContentObserver(CMSettings.Secure.getUriFor( - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.Global.getUriFor( + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR), false, this, UserHandle.USER_ALL); } @Override public void update() { - boolean visible = CMSettings.Secure.getIntForUser(mContext.getContentResolver(), - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; + boolean visible = CMSettings.Global.getIntForUser(mContext.getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; if (visible) { forceAddNavigationBar(); @@ -531,7 +540,7 @@ private void forceAddNavigationBar() { mNavigationBarView.setDisabledFlags(mDisabled1); mNavigationBarView.setBar(this); - addNavigationBar(); + addNavigationBar(true); // dynamically adding nav bar, reset System UI visibility! } // ensure quick settings is disabled until the current user makes it through the setup wizard @@ -784,6 +793,10 @@ public void onClick(View v) { private RankingMap mLatestRankingMap; private boolean mNoAnimationOnNextBarModeChange; + public ScrimController getScrimController() { + return mScrimController; + } + @Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) @@ -801,7 +814,7 @@ public void start() { mStatusBarWindow = new StatusBarWindowView(mContext, null); mStatusBarWindow.setService(this); - + super.start(); // calls createAndAddWindows() mMediaSessionManager @@ -809,7 +822,7 @@ public void start() { // TODO: use MediaSessionManager.SessionListener to hook us up to future updates // in session state - addNavigationBar(); + addNavigationBar(false); // Developer options - Force Navigation bar try { @@ -861,6 +874,9 @@ public void start() { mScreenPinningRequest = new ScreenPinningRequest(mContext); updateCustomRecentsLongPressHandler(true); + + mThemeService = IThemeService.Stub.asInterface(ServiceManager.getService( + CMContextConstants.CM_THEME_SERVICE)); } // ================================================================================ @@ -871,9 +887,8 @@ protected PhoneStatusBarView makeStatusBarView() { Resources res = context.getResources(); - mScreenWidth = (float) context.getResources().getDisplayMetrics().widthPixels; - mMinBrightness = context.getResources().getInteger( - com.android.internal.R.integer.config_screenBrightnessDim); + mScreenWidth = (float) res.getDisplayMetrics().widthPixels; + mMinBrightness = res.getInteger(com.android.internal.R.integer.config_screenBrightnessDim); updateDisplaySize(); // populates mDisplayMetrics updateResources(null); @@ -909,8 +924,16 @@ public boolean onTouch(View v, MotionEvent event) { mNotificationPanel.setBackground(new FastColorDrawable(context.getColor( R.color.notification_panel_solid_background))); } + mLiveLockScreenController = new LiveLockScreenController(mContext, this, + mNotificationPanel); + mNotificationPanel.setLiveController(mLiveLockScreenController); + if (mStatusBarWindowManager != null) { + mStatusBarWindowManager.setLiveLockscreenController(mLiveLockScreenController); + } - mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow); + if (mHeadsUpManager == null) { + mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow); + } mHeadsUpManager.setBar(this); mHeadsUpManager.addListener(this); mHeadsUpManager.addListener(mNotificationPanel); @@ -954,7 +977,9 @@ public boolean onTouch(View v, MotionEvent event) { // no window manager? good luck with that } - mAssistManager = new AssistManager(this, context); + if (mAssistManager == null) { + mAssistManager = new AssistManager(this, context); + } if (mNavigationBarView == null) { mAssistManager.onConfigurationChanged(); } @@ -1017,12 +1042,12 @@ public void onClick(View v) { mHeader.setActivityStarter(this); mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindowContent.findViewById(R.id.keyguard_header); mKeyguardStatusView = mStatusBarWindowContent.findViewById(R.id.keyguard_status_view); - mKeyguardBottomArea = - (KeyguardBottomAreaView) mStatusBarWindowContent.findViewById(R.id.keyguard_bottom_area); + mKeyguardBottomArea = mNotificationPanel.getKeyguardBottomArea(); + mKeyguardBottomArea.setActivityStarter(this); mKeyguardBottomArea.setAssistManager(mAssistManager); mKeyguardIndicationController = new KeyguardIndicationController(mContext, - (KeyguardIndicationTextView) mStatusBarWindowContent.findViewById( + (KeyguardIndicationTextView) mKeyguardBottomArea.findViewById( R.id.keyguard_indication_text), mKeyguardBottomArea.getLockIcon()); mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController); @@ -1038,40 +1063,74 @@ public void onClick(View v) { mHandlerThread.start(); // Other icons - mLocationController = new LocationControllerImpl(mContext, - mHandlerThread.getLooper()); // will post a notification - mBatteryController = new BatteryController(mContext, mHandler); - mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { - @Override - public void onPowerSaveChanged() { - mHandler.post(mCheckBarModes); - if (mDozeServiceHost != null) { - mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave()); + if (mLocationController == null) { + mLocationController = new LocationControllerImpl(mContext, + mHandlerThread.getLooper()); // will post a notification + } + if (mBatteryManager == null) { + mBatteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE); + } + if (mBatteryController == null) { + mBatteryController = new BatteryController(mContext, mHandler); + mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { + @Override + public void onPowerSaveChanged() { + mHandler.post(mCheckBarModes); + if (mDozeServiceHost != null) { + mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave()); + } } + + @Override + public void onBatteryLevelChanged(boolean present, int level, + boolean pluggedIn, boolean charging) { + // noop + } + + @Override + public void onBatteryStyleChanged(int style, int percentMode) { + // noop + } + }); + } + if (mBatteryManager.isDockBatterySupported()) { + if (mDockBatteryController == null) { + mDockBatteryController = new DockBatteryController(mContext, mHandler); } - @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { - // noop - } - @Override - public void onBatteryStyleChanged(int style, int percentMode) { - // noop - } - }); - mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper()); - mHotspotController = new HotspotControllerImpl(mContext); - mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper()); - mSecurityController = new SecurityControllerImpl(mContext); + } + if (mNetworkController == null) { + mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper()); + } + if (mHotspotController == null) { + mHotspotController = new HotspotControllerImpl(mContext); + } + if (mBluetoothController == null) { + mBluetoothController = new BluetoothControllerImpl(mContext, + mHandlerThread.getLooper()); + } + if (mSecurityController == null) { + mSecurityController = new SecurityControllerImpl(mContext); + } if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) { - mRotationLockController = new RotationLockControllerImpl(mContext); + if (mRotationLockController == null) { + mRotationLockController = new RotationLockControllerImpl(mContext); + } + } + if (mUserInfoController == null) { + mUserInfoController = new UserInfoController(mContext); } - mUserInfoController = new UserInfoController(mContext); mVolumeComponent = getComponent(VolumeComponent.class); if (mVolumeComponent != null) { - mZenModeController = mVolumeComponent.getZenController(); + if (mZenModeController == null) { + mZenModeController = mVolumeComponent.getZenController(); + } + } + if (mCastController == null) { + mCastController = new CastControllerImpl(mContext); + } + if (mSuController == null) { + mSuController = new SuControllerImpl(mContext); } - mCastController = new CastControllerImpl(mContext); - mSuController = new SuControllerImpl(mContext); final SignalClusterView signalCluster = (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster); final SignalClusterView signalClusterKeyguard = @@ -1092,19 +1151,31 @@ public void onBatteryStyleChanged(int style, int percentMode) { mNetworkController.addEmergencyListener(mHeader); } - mFlashlightController = new FlashlightController(mContext); + if (mFlashlightController == null) { + mFlashlightController = new FlashlightController(mContext); + } mKeyguardBottomArea.setFlashlightController(mFlashlightController); mKeyguardBottomArea.setPhoneStatusBar(this); mKeyguardBottomArea.setUserSetupComplete(mUserSetup); - mAccessibilityController = new AccessibilityController(mContext); + if (mAccessibilityController == null) { + mAccessibilityController = new AccessibilityController(mContext); + } mKeyguardBottomArea.setAccessibilityController(mAccessibilityController); - mNextAlarmController = new NextAlarmController(mContext); - mKeyguardMonitor = new KeyguardMonitor(mContext); + if (mNextAlarmController == null) { + mNextAlarmController = new NextAlarmController(mContext); + } + if (mKeyguardMonitor == null) { + mKeyguardMonitor = new KeyguardMonitor(mContext); + } if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) { - mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor, - mHandler); + if (mUserSwitcherController == null) { + mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor, + mHandler); + } + } + if (mWeatherController == null) { + mWeatherController = new WeatherControllerImpl(mContext); } - mWeatherController = new WeatherControllerImpl(mContext); mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, (ViewStub) mStatusBarWindowContent.findViewById(R.id.keyguard_user_switcher), @@ -1114,30 +1185,37 @@ public void onBatteryStyleChanged(int style, int percentMode) { // Set up the quick settings tile panel mQSPanel = (QSDragPanel) mStatusBarWindowContent.findViewById(R.id.quick_settings_panel); if (mQSPanel != null) { - final QSTileHost qsh = new QSTileHost(mContext, this, - mBluetoothController, mLocationController, mRotationLockController, - mNetworkController, mZenModeController, mHotspotController, - mCastController, mFlashlightController, - mUserSwitcherController, mKeyguardMonitor, - mSecurityController); - mQSPanel.setHost(qsh); - mQSPanel.setTiles(qsh.getTiles()); - mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindowContent); + if (mQSTileHost == null) { + mQSTileHost = new QSTileHost(mContext, this, + mBluetoothController, mLocationController, mRotationLockController, + mNetworkController, mZenModeController, mHotspotController, + mCastController, mFlashlightController, + mUserSwitcherController, mKeyguardMonitor, + mSecurityController, mBatteryController); + } + mQSPanel.setHost(mQSTileHost); + if (mBrightnessMirrorController == null) { + mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindowContent); + } mQSPanel.setBrightnessMirror(mBrightnessMirrorController); + mQSPanel.setTiles(mQSTileHost.getTiles()); mHeader.setQSPanel(mQSPanel); - qsh.setCallback(new QSTileHost.Callback() { + mQSTileHost.setCallback(new QSTileHost.Callback() { @Override public void onTilesChanged() { mHandler.post(new Runnable() { @Override public void run() { - mQSPanel.setTiles(qsh.getTiles()); + mQSPanel.setTiles(mQSTileHost.getTiles()); } }); } @Override public void setEditing(final boolean editing) { + if (mState != StatusBarState.SHADE) { + return; + } mHandler.post(new Runnable() { @Override public void run() { @@ -1154,6 +1232,9 @@ public boolean isEditing() { @Override public void goToSettingsPage() { + if (mState != StatusBarState.SHADE) { + return; + } setEditing(true); mHandler.postDelayed(new Runnable() { @Override @@ -1162,6 +1243,37 @@ public void run() { } }, 500); } + + @Override + public void resetTiles() { + mHandler.post(new Runnable() { + @Override + public void run() { + mQSPanel.setEditing(false); + mHeader.setEditing(false); + + // unregister custom tile service while we reset to not get + // callbacks from custom tiles + try { + mCustomTileListenerService.unregisterAsSystemService(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to unregister custom tile listener", e); + } + + mQSTileHost.resetTiles(); + + // reregister service + try { + mCustomTileListenerService.registerAsSystemService(mContext, + new ComponentName(mContext.getPackageName(), + PhoneStatusBar.this.getClass().getCanonicalName()), + UserHandle.USER_ALL); + } catch (RemoteException e) { + Log.e(TAG, "Unable to register custom tile listener", e); + } + } + }); + } }); } @@ -1183,17 +1295,41 @@ public void run() { mUserInfoController.reloadUserInfo(); mHeader.setBatteryController(mBatteryController); + BatteryMeterView batteryMeterView = ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)); + batteryMeterView.setBatteryStateRegistar(mBatteryController); batteryMeterView.setBatteryController(mBatteryController); batteryMeterView.setAnimationsEnabled(false); ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.battery_level_text)) - .setBatteryController(mBatteryController); + .setBatteryStateRegistar(mBatteryController); mKeyguardStatusBar.setBatteryController(mBatteryController); - mVisualizerView.setKeyguardMonitor(mKeyguardMonitor); + mHeader.setDockBatteryController(mDockBatteryController); + mKeyguardStatusBar.setDockBatteryController(mDockBatteryController); + if (mDockBatteryController != null) { + DockBatteryMeterView dockBatteryMeterView = + ((DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery)); + dockBatteryMeterView.setBatteryStateRegistar(mDockBatteryController); + ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text)) + .setBatteryStateRegistar(mDockBatteryController); + } else { + DockBatteryMeterView dockBatteryMeterView = + (DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery); + if (dockBatteryMeterView != null) { + mStatusBarView.removeView(dockBatteryMeterView); + } + BatteryLevelTextView dockBatteryLevel = + (BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text); + if (dockBatteryLevel != null) { + mStatusBarView.removeView(dockBatteryLevel); + } + } + mHeader.setNextAlarmController(mNextAlarmController); mHeader.setWeatherController(mWeatherController); + mNotificationPanel.setWeatherController(mWeatherController); + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mBroadcastReceiver.onReceive(mContext, new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF)); @@ -1207,6 +1343,7 @@ public void run() { filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED); + filter.addAction(cyanogenmod.content.Intent.ACTION_SCREEN_CAMERA_GESTURE); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); IntentFilter demoFilter = new IntentFilter(); @@ -1364,7 +1501,7 @@ public void onCustomTilePosted(final StatusBarPanelCustomTile sbc) { @Override public void run() { boolean isUpdate = mQSPanel.getHost().getCustomTileData() - .get(sbc.getKey()) != null; + .get(sbc.persistableKey()) != null; if (isUpdate) { mQSPanel.getHost().updateCustomTile(sbc); } else { @@ -1380,7 +1517,7 @@ public void onCustomTileRemoved(final StatusBarPanelCustomTile sbc) { mHandler.post(new Runnable() { @Override public void run() { - mQSPanel.getHost().removeCustomTileSysUi(sbc.getKey()); + mQSPanel.getHost().removeCustomTileSysUi(sbc.persistableKey()); } }); } @@ -1442,16 +1579,26 @@ private void awakenDreams() { } } - private void prepareNavigationBarView() { + private void prepareNavigationBarView(boolean forceReset) { mNavigationBarView.reorient(); mNavigationBarView.setListeners(mRecentsClickListener, mRecentsPreloadOnTouchListener, mLongPressBackRecentsListener, mHomeActionListener, mLongPressHomeListener); mAssistManager.onConfigurationChanged(); + if (forceReset) { + // Nav Bar was added dynamically - we need to reset the mSystemUiVisibility and call + // setSystemUiVisibility so that mNavigationBarMode is set to the correct value + int newVal = mSystemUiVisibility; + mSystemUiVisibility = 0; + setSystemUiVisibility(newVal, SYSTEM_UI_VISIBILITY_MASK); + checkBarMode(mNavigationBarMode, + mNavigationBarWindowState, mNavigationBarView.getBarTransitions(), + mNoAnimationOnNextBarModeChange); + } } // For small-screen devices (read: phones) that lack hardware navigation buttons - private void addNavigationBar() { + private void addNavigationBar(boolean forceReset) { if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView); if (mNavigationBarView == null) return; @@ -1462,7 +1609,7 @@ private void addNavigationBar() { return; } - prepareNavigationBarView(); + prepareNavigationBarView(forceReset); mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams()); } @@ -1478,7 +1625,7 @@ private void removeNavigationBar() { private void repositionNavigationBar() { if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return; - prepareNavigationBarView(); + prepareNavigationBarView(false); mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams()); } @@ -1831,7 +1978,8 @@ public static boolean isTopLevelChild(Entry entry) { return entry.row.getParent() instanceof NotificationStackScrollLayout; } - private void handleUpdateNotifications() { + @Override + protected void updateNotifications() { mNotificationData.filterAndSort(); updateNotificationShade(); @@ -1839,14 +1987,7 @@ private void handleUpdateNotifications() { } @Override - protected void updateNotifications() { - if (!mHandler.hasMessages(MSG_UPDATE_NOTIFICATIONS)) { - mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATIONS); - } - } - - @Override - protected void updateRowStates() { + public void updateRowStates() { super.updateRowStates(); mNotificationPanel.notifyVisibleChildrenChanged(); } @@ -1960,6 +2101,12 @@ public void findAndUpdateMediaNotifications() { Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " + mMediaMetadata); } + if (mediaNotification != null + && mediaNotification.row != null + && mediaNotification.row instanceof MediaExpandableNotificationRow) { + ((MediaExpandableNotificationRow) mediaNotification.row) + .setMediaController(controller); + } if (mediaNotification != null) { mMediaNotificationKey = mediaNotification.notification.getKey(); @@ -2062,23 +2209,20 @@ public void updateMediaMetaData(boolean metaDataChanged) { } } - // apply user lockscreen image - if (mMediaMetadata == null && backdropBitmap == null) { - backdropBitmap = mKeyguardWallpaper; - } - - boolean keyguardVisible = (mState != StatusBarState.SHADE); + // HACK: Consider keyguard as visible if showing sim pin security screen + KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); + boolean keyguardVisible = mState != StatusBarState.SHADE || updateMonitor.isSimPinSecure(); if (!mKeyguardFadingAway && keyguardVisible && backdropBitmap != null && mScreenOn) { // if there's album art, ensure visualizer is visible - mVisualizerView.setVisible(true); mVisualizerView.setPlaying(mMediaController != null && mMediaController.getPlaybackState() != null && mMediaController.getPlaybackState().getState() == PlaybackState.STATE_PLAYING); } - if (backdropBitmap == null && mMediaMetadata == null) { + // apply user lockscreen image + if (backdropBitmap == null && !mLiveLockScreenController.isShowingLiveLockScreenView()) { backdropBitmap = mKeyguardWallpaper; } @@ -2359,6 +2503,11 @@ public String getCurrentMediaNotificationKey() { return mMediaNotificationKey; } + @Override + protected MediaController getCurrentMediaController() { + return mMediaController; + } + public boolean isScrimSrcModeEnabled() { return mScrimSrcModeEnabled; } @@ -2496,9 +2645,6 @@ public void handleMessage(Message m) { case MSG_LAUNCH_TRANSITION_TIMEOUT: onLaunchTransitionTimeout(); break; - case MSG_UPDATE_NOTIFICATIONS: - handleUpdateNotifications(); - break; } } } @@ -2824,7 +2970,7 @@ public boolean interceptTouchEvent(MotionEvent event) { setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); } } - if (mBrightnessChanged && upOrCancel) { + if (mBrightnessChanged && upOrCancel && !isQsExpanded()) { mBrightnessChanged = false; if (mJustPeeked && mExpandedVisible) { mNotificationPanel.fling(10, false); @@ -3270,6 +3416,9 @@ public void run() { if (mBatteryController != null) { mBatteryController.dump(fd, pw, args); } + if (mDockBatteryController != null) { + mDockBatteryController.dump(fd, pw, args); + } if (mNextAlarmController != null) { mNextAlarmController.dump(fd, pw, args); } @@ -3316,6 +3465,9 @@ private void addStatusBarWindow() { mStatusBarWindowManager = new StatusBarWindowManager(mContext, mKeyguardMonitor); mStatusBarWindowManager.setShowingMedia(mKeyguardShowingMedia); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); + if (mLiveLockScreenController != null) { + mStatusBarWindowManager.setLiveLockscreenController(mLiveLockScreenController); + } } // called by makeStatusbar and also by PhoneStatusBarView @@ -3339,10 +3491,16 @@ public void startActivityDismissingKeyguard(final Intent intent, boolean onlyPro public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final Callback callback) { - if (onlyProvisioned && !isDeviceProvisioned()) return; - final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( mContext, intent, mCurrentUserId); + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, afterKeyguardGone, + callback); + } + + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + final boolean dismissShade, final boolean afterKeyguardGone, final Callback callback) { + if (onlyProvisioned && !isDeviceProvisioned()) return; + final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); Runnable runnable = new Runnable() { public void run() { @@ -3434,6 +3592,24 @@ else if (Intent.ACTION_SCREEN_OFF.equals(action)) { else if (Intent.ACTION_SCREEN_ON.equals(action)) { mScreenOn = true; notifyNavigationBarScreenOn(true); + } else if (Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED.equals(action)) { + WallpaperManager wm = (WallpaperManager) mContext.getSystemService( + Context.WALLPAPER_SERVICE); + mKeyguardWallpaper = wm.getKeyguardBitmap(); + updateMediaMetaData(true); + } else if (cyanogenmod.content.Intent.ACTION_SCREEN_CAMERA_GESTURE.equals(action)) { + boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0) != 0; + if (!userSetupComplete || !isDeviceProvisioned()) { + if (DEBUG) { + Log.d(TAG, String.format("userSetupComplete = $1%s, " + + "deviceProvisioned = $2%s, ignoring camera launch gesture.", + userSetupComplete, isDeviceProvisioned())); + } + return; + } + + onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE); } } }; @@ -3522,6 +3698,7 @@ protected void onConfigurationChanged(Configuration newConfig) { mIconController.updateResources(); mScreenPinningRequest.onConfigurationChanged(); mNetworkController.onConfigurationChanged(); + mStatusBarWindowManager.onConfigurationChanged(newConfig); } @Override @@ -3547,6 +3724,12 @@ public void userSwitched(int newUserId) { } } + public void hideHeadsUp() { + if (mUseHeadsUp && mHeadsUpManager != null) { + mHeadsUpManager.releaseAllImmediately(); + } + } + private void setControllerUsers() { if (mZenModeController != null) { mZenModeController.setUserId(mCurrentUserId); @@ -3557,6 +3740,9 @@ private void setControllerUsers() { if (mBatteryController != null) { mBatteryController.setUserId(mCurrentUserId); } + if (mDockBatteryController != null) { + mDockBatteryController.setUserId(mCurrentUserId); + } } private void resetUserSetupObserver() { @@ -3586,6 +3772,10 @@ private void removeSignalCallbacks(NetworkController networkController) { networkController.removeSignalCallback(signalCluster); networkController.removeSignalCallback(signalClusterKeyguard); networkController.removeSignalCallback(signalClusterQs); + + if (signalCluster != null) signalCluster.setSecurityController(null); + if (signalClusterKeyguard != null) signalClusterKeyguard.setSecurityController(null); + if (signalClusterQs != null) signalClusterQs.setSecurityController(null); } private void recreateStatusBar() { @@ -3593,44 +3783,69 @@ private void recreateStatusBar() { if (mNetworkController != null) { removeSignalCallbacks(mNetworkController); + if (mNetworkController.hasVoiceCallingFeature()) { + mNetworkController.removeEmergencyListener(mHeader); + } + } + if (mHeadsUpManager != null) { + mHeadsUpManager.removeListener(mNotificationPanel); + mHeadsUpManager.removeListener(mScrimController); + } + if (mIconController != null) { + mIconController.cleanup(); + } + if (mKeyguardIndicationController != null) { + mKeyguardIndicationController.cleanup(); + } + if (mLiveLockScreenController != null) { + mLiveLockScreenController.cleanup(); } + mKeyguardBottomArea.cleanup(); mStatusBarWindow.removeContent(mStatusBarWindowContent); mStatusBarWindow.clearDisappearingChildren(); - RankingMap rankingMap = mNotificationData.getRankingMap(); // extract icons from the soon-to-be recreated viewgroup. - /* - int nIcons = mStatusIcons != null ? mStatusIcons.getChildCount() : 0; + ViewGroup statusIcons = mIconController.getStatusIcons(); + int nIcons = statusIcons != null ? statusIcons.getChildCount() : 0; ArrayList icons = new ArrayList(nIcons); ArrayList iconSlots = new ArrayList(nIcons); for (int i = 0; i < nIcons; i++) { - StatusBarIconView iconView = (StatusBarIconView)mStatusIcons.getChildAt(i); + StatusBarIconView iconView = (StatusBarIconView) statusIcons.getChildAt(i); icons.add(iconView.getStatusBarIcon()); iconSlots.add(iconView.getStatusBarSlot()); } - */ removeAllViews(mStatusBarWindowContent); // extract notifications. + RankingMap rankingMap = mNotificationData.getRankingMap(); int nNotifs = mNotificationData.size(); - ArrayList> notifications = - new ArrayList>(nNotifs); + ArrayList> notifications = new ArrayList<>(nNotifs); copyNotifications(notifications, mNotificationData); + // now remove all the notifications since we'll be re-creating these with the copied data mNotificationData.clear(); + if (mCustomTileListenerService != null) { + try { + mCustomTileListenerService.unregisterAsSystemService(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to unregister custom tile listener", e); + } + } + + mQSPanel.getHost().setCustomTileListenerService(null); + mQSPanel.setListening(false); + makeStatusBarView(); repositionNavigationBar(); - // recreate StatusBarIconViews. - /* + // re-add status icons for (int i = 0; i < nIcons; i++) { StatusBarIcon icon = icons.get(i); String slot = iconSlots.get(i); addIcon(slot, i, i, icon); } - */ // recreate notifications. for (int i = 0; i < nNotifs; i++) { @@ -3648,15 +3863,9 @@ private void recreateStatusBar() { // Stop the command queue until the new status bar container settles and has a layout pass mCommandQueue.pause(); - if (mCustomTileListenerService != null) { - try { - mCustomTileListenerService.unregisterAsSystemService(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to unregister custom tile listener", e); - } - } - - mQSPanel.getHost().setCustomTileListenerService(null); + // fix notification panel being shifted to the left by calling + // instantCollapseNotificationPanel() + instantCollapseNotificationPanel(); mStatusBarWindow.requestLayout(); mStatusBarWindow.getViewTreeObserver().addOnGlobalLayoutListener( @@ -3675,6 +3884,17 @@ public void onGlobalLayout() { if (mState == StatusBarState.KEYGUARD) { // this will make sure the keyguard is showing showKeyguard(); + // make sure to hide the notification icon area and system iconography + // to avoid overlap (CYNGNOS-2253) + mIconController.hideNotificationIconArea(false); + mIconController.hideSystemIconArea(false); + } + + // update mLastThemeChangeTime + try { + mLastThemeChangeTime = mThemeService.getLastThemeChangeTime(); + } catch (RemoteException e) { + /* ignore */ } } @@ -3686,7 +3906,9 @@ private void removeAllViews(ViewGroup parent) { removeAllViews((ViewGroup) child); } } - parent.removeAllViews(); + + // AdapterView does not support removeAllViews so check before calling + if (!(parent instanceof AdapterView)) parent.removeAllViews(); } /** @@ -3703,7 +3925,6 @@ void updateResources(Configuration newConfig) { final boolean updateNavBar = shouldUpdateNavbar(mCurrentTheme, newTheme); if (newTheme != null) mCurrentTheme = (ThemeConfig) newTheme.clone(); if (updateStatusBar) { - mContext.recreateTheme(); recreateStatusBar(); } else { loadDimens(); @@ -3730,8 +3951,8 @@ void updateResources(Configuration newConfig) { /** * Determines if we need to recreate the status bar due to a theme change. We currently - * check if the overlay for the status bar, fonts, or icons, or forced update count have - * changed. + * check if the overlay for the status bar, fonts, or icons, or last theme change time is + * greater than mLastThemeChangeTime * * @param oldTheme * @param newTheme @@ -3744,17 +3965,24 @@ private boolean shouldUpdateStatusbar(ThemeConfig oldTheme, ThemeConfig newTheme final String overlay = newTheme.getOverlayForStatusBar(); final String icons = newTheme.getIconPackPkgName(); final String fonts = newTheme.getFontPkgName(); + boolean isNewThemeChange = false; + try { + isNewThemeChange = mLastThemeChangeTime < mThemeService.getLastThemeChangeTime(); + } catch (RemoteException e) { + /* ignore */ + } return oldTheme == null || (overlay != null && !overlay.equals(oldTheme.getOverlayForStatusBar()) || (fonts != null && !fonts.equals(oldTheme.getFontPkgName())) || (icons != null && !icons.equals(oldTheme.getIconPackPkgName())) || - newTheme.getLastThemeChangeRequestType() == RequestType.THEME_UPDATED); + isNewThemeChange); } /** * Determines if we need to update the navbar resources due to a theme change. We currently - * check if the overlay for the navbar, or request type is {@link RequestType.THEME_UPDATED}. + * check if the overlay for the navbar, or last theme change time is greater than + * mLastThemeChangeTime * * @param oldTheme * @param newTheme @@ -3765,10 +3993,16 @@ private boolean shouldUpdateNavbar(ThemeConfig oldTheme, ThemeConfig newTheme) { if (newTheme == null) return false; final String overlay = newTheme.getOverlayForNavBar(); + boolean isNewThemeChange = false; + try { + isNewThemeChange = mLastThemeChangeTime < mThemeService.getLastThemeChangeTime(); + } catch (RemoteException e) { + /* ignore */ + } return oldTheme == null || (overlay != null && !overlay.equals(oldTheme.getOverlayForNavBar()) || - newTheme.getLastThemeChangeRequestType() == RequestType.THEME_UPDATED); + isNewThemeChange); } protected void loadDimens() { @@ -4046,6 +4280,7 @@ public void dispatchDemoCommand(String command, Bundle args) { } if (modeChange || command.equals(COMMAND_BATTERY)) { dispatchDemoCommandToView(command, args, R.id.battery); + dispatchDemoCommandToView(command, args, R.id.dock_battery); } if (modeChange || command.equals(COMMAND_STATUS)) { mIconController.dispatchDemoCommand(command, args); @@ -4126,6 +4361,18 @@ public void showKeyguard() { mDraggedDownRow = null; } mAssistManager.onLockscreenShown(); + mKeyguardBottomArea.requestFocus(); + try { + WindowManagerGlobal.getWindowManagerService() + .setLiveLockscreenEdgeDetector(false); + } catch (RemoteException e){ + e.printStackTrace(); + } + if (mLiveLockScreenController.isShowingLiveLockScreenView()) { + mLiveLockScreenController.onLiveLockScreenFocusChanged(false); + mLiveLockScreenController.getLiveLockScreenView().onKeyguardShowing( + mStatusBarKeyguardViewManager.isScreenTurnedOn()); + } } private void onLaunchTransitionFadingEnded() { @@ -4276,6 +4523,9 @@ public void run() { mNotificationPanel.onAffordanceLaunchEnded(); mNotificationPanel.animate().cancel(); mNotificationPanel.setAlpha(1f); + if (mLiveLockScreenController.isShowingLiveLockScreenView()) { + mLiveLockScreenController.getLiveLockScreenView().onKeyguardDismissed(); + } return staying; } @@ -4289,6 +4539,10 @@ boolean isSecure() { return mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isSecure(); } + public boolean isKeyguardInputRestricted() { + return mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isInputRestricted(); + } + public long calculateGoingToFullShadeDelay() { return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration; } @@ -4321,7 +4575,6 @@ public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDurati - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION, StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION); disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */); - mVisualizerView.setVisible(false); } public boolean isKeyguardFadingAway() { @@ -4365,6 +4618,7 @@ private void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLock mIconPolicy.setKeyguardShowing(false); } mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade); + mLiveLockScreenController.setBarState(mState); updateDozingState(); updatePublicMode(); updateStackScrollerState(goingToFullShade); @@ -4392,7 +4646,9 @@ private void updateDozingState() { public void updateStackScrollerState(boolean goingToFullShade) { if (mStackScroller == null) return; boolean onKeyguard = mState == StatusBarState.KEYGUARD; - mStackScroller.setHideSensitive(isLockscreenPublicMode(), goingToFullShade); + mStackScroller.setHideSensitive(isLockscreenPublicMode() + || (!userAllowsPrivateNotificationsInPublic(mCurrentUserId) && onKeyguard), + goingToFullShade); mStackScroller.setDimmed(onKeyguard, false /* animate */); mStackScroller.setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild(); @@ -4451,14 +4707,34 @@ public boolean onSpacePressed() { return false; } - private void showBouncer() { - if (!mRecreating && - (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { + public void showBouncer() { + if (!mRecreating && mNotificationPanel.mCanDismissKeyguard + && (mState != StatusBarState.SHADE || mLiveLockScreenController.getLiveLockScreenHasFocus())) { mWaitingForKeyguardExit = mStatusBarKeyguardViewManager.isShowing(); mStatusBarKeyguardViewManager.dismiss(); } } + protected void showBouncerOrFocusKeyguardExternalView() { + if (mLiveLockScreenController.isShowingLiveLockScreenView() && !isKeyguardShowingMedia() && + mLiveLockScreenController.isLiveLockScreenInteractive()) { + focusKeyguardExternalView(); + } else { + showBouncer(); + } + } + + protected void unfocusKeyguardExternalView() { + mStatusBarKeyguardViewManager.setKeyguardExternalViewFocus(false); + } + + public void focusKeyguardExternalView() { + mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/, + 1.0f /* speedUpFactor */); + mStatusBarKeyguardViewManager.setKeyguardExternalViewFocus(true); + setBarState(StatusBarState.SHADE); + } + private void instantExpandNotificationsPanel() { // Make our window larger and the panel expanded. @@ -4496,6 +4772,7 @@ public void setBarState(int state) { clearNotificationEffects(); } mState = state; + mVisualizerView.setStatusBarState(state); mGroupManager.setStatusBarState(state); mStatusBarWindowManager.setStatusBarState(state); updateDozing(); @@ -4518,12 +4795,33 @@ public void onClosingFinished() { } public void onUnlockHintStarted() { - mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock); + mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock, + mNotificationPanel.shouldShowScreenOnHints() ? + KeyguardIndicationController.IndicationDirection.UP : + KeyguardIndicationController.IndicationDirection.NONE); + } + + public void onLlsHintStarted() { + String llsName = mLiveLockScreenController.getLiveLockScreenName(); + mKeyguardIndicationController.showTransientIndication( + mContext.getString(R.string.swipe_left_hint, llsName), + KeyguardIndicationController.IndicationDirection.LEFT); + } + + public void onExpandHintStarted() { + mKeyguardIndicationController.showTransientIndication(R.string.expand_hint, + KeyguardIndicationController.IndicationDirection.DOWN); + } + + public void onNotificationsHintStarted() { + mKeyguardIndicationController.showTransientIndication(R.string.swipe_right_hint, + KeyguardIndicationController.IndicationDirection.RIGHT); } public void onHintFinished() { // Delay the reset a bit so the user can read the text. mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); + mKeyguardBottomArea.expand(false); } public void onCameraHintStarted(String hint) { @@ -4544,7 +4842,14 @@ public void onTrackingStopped(boolean expand) { @Override protected int getMaxKeyguardNotifications() { - return mKeyguardMaxNotificationCount; + int max = mKeyguardMaxNotificationCount; + // When an interactive live lockscreen is showing + // we want to limit the number of maximum notifications + // by 1 so there is additional space for the user to dismiss keygard + if (mLiveLockScreenController.isLiveLockScreenInteractive()) { + max--; + } + return max; } public NavigationBarView getNavigationBarView() { @@ -4660,7 +4965,9 @@ public void onFinishedGoingToSleep() { mWakeUpTouchLocation = null; mStackScroller.setAnimationsEnabled(false); updateVisibleToUser(); - mVisualizerView.setVisible(false); + if (mQSTileHost.isEditing()) { + mQSTileHost.setEditing(false); + } if (mLaunchCameraOnFinishedGoingToSleep) { mLaunchCameraOnFinishedGoingToSleep = false; @@ -4700,6 +5007,16 @@ public void onScreenTurnedOn() { mScreenTurningOn = false; mDozeScrimController.onScreenTurnedOn(); mVisualizerView.setVisible(true); + if (mLiveLockScreenController.isShowingLiveLockScreenView()) { + mLiveLockScreenController.onScreenTurnedOn(); + } + } + + public void onScreenTurnedOff() { + mVisualizerView.setVisible(false); + if (mLiveLockScreenController.isShowingLiveLockScreenView()) { + mLiveLockScreenController.onScreenTurnedOff(); + } } /** @@ -5064,7 +5381,9 @@ public void onCameraLaunchGestureDetected(int source) { pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE"); mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); } - vibrateForCameraGesture(); + if (source != StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) { + vibrateForCameraGesture(); + } if (!mStatusBarKeyguardViewManager.isShowing()) { startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, true /* dismissShade */); @@ -5103,6 +5422,14 @@ public VisualizerView getVisualizer() { return mVisualizerView; } + public boolean isShowingLiveLockScreenView() { + return mLiveLockScreenController.isShowingLiveLockScreenView(); + } + + public void slideNotificationPanelIn() { + mNotificationPanel.slideLockScreenIn(); + } + private final class ShadeUpdates { private final ArraySet mVisibleNotifications = new ArraySet(); private final ArraySet mNewVisibleNotifications = new ArraySet(); @@ -5255,4 +5582,8 @@ public void handleMessage(Message msg) { } } } + + public boolean isAffordanceSwipeInProgress() { + return mNotificationPanel.isAffordanceSwipeInProgress(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 1b17899976935..1395ff6d494c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -22,6 +22,8 @@ import android.app.IUserSwitchObserver; import android.app.PendingIntent; import android.app.StatusBarManager; +import android.bluetooth.BluetoothAssignedNumbers; +import android.bluetooth.BluetoothHeadset; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -103,6 +105,7 @@ public class PhoneStatusBarPolicy implements Callback { private boolean mZenVisible; private boolean mVolumeVisible; private boolean mCurrentUserSetup; + private Float mBluetoothBatteryLevel = null; private int mZen; @@ -129,6 +132,9 @@ else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) { updateTTY(intent); } + else if (action.equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) { + updateBluetoothBattery(intent); + } } }; @@ -166,6 +172,9 @@ public PhoneStatusBarPolicy(Context context, CastController cast, HotspotControl filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED); + filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT); + filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + + "." + Integer.toString(BluetoothAssignedNumbers.APPLE)); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); // listen for user / profile change. @@ -182,6 +191,9 @@ public PhoneStatusBarPolicy(Context context, CastController cast, HotspotControl // bluetooth status updateBluetooth(); + //Update initial tty mode + updateTTYMode(); + // Alarm clock mService.setIcon(SLOT_ALARM_CLOCK, R.drawable.stat_sys_alarm, 0, null); mService.setIconVisibility(SLOT_ALARM_CLOCK, false); @@ -354,6 +366,27 @@ public void onBluetoothStateChange(boolean enabled) { updateBluetooth(); } + private void updateBluetoothBattery(Intent intent) { + if (intent.hasExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD)) { + String command = intent.getStringExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD); + if ("+IPHONEACCEV".equals(command)) { + Object[] args = (Object[]) intent.getSerializableExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS); + if (args.length >= 3 && args[0] instanceof Integer && ((Integer)args[0])*2+1<=args.length) { + for (int i=0;i<((Integer)args[0]);i++) { + if (!(args[i*2+1] instanceof Integer) || !(args[i*2+2] instanceof Integer)) { + continue; + } + if (args[i*2+1].equals(1)) { + mBluetoothBatteryLevel = (((Integer)args[i*2+2])+1)/10.0f; + updateBluetooth(); + break; + } + } + } + } + } + } + private final void updateBluetooth() { int iconId = R.drawable.stat_sys_data_bluetooth; String contentDescription = @@ -362,8 +395,24 @@ private final void updateBluetooth() { if (mBluetooth != null) { bluetoothEnabled = mBluetooth.isBluetoothEnabled(); if (mBluetooth.isBluetoothConnected()) { - iconId = R.drawable.stat_sys_data_bluetooth_connected; + if (mBluetoothBatteryLevel == null) { + iconId = R.drawable.stat_sys_data_bluetooth_connected; + } else { + if (mBluetoothBatteryLevel<=0.15f) { + iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_1; + } else if (mBluetoothBatteryLevel<=0.375f) { + iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_2; + } else if (mBluetoothBatteryLevel<=0.625f) { + iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_3; + } else if (mBluetoothBatteryLevel<=0.85f) { + iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_4; + } else { + iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_5; + } + } contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected); + } else { + mBluetoothBatteryLevel = null; } } @@ -391,6 +440,29 @@ private final void updateTTY(Intent intent) { } } + private boolean isWiredHeadsetOn() { + AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + return audioManager.isWiredHeadsetOn(); + } + + private final void updateTTYMode() { + int ttyMode = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF); + boolean enabled = ttyMode != TelecomManager.TTY_MODE_OFF; + if (DEBUG) Log.v(TAG, "updateTTYMode: enabled: " + enabled); + if (enabled && isWiredHeadsetOn()) { + // TTY is on + if (DEBUG) Log.v(TAG, "updateTTYMode: set TTY on"); + mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0, + mContext.getString(R.string.accessibility_tty_enabled)); + mService.setIconVisibility(SLOT_TTY, true); + } else { + // TTY is off + if (DEBUG) Log.v(TAG, "updateTTYMode: set TTY off"); + mService.setIconVisibility(SLOT_TTY, false); + } + } + private void updateCast() { boolean isCasting = false; for (CastDevice device : mCast.getCastDevices()) { @@ -448,6 +520,12 @@ private void updateManagedProfile() { @Override public void onUserSwitching(int newUserId, IRemoteCallback reply) { mUserInfoController.reloadUserInfo(); + if (reply != null) { + try { + reply.sendResult(null); + } catch (RemoteException e) { + } + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 3b068d673871e..8c9daeefd640e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -111,6 +111,7 @@ public PanelView selectPanelForTouch(MotionEvent touch) { @Override public void onPanelPeeked() { super.onPanelPeeked(); + removePendingHideExpandedRunnables(); mBar.makeExpandedVisible(false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index b037bcfb5df6e..e88ed736b706d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -30,6 +30,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import com.android.internal.logging.MetricsLogger; @@ -39,7 +40,9 @@ import com.android.systemui.qs.tiles.AdbOverNetworkTile; import com.android.systemui.qs.tiles.AirplaneModeTile; import com.android.systemui.qs.tiles.AmbientDisplayTile; +import com.android.systemui.qs.tiles.BatterySaverTile; import com.android.systemui.qs.tiles.BluetoothTile; +import com.android.systemui.qs.tiles.CaffeineTile; import com.android.systemui.qs.tiles.CastTile; import com.android.systemui.qs.tiles.CellularTile; import com.android.systemui.qs.tiles.ColorInversionTile; @@ -48,9 +51,9 @@ import com.android.systemui.qs.tiles.DndTile; import com.android.systemui.qs.tiles.EditTile; import com.android.systemui.qs.tiles.FlashlightTile; +import com.android.systemui.qs.tiles.HeadsUpTile; import com.android.systemui.qs.tiles.HotspotTile; import com.android.systemui.qs.tiles.IntentTile; -import com.android.systemui.qs.tiles.LiveDisplayTile; import com.android.systemui.qs.tiles.LocationTile; import com.android.systemui.qs.tiles.LockscreenToggleTile; import com.android.systemui.qs.tiles.NfcTile; @@ -63,6 +66,7 @@ import com.android.systemui.qs.tiles.VolumeTile; import com.android.systemui.qs.tiles.WifiTile; import com.android.systemui.statusbar.CustomTileData; +import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.FlashlightController; @@ -111,6 +115,7 @@ public class QSTileHost implements QSTile.Host, Tunable { private final UserSwitcherController mUserSwitcherController; private final KeyguardMonitor mKeyguard; private final SecurityController mSecurity; + private final BatteryController mBattery; private CustomTileData mCustomTileData; private CustomTileListenerService mCustomTileListenerService; @@ -123,7 +128,7 @@ public QSTileHost(Context context, PhoneStatusBar statusBar, ZenModeController zen, HotspotController hotspot, CastController cast, FlashlightController flashlight, UserSwitcherController userSwitcher, KeyguardMonitor keyguard, - SecurityController security) { + SecurityController security, BatteryController battery) { mContext = context; mStatusBar = statusBar; mBluetooth = bluetooth; @@ -137,6 +142,7 @@ public QSTileHost(Context context, PhoneStatusBar statusBar, mUserSwitcherController = userSwitcher; mKeyguard = keyguard; mSecurity = security; + mBattery = battery; mCustomTileData = new CustomTileData(); final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(), @@ -277,6 +283,11 @@ public KeyguardMonitor getKeyguardMonitor() { return mKeyguard; } + @Override + public BatteryController getBatteryController() { + return mBattery; + } + public UserSwitcherController getUserSwitcherController() { return mUserSwitcherController; } @@ -294,7 +305,7 @@ public void onTuningChanged(String key, String newValue) { final List tileSpecs = loadTileSpecs(newValue); if (tileSpecs.equals(mTileSpecs)) return; for (Map.Entry> tile : mTiles.entrySet()) { - if (!tileSpecs.contains(tile.getKey())) { + if (!tileSpecs.contains(tile.getKey()) && mCustomTileData.get(tile.getKey()) == null) { if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey()); tile.getValue().destroy(); } @@ -307,10 +318,12 @@ public void onTuningChanged(String key, String newValue) { if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec); try { if (mCustomTileData.get(tileSpec) != null) { - newTiles.put(tileSpec, new CustomQSTile(this, - mCustomTileData.get(tileSpec).sbc)); + final CustomQSTile value = new CustomQSTile(this, + mCustomTileData.get(tileSpec).sbc); + newTiles.put(tileSpec, value); } else { - newTiles.put(tileSpec, createTile(tileSpec)); + final QSTile tile = createTile(tileSpec); + newTiles.put(tileSpec, tile); } } catch (Throwable t) { Log.w(TAG, "Error creating tile for spec: " + tileSpec, t); @@ -357,9 +370,16 @@ public QSTile createTile(String tileSpec) { else if (tileSpec.equals("performance")) return new PerfProfileTile(this); else if (tileSpec.equals("lockscreen")) return new LockscreenToggleTile(this); else if (tileSpec.equals("ambient_display")) return new AmbientDisplayTile(this); - else if (tileSpec.equals("live_display")) return new LiveDisplayTile(this); + else if (tileSpec.equals("heads_up")) return new HeadsUpTile(this); + else if (tileSpec.equals("battery_saver")) return new BatterySaverTile(this); + else if (tileSpec.equals("caffeine")) return new CaffeineTile(this); else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec); - else throw new IllegalArgumentException("Bad tile spec: " + tileSpec); + else if (TextUtils.split(tileSpec, "\\|").length == 3) { + /** restores placeholder for + * {@link cyanogenmod.app.StatusBarPanelCustomTile#persistableKey()} **/ + return new CustomQSTile(this, tileSpec); + } else + throw new IllegalArgumentException("Bad tile spec: " + tileSpec); } protected List loadTileSpecs(String tileList) { @@ -386,11 +406,10 @@ protected List loadTileSpecs(String tileList) { tiles.add(tile); } } - // ensure edit tile is present - if (tiles.size() < TILES_PER_PAGE && !tiles.contains("edit")) { + // ensure edit tile is present, default placement should be handled in the default + // tile list. + if (!tiles.contains("edit")) { tiles.add("edit"); - } else if (tiles.size() > TILES_PER_PAGE && !tiles.contains("edit")) { - tiles.add((TILES_PER_PAGE - 1), "edit"); } return tiles; } @@ -408,13 +427,22 @@ public void setTiles(List tiles) { TextUtils.join(",", tiles), ActivityManager.getCurrentUser()); } + public void initiateReset() { + if (mCallback != null) { + mCallback.resetTiles(); + } + } + @Override public void resetTiles() { - setEditing(false); CMSettings.Secure.putStringForUser(getContext().getContentResolver(), CMSettings.Secure.QS_TILES, "default", ActivityManager.getCurrentUser()); } + public QSTile getTile(String spec) { + return mTiles.get(spec); + } + public static int getLabelResource(String spec) { if (spec.equals("wifi")) return R.string.quick_settings_wifi_label; else if (spec.equals("bt")) return R.string.quick_settings_bluetooth_label; @@ -428,9 +456,9 @@ public static int getLabelResource(String spec) { else if (spec.equals("cast")) return R.string.quick_settings_cast_title; else if (spec.equals("hotspot")) return R.string.quick_settings_hotspot_label; else if (spec.equals("edit")) return R.string.quick_settings_edit_label; - else if (spec.equals("adb_network")) return R.string.qs_tile_adb_over_network; - else if (spec.equals("compass")) return R.string.qs_tile_compass; - else if (spec.equals("nfc")) return R.string.quick_settings_nfc; + else if (spec.equals("adb_network")) return R.string.quick_settings_network_adb_label; + else if (spec.equals("compass")) return R.string.quick_settings_compass_label; + else if (spec.equals("nfc")) return R.string.quick_settings_nfc_label; else if (spec.equals("profiles")) return R.string.quick_settings_profiles; else if (spec.equals("sync")) return R.string.quick_settings_sync_label; else if (spec.equals("volume_panel")) return R.string.quick_settings_volume_panel_label; @@ -439,14 +467,46 @@ public static int getLabelResource(String spec) { else if (spec.equals("performance")) return R.string.qs_tile_performance; else if (spec.equals("lockscreen")) return R.string.quick_settings_lockscreen_label; else if (spec.equals("ambient_display")) return R.string.quick_settings_ambient_display_label; - else if (spec.equals("live_display")) return R.string.live_display_title; + else if (spec.equals("heads_up")) return R.string.quick_settings_heads_up_label; + else if (spec.equals("battery_saver")) return R.string.quick_settings_battery_saver_label; + else if (spec.equals("caffeine")) return R.string.quick_settings_caffeine_label; + return 0; + } + + public static int getIconResource(String spec) { + if (spec.equals("wifi")) return R.drawable.ic_qs_wifi_full_4; + else if (spec.equals("bt")) return R.drawable.ic_qs_bluetooth_on; + else if (spec.equals("inversion")) return R.drawable.ic_invert_colors_enable_animation; + else if (spec.equals("cell")) return R.drawable.ic_qs_signal_full_4; + else if (spec.equals("airplane")) return R.drawable.ic_signal_airplane_enable; + else if (spec.equals("dnd")) return R.drawable.ic_dnd; + else if (spec.equals("rotation")) return R.drawable.ic_portrait_from_auto_rotate; + else if (spec.equals("flashlight")) return R.drawable.ic_signal_flashlight_enable; + else if (spec.equals("location")) return R.drawable.ic_signal_location_enable; + else if (spec.equals("cast")) return R.drawable.ic_qs_cast_on; + else if (spec.equals("hotspot")) return R.drawable.ic_hotspot_enable; + else if (spec.equals("edit")) return R.drawable.ic_qs_edit_tiles; + else if (spec.equals("adb_network")) return R.drawable.ic_qs_network_adb_on; + else if (spec.equals("compass")) return R.drawable.ic_qs_compass_on; + else if (spec.equals("nfc")) return R.drawable.ic_qs_nfc_on; + else if (spec.equals("profiles")) return R.drawable.ic_qs_profiles_on; + else if (spec.equals("sync")) return R.drawable.ic_qs_sync_on; + else if (spec.equals("volume_panel")) return R.drawable.ic_qs_volume_panel; + else if (spec.equals("usb_tether")) return R.drawable.ic_qs_usb_tether_on; + else if (spec.equals("screen_timeout")) return R.drawable.ic_qs_screen_timeout_short_avd; + else if (spec.equals("performance")) return R.drawable.ic_qs_perf_profile; + else if (spec.equals("lockscreen")) return R.drawable.ic_qs_lock_screen_on; + else if (spec.equals("ambient_display")) return R.drawable.ic_qs_ambientdisplay_on; + else if (spec.equals("heads_up")) return R.drawable.ic_qs_heads_up_on; + else if (spec.equals("battery_saver")) return R.drawable.ic_qs_battery_saver_on; + else if (spec.equals("caffeine")) return R.drawable.ic_qs_caffeine_on; return 0; } void updateCustomTile(StatusBarPanelCustomTile sbc) { synchronized (mTiles) { - if (mTiles.containsKey(sbc.getKey())) { - QSTile tile = mTiles.get(sbc.getKey()); + if (mTiles.containsKey(sbc.persistableKey())) { + QSTile tile = mTiles.get(sbc.persistableKey()); if (tile instanceof CustomQSTile) { CustomQSTile qsTile = (CustomQSTile) tile; qsTile.update(sbc); @@ -458,8 +518,8 @@ void updateCustomTile(StatusBarPanelCustomTile sbc) { void addCustomTile(StatusBarPanelCustomTile sbc) { synchronized (mTiles) { mCustomTileData.add(new CustomTileData.Entry(sbc)); - mTileSpecs.add(sbc.getKey()); - mTiles.put(sbc.getKey(), new CustomQSTile(this, sbc)); + mTileSpecs.add(sbc.persistableKey()); + mTiles.put(sbc.persistableKey(), new CustomQSTile(this, sbc)); if (mCallback != null) { mCallback.onTilesChanged(); } @@ -479,7 +539,7 @@ void removeCustomTileSysUi(String key) { } } - CustomTileData getCustomTileData() { + public CustomTileData getCustomTileData() { return mCustomTileData; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index b9e92928992fa..975cb77fdd933 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -45,9 +45,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, public static final long ANIMATION_DURATION = 220; public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR = new PathInterpolator(0f, 0, 0.7f, 1f); + public static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f; private static final float SCRIM_BEHIND_ALPHA = 0.62f; - private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f; private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f; private static final float SCRIM_IN_FRONT_ALPHA = 0.75f; private static final int TAG_KEY_ANIM = R.id.scrim; @@ -255,7 +255,7 @@ private void updateScrimNormal() { } } - private void setScrimBehindColor(float alpha) { + public void setScrimBehindColor(float alpha) { setScrimColor(mScrimBehind, alpha); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index 6624b30be5dc3..f9b1f38c8f33b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -17,9 +17,7 @@ package com.android.systemui.statusbar.phone; import android.app.ActivityManager; -import android.app.ActivityManagerNative; import android.app.AlarmManager; -import android.app.IUserSwitchObserver; import android.app.PendingIntent; import android.content.ContentUris; import android.content.ContentResolver; @@ -55,10 +53,10 @@ import android.widget.TextView; import android.widget.Toast; -import com.android.internal.logging.MetricsConstants; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.BatteryLevelTextView; import com.android.systemui.BatteryMeterView; +import com.android.systemui.DockBatteryMeterView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.cm.UserContentObserver; @@ -66,6 +64,7 @@ import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.DockBatteryController; import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.UserInfoController; @@ -77,6 +76,8 @@ import cyanogenmod.app.StatusBarPanelCustomTile; import cyanogenmod.providers.CMSettings; +import cyanogenmod.weather.util.WeatherUtils; +import org.cyanogenmod.internal.logging.CMMetricsLogger; /** * The view to manage the header area in the expanded status bar. @@ -108,6 +109,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private ImageView mQsDetailHeaderProgress; private TextView mEmergencyCallsOnly; private BatteryLevelTextView mBatteryLevel; + private BatteryLevelTextView mDockBatteryLevel; private TextView mAlarmStatus; private TextView mWeatherLine1, mWeatherLine2; private TextView mEditTileDoneText; @@ -138,7 +140,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private float mAvatarCollapsedScaleFactor; private ActivityStarter mActivityStarter; - private BatteryController mBatteryController; private NextAlarmController mNextAlarmController; private WeatherController mWeatherController; private QSDragPanel mQSPanel; @@ -157,8 +158,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private SettingsObserver mSettingsObserver; private boolean mShowWeather; private boolean mShowBatteryTextExpanded; + + private QSTile.DetailAdapter mEditingDetailAdapter; private boolean mEditing; + private UserInfoController mUserInfoController; + public StatusBarHeaderView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -189,6 +194,7 @@ protected void onFinishInflate() { mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress); mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only); mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text); + mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text); mAlarmStatus = (TextView) findViewById(R.id.alarm_status); mAlarmStatus.setOnClickListener(this); mSignalCluster = findViewById(R.id.signal_cluster); @@ -227,9 +233,18 @@ public void getOutline(View view, Outline outline) { // RenderThread is doing more harm than good when touching the header (to expand quick // settings), so disable it for this view - ((RippleDrawable) getBackground()).setForceSoftware(true); - ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true); - ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true); + Drawable d = getBackground(); + if (d instanceof RippleDrawable) { + ((RippleDrawable) d).setForceSoftware(true); + } + d = mSettingsButton.getBackground(); + if (d instanceof RippleDrawable) { + ((RippleDrawable) d).setForceSoftware(true); + } + d = mSystemIconsSuperContainer.getBackground(); + if (d instanceof RippleDrawable) { + ((RippleDrawable) d).setForceSoftware(true); + } } @Override @@ -266,10 +281,23 @@ protected void onConfigurationChanged(Configuration newConfig) { mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size); mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize; + if (mEditTileDoneText != null) { + mEditTileDoneText.setText(R.string.quick_settings_done); + } + updateClockScale(); updateClockCollapsedMargin(); } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mUserInfoController != null) { + mUserInfoController.removeListener(mUserInfoChangedListener); + } + setListening(false); + } + private void updateClockCollapsedMargin() { Resources res = getResources(); int padding = res.getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin); @@ -318,9 +346,26 @@ public void setActivityStarter(ActivityStarter activityStarter) { } public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; - ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController); - mBatteryLevel.setBatteryController(batteryController); + BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery)); + v.setBatteryStateRegistar(batteryController); + v.setBatteryController(batteryController); + mBatteryLevel.setBatteryStateRegistar(batteryController); + } + + public void setDockBatteryController(DockBatteryController dockBatteryController) { + DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery)); + if (dockBatteryController != null) { + v.setBatteryStateRegistar(dockBatteryController); + mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController); + } else { + if (v != null) { + removeView(v); + } + if (mDockBatteryLevel != null) { + removeView(mDockBatteryLevel); + mDockBatteryLevel = null; + } + } } public void setNextAlarmController(NextAlarmController nextAlarmController) { @@ -392,6 +437,10 @@ private void updateVisibilities() { mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE); mBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded); mBatteryLevel.setVisibility(View.VISIBLE); + if (mDockBatteryLevel != null) { + mDockBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded); + mDockBatteryLevel.setVisibility(View.VISIBLE); + } } private void updateSignalClusterDetachment() { @@ -471,12 +520,12 @@ public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) { @Override public void onWeatherChanged(WeatherController.WeatherInfo info) { - if (info.temp == null || info.condition == null) { + if (Double.isNaN(info.temp) || info.condition == null) { mWeatherLine1.setText(null); } else { mWeatherLine1.setText(mContext.getString( R.string.status_bar_expanded_header_weather_format, - info.temp, + WeatherUtils.formatTemperature(info.temp, info.tempUnit), info.condition)); } mWeatherLine2.setText(info.city); @@ -549,13 +598,20 @@ private void setClipping(float height) { invalidateOutline(); } + private UserInfoController.OnUserInfoChangedListener mUserInfoChangedListener = + new UserInfoController.OnUserInfoChangedListener() { + @Override + public void onUserInfoChanged(String name, Drawable picture) { + mMultiUserAvatar.setImageDrawable(picture); + } + }; + public void setUserInfoController(UserInfoController userInfoController) { - userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() { - @Override - public void onUserInfoChanged(String name, Drawable picture) { - mMultiUserAvatar.setImageDrawable(picture); - } - }); + mUserInfoController = userInfoController; + userInfoController.addListener(mUserInfoChangedListener); + if (mMultiUserSwitch != null) { + mMultiUserSwitch.setUserInfoController(mUserInfoController); + } } @Override @@ -734,6 +790,9 @@ private void applyLayoutValues(LayoutValues values) { applyAlpha(mDateCollapsed, values.dateCollapsedAlpha); applyAlpha(mDateExpanded, values.dateExpandedAlpha); applyAlpha(mBatteryLevel, values.batteryLevelAlpha); + if (mDockBatteryLevel != null) { + applyAlpha(mDockBatteryLevel, values.batteryLevelAlpha); + } applyAlpha(mSettingsContainer, values.settingsAlpha); applyAlpha(mWeatherLine1, values.settingsAlpha); applyAlpha(mWeatherLine2, values.settingsAlpha); @@ -747,13 +806,8 @@ private void applyLayoutValues(LayoutValues values) { public void setEditing(boolean editing) { mEditing = editing; - if (mEditing) { - mQsPanelCallback.onShowingDetail(new QSTile.DetailAdapter() { - @Override - public StatusBarPanelCustomTile getCustomTile() { - return null; - } - + if (editing && mEditingDetailAdapter == null) { + mEditingDetailAdapter = new QSTile.DetailAdapter() { @Override public int getTitle() { return R.string.quick_settings_edit_label; @@ -774,6 +828,11 @@ public Intent getSettingsIntent() { return null; } + @Override + public StatusBarPanelCustomTile getCustomTile() { + return null; + } + @Override public void setToggleState(boolean state) { @@ -781,12 +840,12 @@ public void setToggleState(boolean state) { @Override public int getMetricsCategory() { - return MetricsConstants.DONT_TRACK_ME_BRO; + return CMMetricsLogger.DONT_LOG; } - }); - } else { - mQsPanelCallback.onShowingDetail(null); + }; } + mQsPanelCallback.onShowingDetail(mEditing ? mEditingDetailAdapter : null); + updateEverything(); } /** @@ -865,7 +924,7 @@ public void onShowingDetail(final QSTile.DetailAdapter detail) { post(new Runnable() { @Override public void run() { - handleShowingDetail(detail); + handleShowingDetail(mEditing && detail == null ? mEditingDetailAdapter : detail); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 93ac4e01cb785..a7fa27da80af1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -482,6 +482,18 @@ public void refreshAllStatusBarIcons() { refreshAllIconsForLayout(mNotificationIcons); } + public LinearLayout getStatusIcons() { + return mStatusIcons; + } + + public void cleanup() { + TunerService.get(mContext).removeTunable(this); + mClockController.cleanup(); + if (mSignalCluster != null) { + mSignalCluster.setSecurityController(null); + } + } + private void refreshAllIconsForLayout(LinearLayout ll) { final int count = ll.getChildCount(); for (int n = 0; n < count; n++) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 20486937a1ed1..96cf093e21b9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -18,17 +18,21 @@ import android.content.ComponentCallbacks2; import android.content.Context; +import android.graphics.PixelFormat; import android.os.Bundle; import android.os.SystemClock; import android.os.Trace; +import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; +import android.view.WindowManager; import android.view.WindowManagerGlobal; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.R; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.statusbar.CommandQueue; @@ -97,7 +101,7 @@ public void registerStatusBar(PhoneStatusBar phoneStatusBar, if (mBouncer != null) mBouncer.removeView(); mFingerprintUnlockController = fingerprintUnlockController; mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils, - mStatusBarWindowManager, container); + mStatusBarWindowManager, container, mPhoneStatusBar); } /** @@ -108,23 +112,38 @@ public void show(Bundle options) { mShowing = true; mStatusBarWindowManager.setKeyguardShowing(true); mScrimController.abortKeyguardFadingOut(); - reset(); + reset(false); } /** * Shows the notification keyguard or the bouncer depending on * {@link KeyguardBouncer#needsFullscreenBouncer()}. */ - private void showBouncerOrKeyguard() { - if (mBouncer.needsFullscreenBouncer()) { - - // The keyguard might be showing (already). So we need to hide it. - mPhoneStatusBar.hideKeyguard(); - mBouncer.show(true /* resetSecuritySelection */); - } else { - mPhoneStatusBar.showKeyguard(); - mBouncer.hide(false /* destroyView */); - mBouncer.prepare(); + private void showBouncerOrKeyguard(boolean isBackPressed) { + switch (mBouncer.needsFullscreenBouncer()) { + case KeyguardBouncer.UNLOCK_SEQUENCE_FORCE_BOUNCER: + // SIM PIN/PUK + // The keyguard might be showing (already). So we need to hide it. + mPhoneStatusBar.hideKeyguard(); + mBouncer.show(true /* resetSecuritySelection */); + break; + case KeyguardBouncer.UNLOCK_SEQUENCE_BOUNCER_FIRST: + // Pattern/PIN/Password with "Directly pass to security view" enabled + if (isBackPressed) { + mPhoneStatusBar.showKeyguard(); + mBouncer.hide(false /* destroyView */); + mBouncer.prepare(); + } else { + // The keyguard might be showing (already). So we need to hide it. + mPhoneStatusBar.hideKeyguard(); + mBouncer.show(true /* resetSecuritySelection */); + } + break; + case KeyguardBouncer.UNLOCK_SEQUENCE_DEFAULT: + mPhoneStatusBar.showKeyguard(); + mBouncer.hide(false /* destroyView */); + mBouncer.prepare(); + break; } } @@ -151,14 +170,14 @@ public void dismissWithAction(OnDismissAction r, Runnable cancelAction, /** * Reset the state of the view. */ - public void reset() { + public void reset(boolean isBackPressed) { if (mShowing) { if (mOccluded) { mPhoneStatusBar.hideKeyguard(); mPhoneStatusBar.stopWaitingForKeyguardExit(); mBouncer.hide(false /* destroyView */); } else { - showBouncerOrKeyguard(); + showBouncerOrKeyguard(isBackPressed); } KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset(); updateStates(); @@ -203,6 +222,7 @@ public void onScreenTurnedOn() { public void onScreenTurnedOff() { mScreenTurnedOn = false; + mPhoneStatusBar.onScreenTurnedOff(); } public void notifyDeviceWakeUpRequested() { @@ -226,7 +246,7 @@ public void setOccluded(boolean occluded) { @Override public void run() { mStatusBarWindowManager.setKeyguardOccluded(mOccluded); - reset(); + reset(false); } }); return; @@ -235,7 +255,10 @@ public void run() { mOccluded = occluded; mStatusBarWindowManager.setKeyguardOccluded(occluded); mPhoneStatusBar.getVisualizer().setOccluded(occluded); - reset(); + if (!occluded) { + mPhoneStatusBar.mKeyguardBottomArea.setVisibility(View.GONE); + } + reset(false); } public boolean isOccluded() { @@ -362,16 +385,14 @@ public void run() { private void executeAfterKeyguardGoneAction() { if (mAfterKeyguardGoneAction != null) { + dismiss(); mAfterKeyguardGoneAction.onDismiss(); mAfterKeyguardGoneAction = null; } } - /** - * Dismisses the keyguard by going to the next screen or making it gone. - */ public void dismiss() { - if (mDeviceInteractive || mDeviceWillWakeUp) { + if ((mDeviceInteractive || mDeviceWillWakeUp)) { showBouncer(); } } @@ -398,7 +419,7 @@ public boolean isShowing() { public boolean onBackPressed() { if (mBouncer.isShowing()) { mPhoneStatusBar.endAffordanceLaunch(); - reset(); + reset(true); return true; } return false; @@ -431,7 +452,8 @@ private void updateStates() { boolean showing = mShowing; boolean occluded = mOccluded; boolean bouncerShowing = mBouncer.isShowing(); - boolean bouncerDismissible = !mBouncer.isFullscreenBouncer(); + boolean bouncerDismissible = (mBouncer.isFullscreenBouncer() != + KeyguardBouncer.UNLOCK_SEQUENCE_FORCE_BOUNCER); if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing) || mFirstUpdate) { @@ -506,7 +528,8 @@ public void run() { } public boolean shouldDisableWindowAnimationsForUnlock() { - return mPhoneStatusBar.isInLaunchTransition(); + return mPhoneStatusBar.isInLaunchTransition() || + mPhoneStatusBar.isShowingLiveLockScreenView(); } public boolean isGoingToNotificationShade() { @@ -528,6 +551,10 @@ public void keyguardGoingAway() { public void animateCollapsePanels(float speedUpFactor) { mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */, false /* delayed */, speedUpFactor); + if (mStatusBarWindowManager.keyguardExternalViewHasFocus()) { + mStatusBarWindowManager.setKeyguardExternalViewFocus(false); + dismiss(); + } } /** @@ -549,4 +576,8 @@ public ViewRootImpl getViewRootImpl() { public boolean isKeyguardShowingMedia() { return mPhoneStatusBar.isKeyguardShowingMedia(); } + + public void setKeyguardExternalViewFocus(boolean hasFocus) { + mStatusBarWindowManager.setKeyguardExternalViewFocus(hasFocus); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index 117d19df53c05..f0d7828309198 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -18,25 +18,28 @@ import android.content.Context; import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Point; import android.graphics.PixelFormat; import android.os.Handler; import android.os.SystemProperties; +import android.provider.Settings; import android.view.Gravity; import android.view.Display; import android.view.SurfaceSession; import android.view.View; import android.view.ViewGroup; -import android.view.Window; import android.view.WindowManager; -import android.view.WindowManagerPolicy; import com.android.keyguard.R; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.KeyguardMonitor; +import com.android.systemui.statusbar.policy.LiveLockScreenController; +import cyanogenmod.providers.CMSettings; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -53,8 +56,9 @@ public class StatusBarWindowManager implements KeyguardMonitor.Callback { private WindowManager.LayoutParams mLp; private WindowManager.LayoutParams mLpChanged; private int mBarHeight; - private final boolean mKeyguardScreenRotation; + private boolean mKeyguardScreenRotation; private final float mScreenBrightnessDoze; + private final boolean mBlurSupported; private boolean mKeyguardBlurEnabled; private boolean mShowingMedia; @@ -62,6 +66,7 @@ public class StatusBarWindowManager implements KeyguardMonitor.Callback { private final SurfaceSession mFxSession; private final KeyguardMonitor mKeyguardMonitor; + private int mCurrentOrientation; private static final int TYPE_LAYER_MULTIPLIER = 10000; // refer to WindowManagerService.TYPE_LAYER_MULTIPLIER private static final int TYPE_LAYER_OFFSET = 1000; // refer to WindowManagerService.TYPE_LAYER_OFFSET @@ -69,6 +74,7 @@ public class StatusBarWindowManager implements KeyguardMonitor.Callback { private static final int STATUS_BAR_LAYER = 16 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; private final State mCurrentState = new State(); + private LiveLockScreenController mLiveLockScreenController; public StatusBarWindowManager(Context context, KeyguardMonitor kgm) { mContext = context; @@ -76,18 +82,23 @@ public StatusBarWindowManager(Context context, KeyguardMonitor kgm) { mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); mScreenBrightnessDoze = mContext.getResources().getInteger( com.android.internal.R.integer.config_screenBrightnessDoze) / 255f; + mBlurSupported = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_ui_blur_enabled); mKeyguardMonitor = kgm; mKeyguardMonitor.addCallback(this); - mKeyguardBlurEnabled = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_ui_blur_enabled); mFxSession = new SurfaceSession(); } private boolean shouldEnableKeyguardScreenRotation() { Resources res = mContext.getResources(); + boolean enableAccelerometerRotation = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.ACCELEROMETER_ROTATION, 1) != 0; + boolean enableLockScreenRotation = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.LOCKSCREEN_ROTATION, 0) != 0; return SystemProperties.getBoolean("lockscreen.rot_override", false) - || res.getBoolean(R.bool.config_enableLockScreenRotation); + || (res.getBoolean(R.bool.config_enableLockScreenRotation) + && (enableLockScreenRotation && enableAccelerometerRotation)); } /** @@ -121,27 +132,34 @@ public void add(View statusBarView, int barHeight) { mLpChanged = new WindowManager.LayoutParams(); mLpChanged.copyFrom(mLp); - if (mKeyguardBlurEnabled) { + mKeyguardBlurEnabled = mBlurSupported ? + CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED, 1) == 1 : false; + if (mBlurSupported) { Display display = mWindowManager.getDefaultDisplay(); Point xy = new Point(); display.getRealSize(xy); + mCurrentOrientation = mContext.getResources().getConfiguration().orientation; mKeyguardBlur = new BlurLayer(mFxSession, xy.x, xy.y, "KeyGuard"); if (mKeyguardBlur != null) { mKeyguardBlur.setLayer(STATUS_BAR_LAYER - 2); } } + + SettingsObserver observer = new SettingsObserver(new Handler()); + observer.observe(mContext); } private void applyKeyguardFlags(State state) { if (state.keyguardShowing) { mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; - if (!mKeyguardBlurEnabled) { + if (!mKeyguardBlurEnabled || mShowingMedia) { mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; } } else { mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; - if (mKeyguardBlurEnabled) { + if (mKeyguardBlurEnabled && mKeyguardBlur != null) { mKeyguardBlur.hide(); } } @@ -339,6 +357,22 @@ public void setShowingMedia(boolean showingMedia) { applyKeyguardBlurShow(); } + public void setKeyguardExternalViewFocus(boolean hasFocus) { + mLiveLockScreenController.onLiveLockScreenFocusChanged(hasFocus); + // make the keyguard occluded so the external view gets full focus + setKeyguardOccluded(hasFocus); + } + + public void onConfigurationChanged(Configuration newConfig) { + if (mKeyguardBlur != null && newConfig.orientation != mCurrentOrientation) { + Display display = mWindowManager.getDefaultDisplay(); + Point xy = new Point(); + display.getRealSize(xy); + mKeyguardBlur.setSize(xy.x, xy.y); + mCurrentOrientation = newConfig.orientation; + } + } + /** * @param state The {@link StatusBarState} of the status bar. */ @@ -386,6 +420,14 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(mCurrentState); } + public boolean keyguardExternalViewHasFocus() { + return mLiveLockScreenController.getLiveLockScreenHasFocus(); + } + + public void setLiveLockscreenController(LiveLockScreenController liveLockScreenController) { + mLiveLockScreenController = liveLockScreenController; + } + private static class State { boolean keyguardShowing; boolean keyguardOccluded; @@ -436,4 +478,39 @@ public String toString() { return result.toString(); } } + + private class SettingsObserver extends ContentObserver { + public SettingsObserver(Handler handler) { + super(handler); + } + + public void observe(Context context) { + context.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED), + false, + this); + context.getContentResolver().registerContentObserver( + Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), + false, + this); + context.getContentResolver().registerContentObserver( + CMSettings.System.getUriFor(CMSettings.System.LOCKSCREEN_ROTATION), + false, + this); + } + + public void unobserve(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange) { + mKeyguardBlurEnabled = mBlurSupported ? + CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED, 1) == 1 : false; + mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); + // update the state + apply(mCurrentState); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 75d2283243b70..56ced84367249 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -64,8 +64,6 @@ public class StatusBarWindowView extends FrameLayout { private NotificationPanelView mNotificationPanel; private View mBrightnessMirror; - private int mRightInset = 0; - private PhoneStatusBar mService; private final Paint mTransparentSrcPaint = new Paint(); @@ -86,66 +84,6 @@ public StatusBarWindowView(Context context, AttributeSet attrs) { mSettingsObserver = new SettingsObserver(mHandler); } - @Override - protected boolean fitSystemWindows(Rect insets) { - if (getFitsSystemWindows()) { - boolean paddingChanged = insets.left != getPaddingLeft() - || insets.top != getPaddingTop() - || insets.bottom != getPaddingBottom(); - - // Super-special right inset handling, because scrims and backdrop need to ignore it. - if (insets.right != mRightInset) { - mRightInset = insets.right; - applyMargins(); - } - // Drop top inset, apply left inset and pass through bottom inset. - if (paddingChanged) { - setPadding(insets.left, 0, 0, 0); - } - insets.left = 0; - insets.top = 0; - insets.right = 0; - } else { - if (mRightInset != 0) { - mRightInset = 0; - applyMargins(); - } - boolean changed = getPaddingLeft() != 0 - || getPaddingRight() != 0 - || getPaddingTop() != 0 - || getPaddingBottom() != 0; - if (changed) { - setPadding(0, 0, 0, 0); - } - insets.top = 0; - } - return false; - } - - private void applyMargins() { - final int N = getChildCount(); - for (int i = 0; i < N; i++) { - View child = getChildAt(i); - if (child.getLayoutParams() instanceof LayoutParams) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (!lp.ignoreRightInset && lp.rightMargin != mRightInset) { - lp.rightMargin = mRightInset; - child.requestLayout(); - } - } - } - } - - @Override - public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - @Override - protected FrameLayout.LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - } - @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -190,11 +128,13 @@ public boolean onDoubleTap(MotionEvent e) { // occur if our window is translucent. Since we are drawing the whole window anyway with // the scrim, we don't need the window to be cleared in the beginning. if (mService.isScrimSrcModeEnabled()) { - IBinder windowToken = getWindowToken(); - WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams(); - lp.token = windowToken; - setLayoutParams(lp); - WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true); + if (getLayoutParams() instanceof WindowManager.LayoutParams) { + WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams(); + IBinder windowToken = getWindowToken(); + lp.token = windowToken; + setLayoutParams(lp); + WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true); + } setWillNotDraw(false); } else { setWillNotDraw(!DEBUG); @@ -207,6 +147,16 @@ protected void onDetachedFromWindow() { mSettingsObserver.unobserve(); } + @Override + protected boolean fitSystemWindows(Rect insets) { + insets.bottom = 0; + insets.top = 0; + insets.right = 0; + insets.left = 0; + super.fitSystemWindows(insets); + return false; + } + @Override public boolean dispatchKeyEvent(KeyEvent event) { boolean down = event.getAction() == KeyEvent.ACTION_DOWN; @@ -300,7 +250,7 @@ public boolean onTouchEvent(MotionEvent ev) { } @Override - public void onDraw(Canvas canvas) { + protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mService.isScrimSrcModeEnabled()) { // We need to ensure that our window is always drawn fully even when we have paddings, @@ -351,24 +301,6 @@ public void removeContent(View content) { removeView(content); } - public class LayoutParams extends FrameLayout.LayoutParams { - - public boolean ignoreRightInset; - - public LayoutParams(int width, int height) { - super(width, height); - } - - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - - TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout); - ignoreRightInset = a.getBoolean( - R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false); - a.recycle(); - } - } - class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ViewLinker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ViewLinker.java new file mode 100644 index 0000000000000..48457c6b24f62 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ViewLinker.java @@ -0,0 +1,76 @@ +package com.android.systemui.statusbar.phone; + +import android.view.View; + +/* + Allows mirroring of view states such as alpha, translation...etc + */ +public class ViewLinker { + + public static final int LINK_ALPHA = 0x1; + public static final int LINK_TRANSLATION = 0x2; + + private final LinkInfo[] mLinkedViews; + private final T mParent; + + public interface ViewLinkerCallback { + void onAlphaChanged(float alpha); + void onTranslationXChanged(float translationX); + } + + public interface ViewLinkerParent { + void registerLinker(ViewLinkerCallback callback); + } + + public static class LinkInfo { + private View mView; + private int mFlags; + public LinkInfo(View v, int linkFlags) { + mView = v; + mFlags = linkFlags; + } + private boolean supportsFlag(int flag) { + return (mFlags & flag) != 0; + } + } + + private ViewLinkerCallback mCallback = new ViewLinkerCallback() { + @Override + public void onAlphaChanged(float alpha) { + for (LinkInfo v : mLinkedViews) { + if (v.supportsFlag(LINK_ALPHA)) { + v.mView.setAlpha(alpha); + } + } + } + + @Override + public void onTranslationXChanged(float translationX) { + for (LinkInfo v : mLinkedViews) { + if (v.supportsFlag(LINK_TRANSLATION)) { + v.mView.setTranslationX(translationX); + } + } + } + }; + + public ViewLinker(T parent, LinkInfo... viewsToLink) { + mLinkedViews = viewsToLink; + mParent = parent; + ensureParentNotInLink(); + parent.registerLinker(mCallback); + } + + private void ensureParentNotInLink() { + for (LinkInfo v : mLinkedViews) { + if (v.mView == mParent) { + throw new IllegalStateException("Parent cannot be" + + "one of the linked views"); + } + } + } + + public View getParent() { + return mParent; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index a15454458c767..c59a0d8532b96 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -34,7 +34,7 @@ import cyanogenmod.providers.CMSettings; -public class BatteryController extends BroadcastReceiver { +public class BatteryController extends BroadcastReceiver implements BatteryStateRegistar { private static final String TAG = "BatteryController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -52,6 +52,7 @@ public class BatteryController extends BroadcastReceiver { private final PowerManager mPowerManager; private int mLevel; + private boolean mPresent; private boolean mPluggedIn; private boolean mCharging; private boolean mCharged; @@ -85,18 +86,21 @@ public void setUserId(int userId) { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("BatteryController state:"); pw.print(" mLevel="); pw.println(mLevel); + pw.print(" mPresent="); pw.println(mPresent); pw.print(" mPluggedIn="); pw.println(mPluggedIn); pw.print(" mCharging="); pw.println(mCharging); pw.print(" mCharged="); pw.println(mCharged); pw.print(" mPowerSave="); pw.println(mPowerSave); } + @Override public void addStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); - cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); + cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging); cb.onBatteryStyleChanged(mStyle, mPercentMode); } + @Override public void removeStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.remove(cb); } @@ -107,6 +111,7 @@ public void onReceive(Context context, Intent intent) { mLevel = (int)(100f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); + mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false); mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, @@ -140,7 +145,7 @@ private void setPowerSave(boolean powerSave) { private void fireBatteryLevelChanged() { final int N = mChangeCallbacks.size(); for (int i = 0; i < N; i++) { - mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); + mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging); } } @@ -158,12 +163,6 @@ private void fireSettingsChanged() { } } - public interface BatteryStateChangeCallback { - void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging); - void onPowerSaveChanged(); - void onBatteryStyleChanged(int style, int percentMode); - } - private final class SettingsObserver extends ContentObserver { private ContentResolver mResolver; private boolean mRegistered; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java new file mode 100644 index 0000000000000..9fe9bb47835be --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +public interface BatteryStateRegistar { + interface BatteryStateChangeCallback { + void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, boolean charging); + void onPowerSaveChanged(); + void onBatteryStyleChanged(int style, int percentMode); + } + + public void addStateChangedCallback(BatteryStateChangeCallback cb); + public void removeStateChangedCallback(BatteryStateChangeCallback cb); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java index e618cb87887d0..e7f65b4d5490c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java @@ -126,14 +126,15 @@ public void run() { public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon, final int statusType, final int qsType,final boolean activityIn, final boolean activityOut, final String typeContentDescription, - final String description, final boolean isWide, final int subId) { + final String description, final boolean isWide, final boolean showSeparateRoaming, + final int subId) { post(new Runnable() { @Override public void run() { for (SignalCallback signalCluster : mSignalCallbacks) { signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType, activityIn, activityOut, typeContentDescription, description, isWide, - subId); + showSeparateRoaming, subId); } } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java index 4d3a49f30ed29..835c8ad9150f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java @@ -115,7 +115,7 @@ private void handleDiscoveryChangeLocked() { } if (mDiscovering) { mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback, - MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); + MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); mCallbackRegistered = true; } else if (mCallbacks.size() != 0) { mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java index 186005cc21627..720ab44c41075 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -105,11 +108,19 @@ protected void updateClock() { } mCurrentTime.setTime(System.currentTimeMillis()); - - final String text = mDateFormat.format(mCurrentTime); + final String text = getDateFormat(); if (!text.equals(mLastText)) { setText(text); mLastText = text; } } + + private String getDateFormat() { + if (getContext().getResources().getBoolean( + com.android.internal.R.bool.def_custom_dateformat)) { + return DateFormat.getDateFormat(getContext()).format(mCurrentTime); + } else { + return mDateFormat.format(mCurrentTime); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java new file mode 100644 index 0000000000000..3faf7d050e3ae --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.BatteryManager; +import android.os.Handler; +import android.provider.Settings; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; + +import cyanogenmod.providers.CMSettings; + +public class DockBatteryController extends BroadcastReceiver implements BatteryStateRegistar { + + private final ArrayList mChangeCallbacks = new ArrayList<>(); + + private int mLevel; + private boolean mPresent; + private boolean mPluggedIn; + private boolean mCharging; + private boolean mCharged; + private boolean mPowerSave; + + private int mStyle; + private int mPercentMode; + private int mUserId; + private SettingsObserver mObserver; + + public DockBatteryController(Context context, Handler handler) { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + context.registerReceiver(this, filter); + + mObserver = new SettingsObserver(context, handler); + mObserver.observe(); + } + + public void setUserId(int userId) { + mUserId = userId; + mObserver.observe(); + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("BatteryController state:"); + pw.print(" mLevel="); pw.println(mLevel); + pw.print(" mPresent="); pw.println(mPresent); + pw.print(" mPluggedIn="); pw.println(mPluggedIn); + pw.print(" mCharging="); pw.println(mCharging); + pw.print(" mCharged="); pw.println(mCharged); + pw.print(" mPowerSave="); pw.println(mPowerSave); + } + + @Override + public void addStateChangedCallback(BatteryStateChangeCallback cb) { + mChangeCallbacks.add(cb); + cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging); + cb.onBatteryStyleChanged(mStyle, mPercentMode); + } + + @Override + public void removeStateChangedCallback(BatteryStateChangeCallback cb) { + mChangeCallbacks.remove(cb); + } + + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { + mLevel = (int)(100f + * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0) + / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100)); + mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false); + mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0) != 0; + + final int status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN); + mCharged = status == BatteryManager.BATTERY_STATUS_FULL; + mCharging = mPluggedIn && (mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING); + + fireBatteryLevelChanged(); + } + } + + private void fireBatteryLevelChanged() { + final int N = mChangeCallbacks.size(); + for (int i = 0; i < N; i++) { + mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPresent, mCharging); + } + } + + private void fireSettingsChanged() { + final int N = mChangeCallbacks.size(); + for (int i = 0; i < N; i++) { + mChangeCallbacks.get(i).onBatteryStyleChanged(mStyle, mPercentMode); + } + } + + private final class SettingsObserver extends ContentObserver { + private ContentResolver mResolver; + private boolean mRegistered; + + private final Uri STYLE_URI = + CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_BATTERY_STYLE); + private final Uri PERCENT_URI = + CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT); + + public SettingsObserver(Context context, Handler handler) { + super(handler); + mResolver = context.getContentResolver(); + } + + public void observe() { + if (mRegistered) { + mResolver.unregisterContentObserver(this); + } + mResolver.registerContentObserver(STYLE_URI, false, this, mUserId); + mResolver.registerContentObserver(PERCENT_URI, false, this, mUserId); + mRegistered = true; + + update(); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + update(); + } + + private void update() { + mStyle = CMSettings.System.getIntForUser(mResolver, + CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, mUserId); + mPercentMode = CMSettings.System.getIntForUser(mResolver, + CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUserId); + + fireSettingsChanged(); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java index 29a8f67e4cfed..52a2825a16a6f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java @@ -16,16 +16,26 @@ package com.android.systemui.statusbar.policy; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraManager; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.text.TextUtils; import android.util.Log; +import com.android.systemui.R; + import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -41,6 +51,12 @@ public class FlashlightController { private static final int DISPATCH_CHANGED = 1; private static final int DISPATCH_AVAILABILITY_CHANGED = 2; + private static boolean mUseWakeLock; + + private static final String ACTION_TURN_FLASHLIGHT_OFF = + "com.android.systemui.action.TURN_FLASHLIGHT_OFF"; + + private Context mContext; private final CameraManager mCameraManager; /** Call {@link #ensureHandler()} before using */ private Handler mHandler; @@ -54,7 +70,28 @@ public class FlashlightController { private final String mCameraId; private boolean mTorchAvailable; + private WakeLock mWakeLock; + + private Notification mNotification = null; + private boolean mReceiverRegistered; + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_TURN_FLASHLIGHT_OFF.equals(intent.getAction())) { + mHandler.post(new Runnable() { + @Override + public void run() { + setFlashlight(false); + } + }); + } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { + setNotificationShown(true); + } + } + }; + public FlashlightController(Context mContext) { + this.mContext = mContext; mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE); String cameraId = null; @@ -67,6 +104,11 @@ public FlashlightController(Context mContext) { mCameraId = cameraId; } + mUseWakeLock = mContext.getResources().getBoolean(R.bool.flashlight_use_wakelock); + + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + if (mCameraId != null) { ensureHandler(); mCameraManager.registerTorchCallback(mTorchCallback, mHandler); @@ -78,12 +120,25 @@ public void setFlashlight(boolean enabled) { synchronized (this) { if (mFlashlightEnabled != enabled) { mFlashlightEnabled = enabled; + + if (mUseWakeLock) { + if (enabled) { + if (!mWakeLock.isHeld()) mWakeLock.acquire(); + } else { + if (mWakeLock.isHeld()) mWakeLock.release(); + } + } + try { mCameraManager.setTorchMode(mCameraId, enabled); } catch (CameraAccessException e) { Log.e(TAG, "Couldn't set torch mode", e); mFlashlightEnabled = false; pendingError = true; + + if (mUseWakeLock && mWakeLock.isHeld()) { + mWakeLock.release(); + } } } } @@ -93,6 +148,56 @@ public void setFlashlight(boolean enabled) { } } + private void setNotificationShown(boolean showNotification) { + NotificationManager nm = (NotificationManager) + mContext.getSystemService(Context.NOTIFICATION_SERVICE); + if (showNotification) { + nm.notify(R.string.quick_settings_tile_flashlight_not_title, buildNotification()); + } else { + nm.cancel(R.string.quick_settings_tile_flashlight_not_title); + mNotification = null; + } + } + + private void setListenForScreenOff(boolean listen) { + if (listen && !mReceiverRegistered) { + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_TURN_FLASHLIGHT_OFF); + filter.addAction(Intent.ACTION_SCREEN_ON); + mContext.registerReceiver(mReceiver, filter); + mReceiverRegistered = true; + } else if (!listen) { + if (mReceiverRegistered) { + mContext.unregisterReceiver(mReceiver); + mReceiverRegistered = false; + } + setNotificationShown(false); + } + } + + private Notification buildNotification() { + if (mNotification == null) { + Intent fireMe = new Intent(ACTION_TURN_FLASHLIGHT_OFF); + fireMe.addFlags(Intent.FLAG_FROM_BACKGROUND); + fireMe.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + fireMe.setPackage(mContext.getPackageName()); + + final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, fireMe, 0); + mNotification = new Notification.Builder(mContext) + .setContentTitle( + mContext.getString(R.string.quick_settings_tile_flashlight_not_title)) + .setContentText( + mContext.getString(R.string.quick_settings_tile_flashlight_not_summary)) + .setAutoCancel(false) + .setOngoing(true) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setSmallIcon(R.drawable.ic_signal_flashlight_disable) + .setContentIntent(pendingIntent) + .build(); + } + return mNotification; + } + public synchronized boolean isEnabled() { return mFlashlightEnabled; } @@ -188,6 +293,7 @@ private void cleanUpListenersLocked(FlashlightListener listener) { public void onTorchModeUnavailable(String cameraId) { if (TextUtils.equals(cameraId, mCameraId)) { setCameraAvailable(false); + setListenForScreenOff(false); } } @@ -196,6 +302,7 @@ public void onTorchModeChanged(String cameraId, boolean enabled) { if (TextUtils.equals(cameraId, mCameraId)) { setCameraAvailable(true); setTorchMode(enabled); + setListenForScreenOff(enabled); } } @@ -204,6 +311,11 @@ private void setCameraAvailable(boolean available) { synchronized (FlashlightController.this) { changed = mTorchAvailable != available; mTorchAvailable = available; + + if (mUseWakeLock && !available) { + if (mWakeLock.isHeld()) + mWakeLock.release(); + } } if (changed) { if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")"); @@ -216,6 +328,11 @@ private void setTorchMode(boolean enabled) { synchronized (FlashlightController.this) { changed = mFlashlightEnabled != enabled; mFlashlightEnabled = enabled; + + if (mUseWakeLock && !enabled) { + if (mWakeLock.isHeld()) + mWakeLock.release(); + } } if (changed) { if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 4a95d3a4d52ab..3d1212be9d241 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -160,6 +160,10 @@ public void addListener(OnHeadsUpChangedListener listener) { mListeners.add(listener); } + public void removeListener(OnHeadsUpChangedListener listener) { + mListeners.remove(listener); + } + public PhoneStatusBar getBar() { return mBar; } @@ -453,7 +457,10 @@ public void onExpandingFinished() { mReleaseOnExpandFinish = false; } else { for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) { - removeHeadsUpEntry(entry); + if (isHeadsUp(entry.key)) { + // Maybe the heads-up was removed already + removeHeadsUpEntry(entry); + } } } mEntriesToRemoveAfterExpand.clear(); @@ -572,6 +579,9 @@ public void updateEntry() { earliestRemovaltime = currentTime + mMinimumDisplayTime; postTime = Math.max(postTime, currentTime); removeAutoRemovalCallbacks(); + if (mEntriesToRemoveAfterExpand.contains(entry)) { + mEntriesToRemoveAfterExpand.remove(entry); + } if (!hasFullScreenIntent(entry)) { long finishTime = postTime + mHeadsUpNotificationDecay; long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); 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 f6a45663650d6..6fef3d489e98b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -192,6 +192,11 @@ public void setEditMode(boolean editMode) { public void setInfo(NavbarEditor.ButtonInfo item, boolean isVertical, boolean isSmall) { final Resources res = getResources(); + setInfo(item, isVertical, isSmall, res); + } + + public void setInfo(NavbarEditor.ButtonInfo item, boolean isVertical, boolean isSmall, + Resources res) { final int keyDrawableResId; setTag(item); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LiveLockScreenController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LiveLockScreenController.java new file mode 100644 index 0000000000000..2f290ccc223e4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LiveLockScreenController.java @@ -0,0 +1,349 @@ +package com.android.systemui.statusbar.policy; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Handler; +import android.os.Looper; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.EventLog; + +import android.view.View; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.EventLogTags; +import com.android.systemui.SystemUIApplication; +import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.phone.NotificationPanelView; +import com.android.systemui.statusbar.phone.PhoneStatusBar; + +import cyanogenmod.app.CMContextConstants; +import cyanogenmod.app.ILiveLockScreenChangeListener; +import cyanogenmod.app.ILiveLockScreenManager; +import cyanogenmod.app.LiveLockScreenInfo; +import cyanogenmod.externalviews.KeyguardExternalView; + +import java.util.Objects; + +public class LiveLockScreenController { + private static final String TAG = LiveLockScreenController.class.getSimpleName(); + + private ILiveLockScreenManager mLLSM; + private Context mContext; + private PhoneStatusBar mBar; + private NotificationPanelView mPanelView; + private ComponentName mLiveLockScreenComponentName; + private KeyguardExternalView mLiveLockScreenView; + private Handler mHandler; + + private int mStatusBarState; + + private PowerManager mPowerManager; + + private boolean mLlsHasFocus = false; + + private boolean mScreenOnAndInteractive; + + private String mLlsName; + private KeyguardViewMediator mKeyguardViewMediator; + + public LiveLockScreenController(Context context, PhoneStatusBar bar, + NotificationPanelView panelView) { + mContext = context; + mHandler = new Handler(Looper.getMainLooper()); + + mLLSM = ILiveLockScreenManager.Stub.asInterface(ServiceManager.getService( + CMContextConstants.CM_LIVE_LOCK_SCREEN_SERVICE)); + mBar = bar; + mPanelView = panelView; + mPowerManager = context.getSystemService(PowerManager.class); + mKeyguardViewMediator = ((SystemUIApplication) + mContext.getApplicationContext()).getComponent(KeyguardViewMediator.class); + registerListener(); + try { + LiveLockScreenInfo llsInfo = mLLSM.getCurrentLiveLockScreen(); + if (llsInfo != null && llsInfo.component != null) { + updateLiveLockScreenView(llsInfo.component); + } + } catch (RemoteException e) { + /* ignore */ + } + } + + public void cleanup() { + unregisterListener(); + mPanelView = null; + if (mLiveLockScreenView != null) { + mLiveLockScreenView.setProviderComponent(null); + } + mLiveLockScreenView = null; + mLiveLockScreenComponentName = null; + } + + public void setBarState(int statusBarState) { + if (mStatusBarState != StatusBarState.SHADE && statusBarState == StatusBarState.SHADE) { + // going from KEYGUARD or SHADE_LOCKED to SHADE so device has been unlocked + onKeyguardDismissed(); + } + + if (statusBarState == StatusBarState.KEYGUARD) { + mBar.getScrimController().forceHideScrims(false); + } + + mStatusBarState = statusBarState; + if (statusBarState == StatusBarState.KEYGUARD || + statusBarState == StatusBarState.SHADE_LOCKED) { + if (mLiveLockScreenComponentName != null) { + if (mLiveLockScreenView == null) { + mLiveLockScreenView = + getExternalKeyguardView(mLiveLockScreenComponentName); + if (mLiveLockScreenView != null) { + mLiveLockScreenView.registerKeyguardExternalViewCallback( + mExternalKeyguardViewCallbacks); + } + } + if (mLiveLockScreenView != null && !mLiveLockScreenView.isAttachedToWindow()) { + mBar.updateRowStates(); + mPanelView.addView(mLiveLockScreenView, 0); + } + } + } else { + if (isShowingLiveLockScreenView() && !mBar.isKeyguardInputRestricted()) { + mPanelView.removeView(mLiveLockScreenView); + } + mLlsHasFocus = false; + } + } + + private ILiveLockScreenChangeListener mChangeListener = + new ILiveLockScreenChangeListener.Stub() { + @Override + public void onLiveLockScreenChanged(LiveLockScreenInfo llsInfo) throws RemoteException { + if (mPanelView != null) { + updateLiveLockScreenView(llsInfo != null ? llsInfo.component : null); + } + } + }; + + private void registerListener() { + try { + mLLSM.registerChangeListener(mChangeListener); + } catch (RemoteException e) { + /* ignore */ + } + } + + private void unregisterListener() { + try { + mLLSM.unregisterChangeListener(mChangeListener); + } catch (RemoteException e) { + /* ignore */ + } + } + + private KeyguardExternalView getExternalKeyguardView(ComponentName componentName) { + try { + return new KeyguardExternalView(mContext, null, componentName); + } catch (Exception e) { + // just return null below and move on + } + return null; + } + + private KeyguardExternalView.KeyguardExternalViewCallbacks mExternalKeyguardViewCallbacks = + new KeyguardExternalView.KeyguardExternalViewCallbacks() { + @Override + public boolean requestDismiss() { + if (isShowingLiveLockScreenView()) { + mHandler.post(new Runnable() { + @Override + public void run() { + mBar.showKeyguard(); + mBar.showBouncer(); + } + }); + return true; + } + return false; + } + + @Override + public boolean requestDismissAndStartActivity(final Intent intent) { + if (isShowingLiveLockScreenView()) { + mHandler.post(new Runnable() { + @Override + public void run() { + mBar.startActivityDismissingKeyguard(intent, false, true, true, + null); + } + }); + return true; + } + return false; + } + + @Override + public void providerDied() { + mLiveLockScreenView.unregisterKeyguardExternalViewCallback( + mExternalKeyguardViewCallbacks); + mLiveLockScreenView = null; + // make sure we're showing the notification panel if the LLS crashed while it had focus + if (mLlsHasFocus) { + mLlsHasFocus = false; + mHandler.post(new Runnable() { + @Override + public void run() { + mBar.showKeyguard(); + } + }); + } + } + + @Override + public void slideLockscreenIn() { + if (mLlsHasFocus) { + mHandler.post(new Runnable() { + @Override + public void run() { + mBar.showKeyguard(); + } + }); + } + } + }; + + public boolean isShowingLiveLockScreenView() { + return mLiveLockScreenView != null && mLiveLockScreenView.isAttachedToWindow(); + } + + public boolean isLiveLockScreenInteractive() { + return mLiveLockScreenView != null && mLiveLockScreenView.isInteractive(); + } + + public KeyguardExternalView getLiveLockScreenView() { + return mLiveLockScreenView; + } + + public void onScreenTurnedOn() { + mScreenOnAndInteractive = mPowerManager.isInteractive(); + if (mScreenOnAndInteractive) { + if (mLiveLockScreenView != null) mLiveLockScreenView.onScreenTurnedOn(); + EventLog.writeEvent(EventLogTags.SYSUI_LLS_KEYGUARD_SHOWING, 1); + } + } + + public void onScreenTurnedOff() { + if (mScreenOnAndInteractive) { + if (mLiveLockScreenView != null) mLiveLockScreenView.onScreenTurnedOff(); + if (mStatusBarState != StatusBarState.SHADE) { + EventLog.writeEvent(EventLogTags.SYSUI_LLS_KEYGUARD_SHOWING, 0); + } + mScreenOnAndInteractive = false; + } + } + + public void onLiveLockScreenFocusChanged(boolean hasFocus) { + mKeyguardViewMediator.notifyKeyguardPanelFocusChanged(hasFocus); + if (mLiveLockScreenView != null) { + // make sure the LLS knows where the notification panel is + mLiveLockScreenView.onLockscreenSlideOffsetChanged(hasFocus ? 0f : 1f); + } + // don't log focus changes when screen is not interactive + if (hasFocus != mLlsHasFocus && mPowerManager.isInteractive()) { + EventLog.writeEvent(EventLogTags.SYSUI_LLS_NOTIFICATION_PANEL_SHOWN, + hasFocus ? 0 : 1); + } + // Hide statusbar and scrim if live lockscreen + // currently has focus + mBar.setStatusBarViewVisibility(!hasFocus); + mBar.getScrimController().forceHideScrims(hasFocus); + mLlsHasFocus = hasFocus; + } + + public void onKeyguardDismissed() { + if (mLiveLockScreenView != null) mLiveLockScreenView.onKeyguardDismissed(); + EventLog.writeEvent(EventLogTags.SYSUI_LLS_KEYGUARD_DISMISSED, mLlsHasFocus ? 1 : 0); + // Ensure we reset visibility when keyguard is dismissed + mBar.setStatusBarViewVisibility(true); + mBar.getScrimController().forceHideScrims(false); + } + + public boolean getLiveLockScreenHasFocus() { + return mLlsHasFocus; + } + + public String getLiveLockScreenName() { + return mLlsName; + } + + private String getLlsNameFromComponentName(ComponentName cn) { + if (cn == null) return null; + + PackageManager pm = mContext.getPackageManager(); + Intent intent = new Intent(); + intent.setComponent(cn); + ResolveInfo ri = pm.resolveService(intent, 0); + return ri != null ? ri.serviceInfo.loadLabel(pm).toString() : null; + } + + private Runnable mAddNewLiveLockScreenRunnable = new Runnable() { + @Override + public void run() { + if (mLiveLockScreenComponentName != null) { + mLiveLockScreenView = + getExternalKeyguardView(mLiveLockScreenComponentName); + mLiveLockScreenView.registerKeyguardExternalViewCallback( + mExternalKeyguardViewCallbacks); + if (mStatusBarState != StatusBarState.SHADE) { + mPanelView.addView(mLiveLockScreenView); + mLiveLockScreenView.onKeyguardShowing(true); + } + } else { + mLiveLockScreenView = null; + } + } + }; + + private void updateLiveLockScreenView(final ComponentName cn) { + mHandler.post(new Runnable() { + @Override + public void run() { + // If mThirdPartyKeyguardViewComponent differs from cn, go ahead and update + if (!Objects.equals(mLiveLockScreenComponentName, cn)) { + mLiveLockScreenComponentName = cn; + mLlsName = getLlsNameFromComponentName(cn); + if (mLiveLockScreenView != null) { + mLiveLockScreenView.unregisterKeyguardExternalViewCallback( + mExternalKeyguardViewCallbacks); + // setProviderComponent(null) will unbind the existing service + mLiveLockScreenView.setProviderComponent(null); + if (mPanelView.indexOfChild(mLiveLockScreenView) >= 0) { + mLiveLockScreenView.registerOnWindowAttachmentChangedListener( + new KeyguardExternalView.OnWindowAttachmentChangedListener() { + @Override + public void onAttachedToWindow() { + } + + @Override + public void onDetachedFromWindow() { + mLiveLockScreenView + .unregisterOnWindowAttachmentChangedListener( + this); + mHandler.post(mAddNewLiveLockScreenRunnable); + } + } + ); + mPanelView.removeView(mLiveLockScreenView); + } else { + mAddNewLiveLockScreenRunnable.run(); + } + } + } + } + }); + } +} 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 33df7a84b43ba..f7d6f852b7c2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -19,6 +19,7 @@ import android.content.Intent; import android.net.NetworkCapabilities; import android.os.Looper; +import android.os.SystemProperties; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -238,6 +239,7 @@ public void notifyListeners() { int typeIcon = showDataIcon ? icons.mDataType : 0; mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, activityIn, activityOut, dataContentDescription, description, icons.mIsWide, + mCurrentState.showSeparateRoaming, mSubscriptionInfo.getSubscriptionId()); } @@ -277,13 +279,15 @@ public boolean isEmergencyOnly() { } private boolean isRoaming() { - if (isCdma()) { + if (mServiceState == null) { + return false; + } else if (isCdma()) { final int iconMode = mServiceState.getCdmaEriIconMode(); return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH); } else { - return mServiceState != null && mServiceState.getRoaming(); + return mServiceState.getRoaming(); } } @@ -393,12 +397,18 @@ private final void updateTelephony() { mCurrentState.iconGroup = mDefaultIcons; } mCurrentState.dataConnected = mCurrentState.connected - && mDataState == TelephonyManager.DATA_CONNECTED; + && mDataState == TelephonyManager.DATA_CONNECTED + && mCurrentState.dataSim; + mCurrentState.showSeparateRoaming = false; if (isCarrierNetworkChangeActive()) { mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; } else if (isRoaming()) { - mCurrentState.iconGroup = TelephonyIcons.ROAMING; + if (SystemProperties.getBoolean("ro.config.always_show_roaming", false)) { + mCurrentState.showSeparateRoaming = true; + } else { + mCurrentState.iconGroup = TelephonyIcons.ROAMING; + } } if (isEmergencyOnly() != mCurrentState.isEmergency) { mCurrentState.isEmergency = isEmergencyOnly(); @@ -469,6 +479,7 @@ public void onServiceStateChanged(ServiceState state) { + " dataState=" + state.getDataRegState()); } mServiceState = state; + mDataNetType = state.getDataNetworkType(); updateTelephony(); } @@ -530,6 +541,7 @@ static class MobileState extends SignalController.State { boolean airplaneMode; boolean carrierNetworkChangeMode; boolean isDefault; + boolean showSeparateRoaming; @Override public void copyFrom(State s) { @@ -543,6 +555,7 @@ public void copyFrom(State s) { isEmergency = state.isEmergency; airplaneMode = state.airplaneMode; carrierNetworkChangeMode = state.carrierNetworkChangeMode; + showSeparateRoaming = state.showSeparateRoaming; } @Override @@ -557,6 +570,7 @@ protected void toString(StringBuilder builder) { builder.append("isEmergency=").append(isEmergency).append(','); builder.append("airplaneMode=").append(airplaneMode).append(','); builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode); + builder.append("showSeparateRoaming=").append(showSeparateRoaming); } @Override @@ -569,7 +583,8 @@ public boolean equals(Object o) { && ((MobileState) o).isEmergency == isEmergency && ((MobileState) o).airplaneMode == airplaneMode && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode - && ((MobileState) o).isDefault == isDefault; + && ((MobileState) o).isDefault == isDefault + && ((MobileState) o).showSeparateRoaming == showSeparateRoaming; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 8023ea67ac6f2..57b0dba6cb0e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -40,7 +40,7 @@ void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId); + String description, boolean isWide, boolean showSeparateRoaming, int subId); void setSubs(List subs); void setNoSims(boolean show); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 78507beaa1a67..7e1bf05e1751f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -245,6 +245,10 @@ public void addEmergencyListener(EmergencyListener listener) { mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly()); } + public void removeEmergencyListener(EmergencyListener listener) { + mCallbackHandler.setListening(listener, false); + } + public boolean hasMobileDataFeature() { return mHasMobileDataFeature; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java index dce889f831dab..f13ef9fce1a1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java @@ -37,7 +37,7 @@ public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState q @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, - String description, boolean isWide, int subId) { + String description, boolean isWide, boolean showSeparateRoaming, int subId) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java index 5e9447e57170f..72e3a063a9fca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java @@ -256,6 +256,7 @@ static class State { IconGroup iconGroup; int inetCondition; int rssi; // Only for logging. + boolean showSeparateRoaming; // Not used for comparison, just used for logging. long time; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java index a8d4f131b54ed..58168e8e82b5d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java @@ -54,6 +54,7 @@ public final class UserInfoController { private boolean mUseDefaultAvatar; private String mUserName; private Drawable mUserDrawable; + private boolean mProfileSetup; public UserInfoController(Context context) { mContext = context; @@ -73,6 +74,10 @@ public void addListener(OnUserInfoChangedListener callback) { mCallbacks.add(callback); } + public void removeListener (OnUserInfoChangedListener callback) { + mCallbacks.remove(callback); + } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -158,24 +163,23 @@ protected Pair doInBackground(Void... params) { mUseDefaultAvatar = true; } - // If it's a single-user device, get the profile name, since the nickname is not - // usually valid - if (um.getUsers().size() <= 1) { - // Try and read the display name from the local profile - final Cursor cursor = context.getContentResolver().query( - ContactsContract.Profile.CONTENT_URI, new String[] { - ContactsContract.CommonDataKinds.Phone._ID, - ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME - }, null, null, null); - if (cursor != null) { - try { - if (cursor.moveToFirst()) { - name = cursor.getString(cursor.getColumnIndex( - ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); - } - } finally { - cursor.close(); + mProfileSetup = false; + + // Try and read the display name from the local profile + final Cursor cursor = context.getContentResolver().query( + ContactsContract.Profile.CONTENT_URI, new String[] { + ContactsContract.CommonDataKinds.Phone._ID, + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + }, null, null, null); + if (cursor != null) { + try { + if (cursor.moveToFirst()) { + mProfileSetup = true; + name = cursor.getString(cursor.getColumnIndex( + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); } + } finally { + cursor.close(); } } return new Pair(name, avatar); @@ -198,6 +202,10 @@ private void notifyChanged() { } } + public boolean isProfileSetup() { + return mProfileSetup; + } + public interface OnUserInfoChangedListener { public void onUserInfoChanged(String name, Drawable picture); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java index 1fa49568fd554..0f71bccaa8220 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherController.java @@ -25,8 +25,9 @@ public interface Callback { void onWeatherChanged(WeatherInfo temp); } public static class WeatherInfo { - public String temp = null; + public double temp = Double.NaN; public String city = null; public String condition = null; + public int tempUnit; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java index 288bc7efd8a44..1a798f07d1422 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WeatherControllerImpl.java @@ -16,43 +16,49 @@ package com.android.systemui.statusbar.policy; -import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Handler; -import android.provider.Settings; import android.util.Log; +import cyanogenmod.providers.CMSettings; +import cyanogenmod.providers.WeatherContract; +import cyanogenmod.weather.CMWeatherManager; +import cyanogenmod.weather.util.WeatherUtils; import java.util.ArrayList; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.CURRENT_CITY; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.CURRENT_CONDITION; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.CURRENT_TEMPERATURE; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.CURRENT_TEMPERATURE_UNIT; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.TempUnit.CELSIUS; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.TempUnit.FAHRENHEIT; + public class WeatherControllerImpl implements WeatherController { private static final String TAG = WeatherController.class.getSimpleName(); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private WeatherContentObserver mWeatherContentObserver; + private Handler mHandler; + private int mWeatherUnit; + private Uri mWeatherTempetarureUri; public static final ComponentName COMPONENT_WEATHER_FORECAST = new ComponentName( "com.cyanogenmod.lockclock", "com.cyanogenmod.lockclock.weather.ForecastActivity"); - public static final String ACTION_UPDATE_FINISHED - = "com.cyanogenmod.lockclock.action.WEATHER_UPDATE_FINISHED"; - public static final String EXTRA_UPDATE_CANCELLED = "update_cancelled"; public static final String ACTION_FORCE_WEATHER_UPDATE = "com.cyanogenmod.lockclock.action.FORCE_WEATHER_UPDATE"; - public static final Uri CURRENT_WEATHER_URI - = Uri.parse("content://com.cyanogenmod.lockclock.weather.provider/weather/current"); - public static final String[] WEATHER_PROJECTION = new String[]{ - "temperature", - "city", - "condition" + private static final String[] WEATHER_PROJECTION = new String[]{ + CURRENT_TEMPERATURE, + CURRENT_TEMPERATURE_UNIT, + CURRENT_CITY, + CURRENT_CONDITION }; private final ArrayList mCallbacks = new ArrayList(); - private final Receiver mReceiver = new Receiver(); private final Context mContext; private WeatherInfo mCachedInfo = new WeatherInfo(); @@ -60,10 +66,16 @@ public class WeatherControllerImpl implements WeatherController { public WeatherControllerImpl(Context context) { mContext = context; mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + mHandler = new Handler(); + mWeatherContentObserver = new WeatherContentObserver(mHandler); + mWeatherTempetarureUri + = CMSettings.Global.getUriFor(CMSettings.Global.WEATHER_TEMPERATURE_UNIT); + mContext.getContentResolver().registerContentObserver( + WeatherContract.WeatherColumns.CURRENT_WEATHER_URI,true, mWeatherContentObserver); + mContext.getContentResolver().registerContentObserver(mWeatherTempetarureUri, true, + mWeatherContentObserver); + queryWeatherTempUnit(); queryWeather(); - final IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_UPDATE_FINISHED); - mContext.registerReceiver(mReceiver, filter); } public void addCallback(Callback callback) { @@ -85,17 +97,29 @@ public WeatherInfo getWeatherInfo() { } private void queryWeather() { - Cursor c = mContext.getContentResolver().query(CURRENT_WEATHER_URI, WEATHER_PROJECTION, + Cursor c = mContext.getContentResolver().query( + WeatherContract.WeatherColumns.CURRENT_WEATHER_URI, WEATHER_PROJECTION, null, null, null); if (c == null) { if(DEBUG) Log.e(TAG, "cursor was null for temperature, forcing weather update"); + //LockClock keeps track of the user settings (temp unit, search by geo location/city) + //so we delegate the responsibility of handling a weather update to LockClock mContext.sendBroadcast(new Intent(ACTION_FORCE_WEATHER_UPDATE)); } else { try { c.moveToFirst(); - mCachedInfo.temp = c.getString(0); - mCachedInfo.city = c.getString(1); - mCachedInfo.condition = c.getString(2); + double temp = c.getDouble(0); + int reportedUnit = c.getInt(1); + if (reportedUnit == CELSIUS && mWeatherUnit == FAHRENHEIT) { + temp = WeatherUtils.celsiusToFahrenheit(temp); + } else if (reportedUnit == FAHRENHEIT && mWeatherUnit == CELSIUS) { + temp = WeatherUtils.fahrenheitToCelsius(temp); + } + + mCachedInfo.temp = temp; + mCachedInfo.tempUnit = mWeatherUnit; + mCachedInfo.city = c.getString(2); + mCachedInfo.condition = c.getString(3); } finally { c.close(); } @@ -108,19 +132,53 @@ private void fireCallback() { } } - private final class Receiver extends BroadcastReceiver { + private class WeatherContentObserver extends ContentObserver { + + public WeatherContentObserver(Handler handler) { + super(handler); + } + @Override - public void onReceive(Context context, Intent intent) { - if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction()); - if (intent.hasExtra(EXTRA_UPDATE_CANCELLED)) { - if (intent.getBooleanExtra(EXTRA_UPDATE_CANCELLED, false)) { - // no update - return; + public void onChange(boolean selfChange, Uri uri) { + if (uri != null) { + if (uri.compareTo(WeatherContract.WeatherColumns.CURRENT_WEATHER_URI) == 0) { + queryWeather(); + fireCallback(); + } else if (uri.compareTo(mWeatherTempetarureUri) == 0) { + queryWeatherTempUnit(); + fixCachedWeatherInfo(); + fireCallback(); + } else { + super.onChange(selfChange, uri); } } - queryWeather(); - fireCallback(); + } + + @Override + public void onChange(boolean selfChange) { + onChange(selfChange, null); } } + private void queryWeatherTempUnit() { + try { + mWeatherUnit = CMSettings.Global.getInt(mContext.getContentResolver(), + CMSettings.Global.WEATHER_TEMPERATURE_UNIT); + } catch (CMSettings.CMSettingNotFoundException e) { + //CMSettingsProvider should have taken care of setting a default value for this setting + //so how is that we ended up here?? We need to set a valid temp unit anyway to keep + //this going + mWeatherUnit = WeatherContract.WeatherColumns.TempUnit.CELSIUS; + } + } + + private void fixCachedWeatherInfo() { + if (mCachedInfo.tempUnit == CELSIUS && mWeatherUnit == FAHRENHEIT) { + mCachedInfo.temp = WeatherUtils.celsiusToFahrenheit(mCachedInfo.temp); + mCachedInfo.tempUnit = FAHRENHEIT; + } else if (mCachedInfo.tempUnit == FAHRENHEIT && mWeatherUnit == CELSIUS) { + mCachedInfo.temp = WeatherUtils.fahrenheitToCelsius(mCachedInfo.temp); + mCachedInfo.tempUnit = CELSIUS; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 4ec8b430db4af..b6e131acec864 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -50,6 +50,7 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.phone.ViewLinker; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ScrollAdapter; @@ -63,7 +64,8 @@ */ public class NotificationStackScrollLayout extends ViewGroup implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter, - ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener { + ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener, + ViewLinker.ViewLinkerParent { private static final String TAG = "NotificationStackScrollLayout"; private static final boolean DEBUG = false; @@ -211,8 +213,6 @@ public class NotificationStackScrollLayout extends ViewGroup private boolean mDisallowScrollingInThisMotion; private long mGoToFullShadeDelay; - private final PerformanceManager mPerf; - private ViewTreeObserver.OnPreDrawListener mChildrenUpdater = new ViewTreeObserver.OnPreDrawListener() { @Override @@ -236,6 +236,7 @@ public boolean onPreDraw() { private boolean mForceNoOverlappingRendering; private NotificationOverflowContainer mOverflowContainer; private final ArrayList> mTmpList = new ArrayList<>(); + private ViewLinker.ViewLinkerCallback mLinkerCallback; public NotificationStackScrollLayout(Context context) { this(context, null); @@ -259,8 +260,6 @@ public NotificationStackScrollLayout(Context context, AttributeSet attrs, int de mExpandHelper.setEventSource(this); mExpandHelper.setScrollAdapter(this); - mPerf = PerformanceManager.getInstance(context); - mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext()); mSwipeHelper.setLongPressListener(mLongPressListener); initView(context); @@ -847,10 +846,6 @@ public boolean onTouchEvent(MotionEvent ev) { horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev); } - if (expandWantsIt && mIsBeingDragged) { - mPerf.cpuBoost(200 * 1000); - } - return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev); } @@ -2887,6 +2882,23 @@ public boolean hasOverlappingRendering() { return !mForceNoOverlappingRendering && super.hasOverlappingRendering(); } + @Override + public void registerLinker(ViewLinker.ViewLinkerCallback callback) { + mLinkerCallback = callback; + } + + @Override + public void setAlpha(float alpha) { + super.setAlpha(alpha); + mLinkerCallback.onAlphaChanged(alpha); + } + + @Override + public void setTranslationX(float translationX) { + super.setTranslationX(translationX); + mLinkerCallback.onTranslationXChanged(translationX); + } + /** * A listener that is notified when some child locations might have changed. */ diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java index a2b062c8b7104..0ae34bf97a982 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java @@ -155,7 +155,7 @@ private void startDemoMode() { getContext().sendBroadcast(intent); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_CLOCK); - intent.putExtra("hhmm", "0600"); + intent.putExtra("hhmm", "1230"); getContext().sendBroadcast(intent); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_NETWORK); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java index b186323b3a5d5..53fbef7b66039 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java @@ -155,11 +155,15 @@ public boolean isEditing() { public void goToSettingsPage() { } + @Override + public void resetTiles() { + } + private static class CustomHost extends QSTileHost { public CustomHost(Context context) { super(context, null, null, null, null, null, null, null, null, null, - null, null, new BlankSecurityController()); + null, null, new BlankSecurityController(), null); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java new file mode 100644 index 0000000000000..c33954140be9b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarIconBlacklistFragment.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.tuner; + +import android.annotation.Nullable; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceFragment; + +import android.preference.PreferenceGroup; +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.StatusBarIconController; + +public class StatusBarIconBlacklistFragment extends PreferenceFragment { + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.tuner_statusbar_icons); + } + + @Override + public void onResume() { + super.onResume(); + registerPrefs(getPreferenceScreen()); + } + + @Override + public void onPause() { + super.onPause(); + unregisterPrefs(getPreferenceScreen()); + } + + private void registerPrefs(PreferenceGroup group) { + TunerService tunerService = TunerService.get(getContext()); + final int N = group.getPreferenceCount(); + for (int i = 0; i < N; i++) { + Preference pref = group.getPreference(i); + if (pref instanceof StatusBarSwitch) { + tunerService.addTunable((TunerService.Tunable) pref, StatusBarIconController.ICON_BLACKLIST); + } else if (pref instanceof PreferenceGroup) { + registerPrefs((PreferenceGroup) pref); + } + } + } + + private void unregisterPrefs(PreferenceGroup group) { + TunerService tunerService = TunerService.get(getContext()); + final int N = group.getPreferenceCount(); + for (int i = 0; i < N; i++) { + Preference pref = group.getPreference(i); + if (pref instanceof TunerService.Tunable) { + tunerService.removeTunable((TunerService.Tunable) pref); + } else if (pref instanceof PreferenceGroup) { + registerPrefs((PreferenceGroup) pref); + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java index c84f61865522c..401fb0e2bcab8 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java @@ -16,7 +16,9 @@ package com.android.systemui.tuner; import android.app.Activity; +import android.app.Fragment; import android.os.Bundle; +import android.view.MenuItem; public class TunerActivity extends Activity { @@ -27,4 +29,43 @@ protected void onCreate(Bundle savedInstanceState) { .commit(); } + /** + * Base class for direct entry points into + * tuner fragments + */ + private static abstract class FragmentTunerActivityBase extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getActionBar().setDisplayHomeAsUpEnabled(true); + getFragmentManager().beginTransaction().replace(android.R.id.content, + getFragment()).commit(); + } + + protected abstract Fragment getFragment(); + + @Override + public final boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + } + + public static final class DemoModeActivity extends FragmentTunerActivityBase { + @Override + protected Fragment getFragment() { + return new DemoModeFragment(); + } + } + + public static final class StatusBarIconActivity extends FragmentTunerActivityBase { + @Override + protected Fragment getFragment() { + return new StatusBarIconBlacklistFragment(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java index 1ff5ceff2e18b..0bc663b0be56a 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java @@ -44,18 +44,13 @@ public class TunerFragment extends PreferenceFragment { private static final String TAG = "TunerFragment"; - private static final String KEY_QS_TUNER = "qs_tuner"; + private static final String KEY_STATUSBAR_BLACKLIST = "statusbar_icon_blacklist"; private static final String KEY_DEMO_MODE = "demo_mode"; - private static final String KEY_BATTERY_PCT = "battery_pct"; public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning"; private static final int MENU_REMOVE = Menu.FIRST + 1; - private final SettingObserver mSettingObserver = new SettingObserver(); - - private SwitchPreference mBatteryPct; - public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -63,11 +58,12 @@ public void onCreate(Bundle savedInstanceState) { getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); setHasOptionsMenu(true); - findPreference(KEY_QS_TUNER).setOnPreferenceClickListener(new OnPreferenceClickListener() { + findPreference(KEY_STATUSBAR_BLACKLIST).setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(android.R.id.content, new QsTuner(), "QsTuner"); + ft.replace(android.R.id.content, new StatusBarIconBlacklistFragment(), + "StatusBarBlacklist"); ft.addToBackStack(null); ft.commit(); return true; @@ -83,7 +79,6 @@ public boolean onPreferenceClick(Preference preference) { return true; } }); - mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT); if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING, 0) == 0) { new AlertDialog.Builder(getContext()) @@ -102,7 +97,6 @@ public void onClick(DialogInterface dialog, int which) { @Override public void onResume() { super.onResume(); - updateBatteryPct(); registerPrefs(getPreferenceScreen()); MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true); @@ -111,7 +105,6 @@ public void onResume() { @Override public void onPause() { super.onPause(); - getContext().getContentResolver().unregisterContentObserver(mSettingObserver); unregisterPrefs(getPreferenceScreen()); MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false); @@ -165,30 +158,4 @@ public void run() { } return super.onOptionsItemSelected(item); } - - private void updateBatteryPct() { - mBatteryPct.setOnPreferenceChangeListener(null); - mBatteryPct.setOnPreferenceChangeListener(mBatteryPctChange); - } - - private final class SettingObserver extends ContentObserver { - public SettingObserver() { - super(new Handler()); - } - - @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - super.onChange(selfChange, uri, userId); - updateBatteryPct(); - } - } - - private final OnPreferenceChangeListener mBatteryPctChange = new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean v = (Boolean) newValue; - MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v); - return true; - } - }; } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java index b2c90be6923f0..3e7477c0f5a4e 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java @@ -132,6 +132,12 @@ protected void reregisterAll() { public void reloadSetting(Uri uri) { String key = mListeningUris.get(uri); + + // Handle possible null keys + if (TextUtils.isEmpty(key)) { + return; + } + String value; if (uri.getAuthority().equals(CMSettings.AUTHORITY)) { value = CMSettings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 7d34cdc4cad12..baa53217b54c1 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -327,7 +327,7 @@ private Notification onVolumeMounted(VolumeInfo vol) { // Don't annoy when user dismissed in past. (But make sure the disk is adoptable; we // used to allow snoozing non-adoptable disks too.) - if (rec.isSnoozed() && disk.isAdoptable()) { + if (rec == null || (rec.isSnoozed() && disk.isAdoptable())) { return null; } @@ -364,6 +364,11 @@ private Notification onVolumeMounted(VolumeInfo vol) { .setContentIntent(browseIntent) .setCategory(Notification.CATEGORY_SYSTEM) .setPriority(Notification.PRIORITY_LOW); + // USB disks notification can be persistent + if (disk.isUsb()) { + builder.setOngoing(mContext.getResources().getBoolean( + R.bool.config_persistUsbDriveNotification)); + } // Non-adoptable disks can't be snoozed. if (disk.isAdoptable()) { builder.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid())); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index e9f1095c0a60f..9fda531eaff47 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -31,6 +31,7 @@ import android.content.res.Resources; import android.graphics.Color; import android.graphics.PixelFormat; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.ColorDrawable; @@ -42,6 +43,7 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; +import android.provider.Settings; import android.provider.Settings.Global; import android.util.DisplayMetrics; import android.util.Log; @@ -104,7 +106,6 @@ public class VolumeDialog { private final SpTexts mSpTexts; private final SparseBooleanArray mDynamic = new SparseBooleanArray(); private final KeyguardManager mKeyguard; - private final AudioManager mAudioManager; private final int mExpandButtonAnimationDuration; private final ZenFooter mZenFooter; private final LayoutTransition mLayoutTransition; @@ -128,15 +129,15 @@ public class VolumeDialog { private boolean mPendingStateChanged; private boolean mPendingRecheckAll; private long mCollapseTime; + private int mLastActiveStream; public VolumeDialog(Context context, int windowType, VolumeDialogController controller, - ZenModeController zenModeController, Callback callback) { + ZenModeController zenModeController, Callback callback) { mContext = context; mController = controller; mCallback = callback; mSpTexts = new SpTexts(mContext); mKeyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); - mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mDialog = new CustomDialog(mContext); @@ -163,7 +164,7 @@ public VolumeDialog(Context context, int windowType, VolumeDialogController cont window.setAttributes(lp); window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); - mActiveSliderTint = loadColorStateList(R.color.system_accent_color); + mActiveSliderTint = loadColorStateList(R.color.volume_slider_active); mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive); mDialog.setContentView(R.layout.volume_dialog); mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog); @@ -177,19 +178,19 @@ public VolumeDialog(Context context, int windowType, VolumeDialogController cont mDialogContentView.setLayoutTransition(mLayoutTransition); mMotion = new VolumeDialogMotion(mDialog, mDialogView, mDialogContentView, mExpandButton, new VolumeDialogMotion.Callback() { - @Override - public void onAnimatingChanged(boolean animating) { - if (animating) return; - if (mPendingStateChanged) { - mHandler.sendEmptyMessage(H.STATE_CHANGED); - mPendingStateChanged = false; - } - if (mPendingRecheckAll) { - mHandler.sendEmptyMessage(H.RECHECK_ALL); - mPendingRecheckAll = false; - } - } - }); + @Override + public void onAnimatingChanged(boolean animating) { + if (animating) return; + if (mPendingStateChanged) { + mHandler.sendEmptyMessage(H.STATE_CHANGED); + mPendingStateChanged = false; + } + if (mPendingRecheckAll) { + mHandler.sendEmptyMessage(H.RECHECK_ALL); + mPendingRecheckAll = false; + } + } + }); addRow(AudioManager.STREAM_RING, R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true); @@ -272,11 +273,15 @@ private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) row.settingsButton.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - final boolean moved = oldLeft != left || oldTop != top; + int oldLeft, int oldTop, int oldRight, int oldBottom) { + final boolean moved = mLastActiveStream != mActiveStream || + oldLeft != left || oldTop != top; if (D.BUG) Log.d(TAG, "onLayoutChange moved=" + moved + " old=" + new Rect(oldLeft, oldTop, oldRight, oldBottom).toShortString() - + " new=" + new Rect(left,top,right,bottom).toShortString()); + + "," + mLastActiveStream + + " new=" + new Rect(left,top,right,bottom).toShortString() + + "," + mActiveStream); + mLastActiveStream = mActiveStream; if (moved) { for (int i = 0; i < mDialogContentView.getChildCount(); i++) { final View c = mDialogContentView.getChildAt(i); @@ -362,6 +367,8 @@ private VolumeRow initRow(final int stream, int iconRes, int iconMuteRes, boolea row.header = (TextView) row.view.findViewById(R.id.volume_row_header); mSpTexts.add(row.header); row.slider = (SeekBar) row.view.findViewById(R.id.volume_row_slider); + row.slider.setProgressTintMode(PorterDuff.Mode.SRC_ATOP); + row.slider.setThumbTintMode(PorterDuff.Mode.SRC_ATOP); row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); // forward events above the slider into the slider @@ -597,13 +604,17 @@ private void trimObsoleteH() { final VolumeRow row = mRows.get(i); if (row.ss == null || !row.ss.dynamic) continue; if (!mDynamic.get(row.stream)) { - mRows.remove(i); - mDialogContentView.removeView(row.view); - mDialogContentView.removeView(row.space); + removeRow(row); } } } + private void removeRow(VolumeRow volumeRow) { + mRows.remove(volumeRow); + mDialogContentView.removeView(volumeRow.view); + mDialogContentView.removeView(volumeRow.space); + } + private void onStateChangedH(State state) { final boolean animating = mMotion.isAnimating(); if (D.BUG) Log.d(TAG, "onStateChangedH animating=" + animating); @@ -624,6 +635,8 @@ private void onStateChangedH(State state) { } } + updateNotificationRowH(); + if (mActiveStream != state.activeStream) { mActiveStream = state.activeStream; updateRowsH(); @@ -635,11 +648,23 @@ private void onStateChangedH(State state) { updateFooterH(); } + private void updateNotificationRowH() { + VolumeRow notificationRow = findRow(AudioManager.STREAM_NOTIFICATION); + if (notificationRow != null) { + if (mState.linkedNotification) { + removeRow(notificationRow); + } + } else if (!mState.linkedNotification) { + addRow(AudioManager.STREAM_NOTIFICATION, + R.drawable.ic_volume_notification, R.drawable.ic_volume_notification_mute, + true); + } + } + private void updateFooterH() { if (D.BUG) Log.d(TAG, "updateFooterH"); final boolean wasVisible = mZenFooter.getVisibility() == View.VISIBLE; - final boolean visible = mState.zenMode != Global.ZEN_MODE_OFF - && mAudioManager.isStreamAffectedByRingerMode(mActiveStream); + final boolean visible = mState.zenMode != Global.ZEN_MODE_OFF; if (wasVisible != visible && !visible) { prepareForCollapse(); } @@ -663,8 +688,9 @@ private void updateVolumeRowH(VolumeRow row) { final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM; final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM; final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC; - final boolean isRingVibrate = isRingStream - && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; + final boolean isNotificationStream = row.stream == AudioManager.STREAM_NOTIFICATION; + final boolean isVibrate = mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; + final boolean isRingVibrate = isRingStream && isVibrate; final boolean isRingSilent = isRingStream && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT; final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS; @@ -672,8 +698,9 @@ private void updateVolumeRowH(VolumeRow row) { final boolean isZenPriority = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; final boolean isRingZenNone = (isRingStream || isSystemStream) && isZenNone; final boolean isRingLimited = isRingStream && isZenPriority; - final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream) - : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream) + final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream || isNotificationStream) + : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream || isNotificationStream) + : isVibrate ? (isNotificationStream) : false; // update slider max @@ -708,12 +735,12 @@ private void updateVolumeRowH(VolumeRow row) { row.icon.setAlpha(iconEnabled ? 1 : 0.5f); final int iconRes = isRingVibrate ? R.drawable.ic_volume_ringer_vibrate - : isRingSilent || zenMuted ? row.cachedIconRes - : ss.routedToBluetooth ? + : isRingSilent || zenMuted ? row.cachedIconRes + : ss.routedToBluetooth ? (ss.muted ? R.drawable.ic_volume_media_bt_mute : R.drawable.ic_volume_media_bt) - : mAutomute && ss.level == 0 ? row.iconMuteRes - : (ss.muted ? row.iconMuteRes : row.iconRes); + : mAutomute && ss.level == 0 ? row.iconMuteRes + : (ss.muted ? row.iconMuteRes : row.iconRes); if (iconRes != row.cachedIconRes) { if (row.cachedIconRes != 0 && isRingVibrate) { mController.vibrate(); @@ -723,11 +750,11 @@ private void updateVolumeRowH(VolumeRow row) { } row.iconState = iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE - : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes) + : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes) ? Events.ICON_STATE_MUTE - : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes) + : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes) ? Events.ICON_STATE_UNMUTE - : Events.ICON_STATE_UNKNOWN; + : Events.ICON_STATE_UNKNOWN; row.icon.setContentDescription(ss.name); // update slider @@ -934,6 +961,12 @@ public void run() { } }; + public void cleanup() { + mController.removeCallback(mControllerCallbackH); + mZenFooter.cleanup(); + mAccessibility.cleanup(); + } + private final class H extends Handler { private static final int SHOW = 1; private static final int DISMISS = 2; @@ -1056,36 +1089,21 @@ private final class Accessibility extends AccessibilityDelegate { public void init() { mMgr = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); - mDialogView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { - @Override - public void onViewDetachedFromWindow(View v) { - if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow"); - // noop - } - - @Override - public void onViewAttachedToWindow(View v) { - if (D.BUG) Log.d(TAG, "onViewAttachedToWindow"); - updateFeedbackEnabled(); - } - }); - mDialogView.setAccessibilityDelegate(this); - mMgr.addAccessibilityStateChangeListener(new AccessibilityStateChangeListener() { - @Override - public void onAccessibilityStateChanged(boolean enabled) { - updateFeedbackEnabled(); - } - }); + mDialogView.addOnAttachStateChangeListener(mOnAttachStateChangeListener); updateFeedbackEnabled(); } @Override public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, - AccessibilityEvent event) { + AccessibilityEvent event) { rescheduleTimeoutH(); return super.onRequestSendAccessibilityEvent(host, child, event); } + public void cleanup() { + mDialogView.removeOnAttachStateChangeListener(mOnAttachStateChangeListener); + } + private void updateFeedbackEnabled() { mFeedbackEnabled = computeFeedbackEnabled(); } @@ -1101,6 +1119,21 @@ private boolean computeFeedbackEnabled() { } return false; } + + private OnAttachStateChangeListener mOnAttachStateChangeListener = + new OnAttachStateChangeListener() { + @Override + public void onViewDetachedFromWindow(View v) { + if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow"); + // noop + } + + @Override + public void onViewAttachedToWindow(View v) { + if (D.BUG) Log.d(TAG, "onViewAttachedToWindow"); + updateFeedbackEnabled(); + } + }; } private static class VolumeRow { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java index 1083f407b4218..742b18b38ec66 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java @@ -43,7 +43,7 @@ public class VolumeDialogComponent implements VolumeComponent { private final Context mContext; private final VolumeDialogController mController; private final ZenModeController mZenModeController; - private final VolumeDialog mDialog; + private VolumeDialog mDialog; private final VolumePolicy mVolumePolicy = new VolumePolicy( true, // volumeDownToEnterSilent true, // volumeUpToExitSilent @@ -138,4 +138,11 @@ public void onZenPrioritySettingsClicked() { } }; + public void recreateDialog() { + if (mDialog != null) mDialog.cleanup(); + + mDialog = new VolumeDialog(mContext, WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY, + mController, mZenModeController, mVolumeDialogCallback); + applyConfiguration(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java index 32d68054a6af0..9269c1c89172d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java @@ -29,6 +29,7 @@ import android.media.AudioManager; import android.media.AudioSystem; import android.media.IVolumeController; +import android.media.ToneGenerator; import android.media.VolumePolicy; import android.media.session.MediaController.PlaybackInfo; import android.media.session.MediaSession.Token; @@ -54,6 +55,8 @@ import java.util.Map; import java.util.Objects; +import cyanogenmod.providers.CMSettings; + /** * Source of truth for all state / events related to the volume dialog. No presentation. * @@ -67,6 +70,9 @@ public class VolumeDialogController { private static final int DYNAMIC_STREAM_START_INDEX = 100; private static final int VIBRATE_HINT_DURATION = 50; + private static final int FREE_DELAY = 10000; + private static final int BEEP_DURATION = 150; + private static final int[] STREAMS = { AudioSystem.STREAM_ALARM, AudioSystem.STREAM_BLUETOOTH_SCO, @@ -102,10 +108,13 @@ public class VolumeDialogController { private VolumePolicy mVolumePolicy; private boolean mShowDndTile = true; + private ToneGenerator mToneGenerators[]; + public VolumeDialogController(Context context, ComponentName component) { mContext = context.getApplicationContext(); Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED); mComponent = component; + mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()]; mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName()); mWorkerThread.start(); mWorker = new W(mWorkerThread.getLooper()); @@ -289,6 +298,7 @@ private void onVolumeChangedW(int stream, int flags) { final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0; final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0; final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0; + final boolean playSound = (flags & AudioManager.FLAG_PLAY_SOUND) != 0; boolean changed = false; if (showUI) { changed |= updateActiveStreamW(stream); @@ -308,6 +318,19 @@ private void onVolumeChangedW(int stream, int flags) { if (showSilentHint) { mCallbacks.onShowSilentHint(); } + if (playSound) { + if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) { + mWorker.removeMessages(W.PLAY_SOUND); + mWorker.sendMessageDelayed(mWorker.obtainMessage(W.PLAY_SOUND, stream, flags), + AudioSystem.PLAY_SOUND_DELAY); + } + + if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { + mWorker.removeMessages(W.PLAY_SOUND); + onStopSoundsW(); + } + + } if (changed && fromKey) { Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume); } @@ -348,6 +371,7 @@ private void onGetStateW() { updateZenModeW(); updateEffectsSuppressorW(mNoMan.getEffectsSuppressor()); updateZenModeConfigW(); + updateLinkNotificationConfigW(); mCallbacks.onStateChanged(mState); } @@ -400,6 +424,16 @@ private static boolean isRinger(int stream) { return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION; } + private boolean updateLinkNotificationConfigW() { + boolean linkNotificationWithVolume = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1; + if (mState.linkedNotification == linkNotificationWithVolume) { + return false; + } + mState.linkedNotification = linkNotificationWithVolume; + return true; + } + private boolean updateZenModeConfigW() { final ZenModeConfig zenModeConfig = getZenModeConfig(); if (Objects.equals(mState.zenModeConfig, zenModeConfig)) return false; @@ -556,6 +590,9 @@ private final class W extends Handler { private static final int NOTIFY_VISIBLE = 12; private static final int USER_ACTIVITY = 13; private static final int SHOW_SAFETY_WARNING = 14; + private static final int PLAY_SOUND = 15; + private static final int STOP_SOUNDS = 16; + private static final int FREE_RESOURCES = 17; W(Looper looper) { super(looper); @@ -578,6 +615,9 @@ public void handleMessage(Message msg) { case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break; case USER_ACTIVITY: onUserActivityW(); break; case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break; + case PLAY_SOUND: onPlaySoundW(msg.arg1, msg.arg2); break; + case STOP_SOUNDS: onStopSoundsW(); break; + case FREE_RESOURCES: onFreeResourcesW(); break; } } } @@ -707,6 +747,66 @@ public void run() { } + protected void onPlaySoundW(int streamType, int flags) { + + // If preference is no sound - just exit here + if (CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.VOLUME_ADJUST_SOUNDS_ENABLED, 1) == 0) { + return; + } + + if (mWorker.hasMessages(W.STOP_SOUNDS)) { + mWorker.removeMessages(W.STOP_SOUNDS); + // Force stop right now + onStopSoundsW(); + } + + ToneGenerator toneGen = getOrCreateToneGeneratorW(streamType); + if (toneGen != null) { + toneGen.startTone(ToneGenerator.TONE_PROP_BEEP); + mWorker.sendMessageDelayed(mWorker.obtainMessage(W.STOP_SOUNDS), BEEP_DURATION); + } + + mWorker.removeMessages(W.FREE_RESOURCES); + mWorker.sendMessageDelayed(mWorker.obtainMessage(W.FREE_RESOURCES), FREE_DELAY); + } + + protected void onStopSoundsW() { + int numStreamTypes = AudioSystem.getNumStreamTypes(); + for (int i = numStreamTypes - 1; i >= 0; i--) { + ToneGenerator toneGen = mToneGenerators[i]; + if (toneGen != null) { + toneGen.stopTone(); + } + } + } + + private ToneGenerator getOrCreateToneGeneratorW(int streamType) { + if (mToneGenerators[streamType] == null) { + try { + mToneGenerators[streamType] = new ToneGenerator(streamType, + ToneGenerator.MAX_VOLUME); + } catch (RuntimeException e) { + if (false) { + Log.d(TAG, "ToneGenerator constructor failed with " + + "RuntimeException: " + e); + } + } + } + return mToneGenerators[streamType]; + } + + protected void onFreeResourcesW() { + synchronized (this) { + for (int i = mToneGenerators.length - 1; i >= 0; i--) { + if (mToneGenerators[i] != null) { + mToneGenerators[i].release(); + } + mToneGenerators[i] = null; + } + } + } + private final class SettingObserver extends ContentObserver { private final Uri SERVICE_URI = Settings.Secure.getUriFor( Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT); @@ -714,6 +814,8 @@ private final class SettingObserver extends ContentObserver { Settings.Global.getUriFor(Settings.Global.ZEN_MODE); private final Uri ZEN_MODE_CONFIG_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG); + private final Uri VOLUME_LINK_NOTIFICATION_URI = + Settings.Secure.getUriFor(Settings.Secure.VOLUME_LINK_NOTIFICATION); public SettingObserver(Handler handler) { super(handler); @@ -723,6 +825,8 @@ public void init() { mContext.getContentResolver().registerContentObserver(SERVICE_URI, false, this); mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this); mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_URI, false, this); + mContext.getContentResolver().registerContentObserver(VOLUME_LINK_NOTIFICATION_URI, + false, this); onChange(true, SERVICE_URI); } @@ -750,6 +854,9 @@ public void onChange(boolean selfChange, Uri uri) { if (ZEN_MODE_CONFIG_URI.equals(uri)) { changed = updateZenModeConfigW(); } + if (VOLUME_LINK_NOTIFICATION_URI.equals(uri)) { + changed = updateLinkNotificationConfigW(); + } if (changed) { mCallbacks.onStateChanged(mState); } @@ -868,6 +975,13 @@ public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) { @Override public void onRemoteVolumeChanged(Token token, int flags) { + // If an inactive session changed the remoteVolume, bail + // since we don't have any active streams to update + if (!mRemoteStreams.containsKey(token)) { + Log.i(TAG, "onRemoteVolumeChanged called on inactive" + + "stream. Ignoring"); + return; + } final int stream = mRemoteStreams.get(token); final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0; boolean changed = updateActiveStreamW(stream); @@ -947,6 +1061,7 @@ public static final class State { public String effectsSuppressorName; public ZenModeConfig zenModeConfig; public int activeStream = NO_ACTIVE_STREAM; + public boolean linkedNotification; public State copy() { final State rt = new State(); @@ -960,6 +1075,7 @@ public State copy() { rt.effectsSuppressorName = effectsSuppressorName; if (zenModeConfig != null) rt.zenModeConfig = zenModeConfig.copy(); rt.activeStream = activeStream; + rt.linkedNotification = linkedNotification; return rt; } @@ -989,6 +1105,7 @@ public String toString(int indent) { sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName); sep(sb, indent); sb.append("zenModeConfig:").append(zenModeConfig); sep(sb, indent); sb.append("activeStream:").append(activeStream); + sep(sb, indent); sb.append("linkedNotification:").append(linkedNotification); if (indent > 0) sep(sb, indent); return sb.append('}').toString(); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index e49ff5032bcff..fa0de7d272c8f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -97,9 +97,8 @@ protected void onConfigurationChanged(Configuration newConfig) { getVolumeComponent().onConfigurationChanged(newConfig); if (isThemeChange(newConfig)) { - // TODO: implement initPanel() if needed - //initPanel(); mContext.recreateTheme(); + mVolumeComponent.recreateDialog(); } mConfiguration.setTo(newConfig); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java index af7ee0856cb67..0fb80c0cc7727 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java @@ -69,17 +69,19 @@ protected void onFinishInflate() { mSpTexts.add(mEndNowButton); } + private ZenModeController.Callback mZenModeCallback = new ZenModeController.Callback() { + @Override + public void onZenChanged(int zen) { + setZen(zen); + } + @Override + public void onConfigChanged(ZenModeConfig config) { + setConfig(config); + } + }; + public void init(final ZenModeController controller) { - controller.addCallback(new ZenModeController.Callback() { - @Override - public void onZenChanged(int zen) { - setZen(zen); - } - @Override - public void onConfigChanged(ZenModeConfig config) { - setConfig(config); - } - }); + controller.addCallback(mZenModeCallback); mEndNowButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -142,4 +144,8 @@ public void onConfigurationChanged() { mSpTexts.update(); } + public void cleanup() { + mController.removeCallback(mZenModeCallback); + } + } diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index 33377149aed8d..ddf623a728ce5 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -70,9 +70,7 @@ public class ZenModePanel extends LinearLayout { private static final int SECONDS_MS = 1000; private static final int MINUTES_MS = 60 * SECONDS_MS; - private static final int[] MINUTE_BUCKETS = DEBUG - ? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 } - : ZenModeConfig.MINUTE_BUCKETS; + private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS; private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0]; private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1]; private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60); @@ -421,8 +419,13 @@ private void updateWidgets() { mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE); } final String warning = computeAlarmWarningText(zenNone); - mZenAlarmWarning.setVisibility(warning != null ? VISIBLE : GONE); + final int oldVis = mZenAlarmWarning.getVisibility(); + final int newVis = warning != null ? VISIBLE : GONE; + mZenAlarmWarning.setVisibility(newVis); mZenAlarmWarning.setText(warning); + if (newVis != oldVis) { + requestLayout(); + } } private String computeAlarmWarningText(boolean zenNone) { @@ -511,7 +514,7 @@ private Condition getTimeUntilNextAlarmCondition() { GregorianCalendar weekRange = new GregorianCalendar(); final long now = weekRange.getTimeInMillis(); setToMidnight(weekRange); - weekRange.roll(Calendar.DATE, 6); + weekRange.add(Calendar.DATE, 6); final long nextAlarmMs = mController.getNextAlarm(); if (nextAlarmMs > 0) { GregorianCalendar nextAlarm = new GregorianCalendar(); @@ -603,13 +606,6 @@ private void bind(final Condition condition, final View row, final int rowId) { if (DEBUG) Log.d(mTag, "bind i=" + mZenConditions.indexOfChild(row) + " first=" + first + " condition=" + conditionId); tag.rb.setEnabled(enabled); - final boolean checked = (mSessionExitCondition != null - || mAttachedZen != Global.ZEN_MODE_OFF) - && (sameConditionId(mSessionExitCondition, tag.condition)); - if (checked != tag.rb.isChecked()) { - if (DEBUG) Log.d(mTag, "bind checked=" + checked + " condition=" + conditionId); - tag.rb.setChecked(checked); - } tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index 739286956aa34..25581e3743bde 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -33,7 +33,9 @@ LOCAL_PACKAGE_NAME := SystemUITests LOCAL_STATIC_JAVA_LIBRARIES := mockito-target Keyguard LOCAL_STATIC_JAVA_LIBRARIES += org.cyanogenmod.platform.internal \ android-support-v7-palette \ - android-support-v4 + android-support-v4 \ + uicommon + # sign this with platform cert, so this test is allowed to inject key events into # UI it doesn't own. This is necessary to allow screenshots to be taken diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java index 00b8de237347c..7df96a9dbd194 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java @@ -103,9 +103,10 @@ public void testSignalCallback_setMobileDataIndicators() { int type = R.drawable.stat_sys_data_fully_connected_1x; int qsType = R.drawable.ic_qs_signal_1x; boolean wide = true; + boolean showSeparateRoamIndicator = false; int subId = 5; mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription, - description, wide, subId); + description, wide, showSeparateRoamIndicator, subId); waitForCallbacks(); ArgumentCaptor statusArg = ArgumentCaptor.forClass(IconState.class); @@ -117,11 +118,13 @@ public void testSignalCallback_setMobileDataIndicators() { ArgumentCaptor typeContentArg = ArgumentCaptor.forClass(String.class); ArgumentCaptor descArg = ArgumentCaptor.forClass(String.class); ArgumentCaptor wideArg = ArgumentCaptor.forClass(Boolean.class); + ArgumentCaptor showSeparateRoamIndicatorArg = + ArgumentCaptor.forClass(Boolean.class); ArgumentCaptor subIdArg = ArgumentCaptor.forClass(Integer.class); Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(), qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(), outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(), - subIdArg.capture()); + showSeparateRoamIndicatorArg.capture(), subIdArg.capture()); assertEquals(status, statusArg.getValue()); assertEquals(qs, qsArg.getValue()); assertEquals(type, (int) typeIconArg.getValue()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 30c08cdd224a7..5e87ea16d0ebd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -59,8 +59,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected NetworkControllerImpl mNetworkController; protected MobileSignalController mMobileSignalController; protected PhoneStateListener mPhoneStateListener; - private SignalStrength mSignalStrength; - private ServiceState mServiceState; + protected SignalStrength mSignalStrength; + protected ServiceState mServiceState; protected ConnectivityManager mMockCm; protected WifiManager mMockWm; protected SubscriptionManager mMockSm; @@ -234,7 +234,7 @@ private void updateSignalStrength() { mPhoneStateListener.onSignalStrengthsChanged(mSignalStrength); } - private void updateServiceState() { + protected void updateServiceState() { Log.d(TAG, "Sending Service State: " + mServiceState); mPhoneStateListener.onServiceStateChanged(mServiceState); } @@ -245,6 +245,7 @@ public void updateCallState(int state) { } public void updateDataConnectionState(int dataState, int dataNetType) { + when(mServiceState.getDataNetworkType()).thenReturn(dataNetType); mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType); } @@ -279,6 +280,7 @@ protected void verifyLastQsMobileDataIndicators(boolean visible, int icon, int t ArgumentCaptor.forClass(String.class).capture(), ArgumentCaptor.forClass(String.class).capture(), ArgumentCaptor.forClass(Boolean.class).capture(), + ArgumentCaptor.forClass(Boolean.class).capture(), ArgumentCaptor.forClass(Integer.class).capture()); IconState iconState = iconArg.getValue(); assertEquals("Visibility in, quick settings", visible, iconState.visible); @@ -305,6 +307,7 @@ protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typ ArgumentCaptor.forClass(String.class).capture(), ArgumentCaptor.forClass(String.class).capture(), ArgumentCaptor.forClass(Boolean.class).capture(), + ArgumentCaptor.forClass(Boolean.class).capture(), ArgumentCaptor.forClass(Integer.class).capture()); IconState iconState = iconArg.getValue(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index 0ec8802f9c602..3e0da3c332116 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -114,6 +114,21 @@ public void test4gDataIconConfigChange() { TelephonyIcons.QS_DATA_4G); } + public void testDataChangeWithoutConnectionState() { + setupDefaultSignal(); + updateDataConnectionState(TelephonyManager.DATA_CONNECTED, + TelephonyManager.NETWORK_TYPE_LTE); + + verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */], + TelephonyIcons.QS_DATA_LTE); + + Mockito.when(mServiceState.getDataNetworkType()) + .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA); + updateServiceState(); + verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */], + TelephonyIcons.QS_DATA_H); + } + public void testDataActivity() { setupDefaultSignal(); diff --git a/packages/VpnDialogs/res/values-as-rIN/strings.xml b/packages/VpnDialogs/res/values-as-rIN/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-as-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-ast-rES/strings.xml b/packages/VpnDialogs/res/values-ast-rES/strings.xml new file mode 100644 index 0000000000000..7b17f142ff59a --- /dev/null +++ b/packages/VpnDialogs/res/values-ast-rES/strings.xml @@ -0,0 +1,48 @@ + + + + + + Solicitú de conexón + + %s quier facer una conexón VPN + que permite monitorear el tráficu. Aceuta namái si confíes na fonte. + +
+ + ]]> apaez arriba na pantalla cuando VPN ta activa. +
+ + VPN coneutada + + Configurar + + Desconeutar + + Sesión: + + Duración: + + Unvióse: + + Recibióse: + + + %1$s bytes / + %2$s paquetes +     +
diff --git a/packages/VpnDialogs/res/values-be/strings.xml b/packages/VpnDialogs/res/values-be/strings.xml new file mode 100644 index 0000000000000..4903231c28b5c --- /dev/null +++ b/packages/VpnDialogs/res/values-be/strings.xml @@ -0,0 +1,48 @@ + + + + + + Запыт на злучэнне + + %sхоча ўсталяваць злучэнне VPN + гэта дазваляе яму кантраляваць сеткавы трафік. Працягвайце, калі вы давяраеце крыніцы. + +
+ + ]]>адлюстроўваецца ў верхняй частцы экрана, калі VPN-актыўны. +
+ + VPN падключаны + + Налады + + Адключыцца + + Сэсія: + + Працягласць: + + Дасланыя: + + Атрымана: + + + %1$s байт / + %2$s пакетаў + +
diff --git a/packages/VpnDialogs/res/values-br-rFR/strings.xml b/packages/VpnDialogs/res/values-br-rFR/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-br-rFR/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-bs-rBA/strings.xml b/packages/VpnDialogs/res/values-bs-rBA/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-bs-rBA/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-csb-rPL/strings.xml b/packages/VpnDialogs/res/values-csb-rPL/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-csb-rPL/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-cy/strings.xml b/packages/VpnDialogs/res/values-cy/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-cy/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-en-rPT/strings.xml b/packages/VpnDialogs/res/values-en-rPT/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-en-rPT/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-eo/strings.xml b/packages/VpnDialogs/res/values-eo/strings.xml new file mode 100644 index 0000000000000..946765c354b76 --- /dev/null +++ b/packages/VpnDialogs/res/values-eo/strings.xml @@ -0,0 +1,29 @@ + + + + + + + + + + Malkonekti + + + + + + diff --git a/packages/VpnDialogs/res/values-es-rCO/strings.xml b/packages/VpnDialogs/res/values-es-rCO/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-es-rCO/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-es-rMX/strings.xml b/packages/VpnDialogs/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-es-rMX/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-frp-rIT/strings.xml b/packages/VpnDialogs/res/values-frp-rIT/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-frp-rIT/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-fy-rNL/strings.xml b/packages/VpnDialogs/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-fy-rNL/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-ga-rIE/strings.xml b/packages/VpnDialogs/res/values-ga-rIE/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-ga-rIE/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-gd-rGB/strings.xml b/packages/VpnDialogs/res/values-gd-rGB/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-gd-rGB/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-ku/strings.xml b/packages/VpnDialogs/res/values-ku/strings.xml new file mode 100644 index 0000000000000..65b63807a77c5 --- /dev/null +++ b/packages/VpnDialogs/res/values-ku/strings.xml @@ -0,0 +1,39 @@ + + + + + + + + VPN پەیوەستکراوە + + رێکخستن + + پچڕاندنی پەیوەندی + + دانشتن: + + ماوه‌: + + گەیشت: + + گەیشت: + + + %1$s بایت / + %2$s گیرفانەکان + + diff --git a/packages/VpnDialogs/res/values-lb/strings.xml b/packages/VpnDialogs/res/values-lb/strings.xml new file mode 100644 index 0000000000000..f598ac6b540a5 --- /dev/null +++ b/packages/VpnDialogs/res/values-lb/strings.xml @@ -0,0 +1,47 @@ + + + + + + Connectiounsufro + + %s wëll eng VPN-Connectioun opstellen, wouduerch den Netzwierktrafic kann iwwerwaacht ginn. Acceptéier dat just, wann s du der Quell vertraus. + +
+ + ]]> erschéngt uewen um Schierm, wa VPN aktiv ass. +
+ + VPN connectéiert + + Astellen + + Deconnectéieren + + Sëtzung: + + Dauer: + + Geschéckt: + + Empfaangen: + + + %1$s Bytes / + %2$s Päck +     +
diff --git a/packages/VpnDialogs/res/values-oc-rFR/strings.xml b/packages/VpnDialogs/res/values-oc-rFR/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-oc-rFR/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-or-rIN/strings.xml b/packages/VpnDialogs/res/values-or-rIN/strings.xml new file mode 100644 index 0000000000000..4afbe1f506ef9 --- /dev/null +++ b/packages/VpnDialogs/res/values-or-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/packages/VpnDialogs/res/values-ug/strings.xml b/packages/VpnDialogs/res/values-ug/strings.xml new file mode 100644 index 0000000000000..f85983d77e57e --- /dev/null +++ b/packages/VpnDialogs/res/values-ug/strings.xml @@ -0,0 +1,39 @@ + + + + + + باغلىنىش ئىلتىماسى + + %s سىزنىڭ VPN ئۇلىنىشىنى بېكىتىشىڭىزنى تەلەپ قىلىدۇ، تورنى نازارەت قىلدۇ. ئەگەر سىز ئىشەنسىڭىز يول قويۇڭ. +
]]> ئېكراننىڭ چوققىسىدا كۆرۈنسە، VPN نىڭ ئاكتىپ ئىكەنلىكىنى بىلدۈرىدۇ.
+ + VPN باغلاندى + + سەپلىمە + + ئۈز + + سۆزلىشىش + + داۋاملىشىش ۋاقتى: + + ئەۋەتىلگىنى: + + تاپشۇرۇۋالغىنى: + + %1$s بايت/%2$s بوغچا +
diff --git a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java index e9703670008d8..96d29fd41074f 100644 --- a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java +++ b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java @@ -185,7 +185,6 @@ public int processMessage(String app_id, String content_type, Intent intent) WapPushManDBHelper dbh = getDatabase(mContext); SQLiteDatabase db = dbh.getReadableDatabase(); WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, app_id, content_type); - db.close(); if (lastapp == null) { Log.w(LOG_TAG, "no receiver app found for " + app_id + ":" + content_type); @@ -284,7 +283,6 @@ public boolean addPackage(String x_app_id, String content_type, ret = true; } - db.close(); return ret; } @@ -308,7 +306,6 @@ public boolean updatePackage(String x_app_id, String content_type, WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type); if (lastapp == null) { - db.close(); return false; } @@ -328,7 +325,6 @@ public boolean updatePackage(String x_app_id, String content_type, + package_name + "." + class_name + ", sq:" + lastapp.installOrder); - db.close(); return num > 0; } @@ -346,7 +342,6 @@ public boolean deletePackage(String x_app_id, String content_type, + " and class_name=\'" + class_name + "\'"; int num_removed = db.delete(APPID_TABLE_NAME, where, null); - db.close(); if (LOCAL_LOGV) Log.v(LOG_TAG, "deleted " + num_removed + " rows:" + x_app_id + ":" + content_type + " " + package_name + "." + class_name); @@ -399,7 +394,6 @@ public boolean verifyData(String x_app_id, String content_type, if (LOCAL_LOGV) Log.v(LOG_TAG, "verifyData app id: " + x_app_id + " content type: " + content_type + " lastapp: " + lastapp); - db.close(); if (lastapp == null) return false; @@ -430,7 +424,6 @@ public boolean isDataExist(String x_app_id, String content_type, SQLiteDatabase db = dbh.getReadableDatabase(); boolean ret = dbh.queryLastApp(db, x_app_id, content_type) != null; - db.close(); return ret; } diff --git a/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml b/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml index 54f8ff3e94053..97cd62081b08b 100644 --- a/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml +++ b/packages/WallpaperCropper/res/layout/actionbar_set_wallpaper.xml @@ -32,5 +32,5 @@ android:drawablePadding="8dp" android:gravity="center_vertical" android:text="@string/wallpaper_instructions" - android:textColor="@android:color/white" /> + android:textColor="@color/set_wallpaper_text_color" />
diff --git a/packages/WallpaperCropper/res/values-as-rIN/strings.xml b/packages/WallpaperCropper/res/values-as-rIN/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-as-rIN/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-ast-rES/strings.xml b/packages/WallpaperCropper/res/values-ast-rES/strings.xml new file mode 100644 index 0000000000000..caa847e8fc524 --- /dev/null +++ b/packages/WallpaperCropper/res/values-ast-rES/strings.xml @@ -0,0 +1,26 @@ + + + + + Recortar el fondu de pantalla + + Afitar fondu de pantalla + + Nun pudo cargase la imaxe como fondu de pantalla + diff --git a/packages/WallpaperCropper/res/values-be/strings.xml b/packages/WallpaperCropper/res/values-be/strings.xml new file mode 100644 index 0000000000000..d8cce31412e41 --- /dev/null +++ b/packages/WallpaperCropper/res/values-be/strings.xml @@ -0,0 +1,26 @@ + + + + + Абрэзаць шпалеру + + Усталяваць шпалеру + + Не атрымалася загрузіць выяву + diff --git a/packages/WallpaperCropper/res/values-br-rFR/strings.xml b/packages/WallpaperCropper/res/values-br-rFR/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-br-rFR/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-bs-rBA/strings.xml b/packages/WallpaperCropper/res/values-bs-rBA/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-bs-rBA/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-csb-rPL/strings.xml b/packages/WallpaperCropper/res/values-csb-rPL/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-csb-rPL/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-cy/strings.xml b/packages/WallpaperCropper/res/values-cy/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-cy/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-en-rPT/strings.xml b/packages/WallpaperCropper/res/values-en-rPT/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-en-rPT/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-eo/strings.xml b/packages/WallpaperCropper/res/values-eo/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-eo/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-es-rCO/strings.xml b/packages/WallpaperCropper/res/values-es-rCO/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-es-rCO/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-es-rMX/strings.xml b/packages/WallpaperCropper/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-es-rMX/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-frp-rIT/strings.xml b/packages/WallpaperCropper/res/values-frp-rIT/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-frp-rIT/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-fy-rNL/strings.xml b/packages/WallpaperCropper/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-fy-rNL/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-ga-rIE/strings.xml b/packages/WallpaperCropper/res/values-ga-rIE/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-ga-rIE/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-gd-rGB/strings.xml b/packages/WallpaperCropper/res/values-gd-rGB/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-gd-rGB/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-ku/strings.xml b/packages/WallpaperCropper/res/values-ku/strings.xml new file mode 100644 index 0000000000000..973d055224e0d --- /dev/null +++ b/packages/WallpaperCropper/res/values-ku/strings.xml @@ -0,0 +1,26 @@ + + + + + بڕینی وێنەی پشتەوە + + دانانی وێنەی پشتەوە + + نەتوانرا وێنەی پشتەوە دابنرێت + diff --git a/packages/WallpaperCropper/res/values-lb/strings.xml b/packages/WallpaperCropper/res/values-lb/strings.xml new file mode 100644 index 0000000000000..b4c6af6444e45 --- /dev/null +++ b/packages/WallpaperCropper/res/values-lb/strings.xml @@ -0,0 +1,26 @@ + + + + + Hannergrondbild schneiden + + Hannergrondbild setzen + + D\'Bild konnt net als Hannergrondbild geluede ginn + diff --git a/packages/WallpaperCropper/res/values-oc-rFR/strings.xml b/packages/WallpaperCropper/res/values-oc-rFR/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-oc-rFR/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-or-rIN/strings.xml b/packages/WallpaperCropper/res/values-or-rIN/strings.xml new file mode 100644 index 0000000000000..0e609fe0671ef --- /dev/null +++ b/packages/WallpaperCropper/res/values-or-rIN/strings.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/packages/WallpaperCropper/res/values-ug/strings.xml b/packages/WallpaperCropper/res/values-ug/strings.xml new file mode 100644 index 0000000000000..e28e735ed134f --- /dev/null +++ b/packages/WallpaperCropper/res/values-ug/strings.xml @@ -0,0 +1,26 @@ + + + + + تام قەغەز كەس + + تام قەغەز تەڭشىكى + + سۈرەتنى تام قەغەز سۈپىتىدە يۈكلىيەلمىدى + diff --git a/packages/WallpaperCropper/res/values/cm_colors.xml b/packages/WallpaperCropper/res/values/cm_colors.xml new file mode 100644 index 0000000000000..bfb299404cb40 --- /dev/null +++ b/packages/WallpaperCropper/res/values/cm_colors.xml @@ -0,0 +1,20 @@ + + + + + @android:color/white + diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java index 1b4182dbb3239..4e4c249f36098 100644 --- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java @@ -31,7 +31,7 @@ /** * Utility methods for performing accessibility display adjustments. */ -public class DisplayAdjustmentUtils { +class DisplayAdjustmentUtils { private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName(); /** Matrix and offset used for converting color to gray-scale. */ @@ -77,11 +77,6 @@ public static boolean hasAdjustments(Context context, int userId) { return true; } - if (CMSettings.Secure.getStringForUser(cr, - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, userId) != null) { - return true; - } - return false; } @@ -97,23 +92,6 @@ public static void applyAdjustments(Context context, int userId) { colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY); } - String adj = CMSettings.Secure.getStringForUser(cr, - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, userId); - if (adj != null) { - String[] tmp = adj.split(" "); - if (tmp.length == 16) { - float[] adjMatrix = new float[16]; - try { - for (int i = 0; i < 16; i++) { - adjMatrix[i] = Float.parseFloat(tmp[i]); - } - colorMatrix = multiply(colorMatrix, adjMatrix); - } catch (NumberFormatException e) { - Slog.e(LOG_TAG, e.getMessage(), e); - } - } - } - if (Settings.Secure.getIntForUser(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { final int daltonizerMode = Settings.Secure.getIntForUser(cr, diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 1629a3773efe9..d16c78abaf3b8 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -80,7 +80,9 @@ import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; +import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.AtomicFile; import android.util.EventLog; import android.util.Log; @@ -93,6 +95,7 @@ import com.android.internal.backup.IObbBackupService; import com.android.server.AppWidgetBackupBridge; import com.android.server.EventLogTags; +import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.backup.PackageManagerBackupAgent.Metadata; @@ -300,6 +303,7 @@ public String toString() { volatile boolean mClearingData; // Transport bookkeeping + final ArraySet mTransportWhitelist; final Intent mTransportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST); final ArrayMap mTransportNames = new ArrayMap(); // component name -> registration name @@ -1084,11 +1088,15 @@ public BackupManagerService(Context context, Trampoline parent) { // Set up our transport options and initialize the default transport // TODO: Don't create transports that we don't need to? - mCurrentTransport = Settings.Secure.getString(context.getContentResolver(), + SystemConfig systemConfig = SystemConfig.getInstance(); + mTransportWhitelist = systemConfig.getBackupTransportWhitelist(); + + String transport = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT); - if ("".equals(mCurrentTransport)) { - mCurrentTransport = null; + if (TextUtils.isEmpty(transport)) { + transport = null; } + mCurrentTransport = transport; if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport); // Find all transport hosts and bind to their services @@ -1099,11 +1107,11 @@ public BackupManagerService(Context context, Trampoline parent) { } if (hosts != null) { for (int i = 0; i < hosts.size(); i++) { - final ServiceInfo transport = hosts.get(i).serviceInfo; + final ServiceInfo transportService = hosts.get(i).serviceInfo; if (MORE_DEBUG) { - Slog.v(TAG, " " + transport.packageName + "/" + transport.name); + Slog.v(TAG, " " + transportService.packageName + "/" + transportService.name); } - tryBindTransport(transport); + tryBindTransport(transportService); } } @@ -1983,7 +1991,12 @@ boolean tryBindTransport(ServiceInfo info) { // Actually bind; presumes that we have already validated the transport service boolean bindTransport(ServiceInfo transport) { ComponentName svcName = new ComponentName(transport.packageName, transport.name); - if (MORE_DEBUG) { + if (!mTransportWhitelist.contains(svcName)) { + Slog.w(TAG, "Proposed transport " + svcName + " not whitelisted; ignoring"); + return false; + } + + if (DEBUG) { Slog.i(TAG, "Binding to transport host " + svcName); } Intent intent = new Intent(mTransportServiceIntent); @@ -2222,7 +2235,8 @@ IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) { synchronized(mAgentConnectLock) { mConnecting = true; mConnectedAgent = null; - if (mActivityManager.bindBackupAgent(app, mode)) { + if (mActivityManager.bindBackupAgent(app.packageName, mode, + UserHandle.USER_OWNER)) { Slog.d(TAG, "awaiting agent for " + app); // success; wait for the agent to arrive @@ -9654,6 +9668,12 @@ private void dumpInternal(PrintWriter pw) { + " (now = " + System.currentTimeMillis() + ')'); pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled()); + pw.println("Transport whitelist:"); + for (ComponentName transport : mTransportWhitelist) { + pw.print(" "); + pw.println(transport.flattenToShortString()); + } + pw.println("Available transports:"); final String[] transports = listAllTransports(); if (transports != null) { diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 14334900a1770..5875ca95b3c14 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -74,6 +74,8 @@ import java.util.Random; import java.util.TimeZone; import java.util.TreeSet; +import java.util.Timer; +import java.util.TimerTask; import static android.app.AlarmManager.RTC_WAKEUP; import static android.app.AlarmManager.RTC; @@ -127,6 +129,7 @@ class AlarmManagerService extends SystemService { private final ArrayList mTriggeredUids = new ArrayList(); private final ArrayList mBlockedUids = new ArrayList(); + private static final int BLOCKED_UID_CHECK_INTERVAL = 1000; // 1 sec. long mNativeData; private long mNextWakeup; @@ -1250,16 +1253,9 @@ public void updateBlockedUids(int uid, boolean isBlocked) { synchronized(mLock) { if(isBlocked) { mBlockedUids.add(new Integer(uid)); - if (checkReleaseWakeLock()) { - /* all the uids for which the alarms are triggered - * are either blocked or have called onSendFinished. - */ - if (mWakeLock.isHeld()) { - mWakeLock.release(); - if (localLOGV) - Slog.v(TAG, "AM WakeLock Released Internally in updateBlockedUids"); - } - } + Timer checkBlockedUidTimer = new Timer(); + checkBlockedUidTimer.schedule( new CheckBlockedUidTimerTask(uid), + BLOCKED_UID_CHECK_INTERVAL); } else { mBlockedUids.clear(); } @@ -1267,6 +1263,24 @@ public void updateBlockedUids(int uid, boolean isBlocked) { } }; + class CheckBlockedUidTimerTask extends TimerTask { + private int mUid; + CheckBlockedUidTimerTask(int uid) { + mUid = uid; + } + @Override + public void run(){ + if (mBlockedUids.contains(mUid) && mTriggeredUids.contains(mUid)) { + if (mWakeLock.isHeld()) { + mWakeLock.release(); + if (localLOGV) + Slog.v(TAG, "AM WakeLock Released Internally!!"); + return; + } + } + return; + } + } void dumpImpl(PrintWriter pw) { synchronized (mLock) { pw.println("Current Alarm Manager state:"); @@ -1745,20 +1759,6 @@ void rescheduleKernelAlarmsLocked() { } } - boolean checkReleaseWakeLock() { - if (mTriggeredUids.size() == 0 || mBlockedUids.size() == 0) - return false; - - int uid; - for (int i = 0; i < mTriggeredUids.size(); i++) { - uid = mTriggeredUids.get(i); - if (!mBlockedUids.contains(uid)) { - return false; - } - } - return true; - } - private void removeLocked(PendingIntent operation) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { @@ -2277,12 +2277,6 @@ void deliverAlarmsLocked(ArrayList triggerList, long nowELAPSED) { mInFlight.add(inflight); mBroadcastRefCount++; mTriggeredUids.add(new Integer(alarm.uid)); - if (checkReleaseWakeLock()) { - if (mWakeLock.isHeld()) { - mWakeLock.release(); - if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally deliverAlarms"); - } - } if (allowWhileIdle) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm. @@ -2839,13 +2833,6 @@ public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, mBroadcastRefCount--; mTriggeredUids.remove(new Integer(uid)); - if (checkReleaseWakeLock()) { - if (mWakeLock.isHeld()) { - mWakeLock.release(); - if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally onSendFinish"); - } - } - if (mBroadcastRefCount == 0) { if (mWakeLock.isHeld()) { mWakeLock.release(); diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java index 6a673164b1b49..a0b5c154c13f6 100644 --- a/services/core/java/com/android/server/AnyMotionDetector.java +++ b/services/core/java/com/android/server/AnyMotionDetector.java @@ -58,9 +58,6 @@ interface DeviceIdleCallback { /** Current measurement state. */ private int mState; - /** Threshold angle in degrees beyond which the device is considered moving. */ - private final float THRESHOLD_ANGLE = 2f; - /** Threshold energy above which the device is considered moving. */ private final float THRESHOLD_ENERGY = 5f; @@ -88,6 +85,9 @@ interface DeviceIdleCallback { private SensorManager mSensorManager; private PowerManager.WakeLock mWakeLock; + /** Threshold angle in degrees beyond which the device is considered moving. */ + private final float mThresholdAngle; + /** The minimum number of samples required to detect AnyMotion. */ private int mNumSufficientSamples; @@ -106,7 +106,7 @@ interface DeviceIdleCallback { private DeviceIdleCallback mCallback = null; public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm, - DeviceIdleCallback callback) { + DeviceIdleCallback callback, float thresholdAngle) { if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated."); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock.setReferenceCounted(false); @@ -116,6 +116,7 @@ public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm, mMeasurementInProgress = false; mState = STATE_INACTIVE; mCallback = callback; + mThresholdAngle = thresholdAngle; mRunningStats = new RunningSignalStats(); mNumSufficientSamples = (int) Math.ceil( ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS)); @@ -224,8 +225,9 @@ public int getStationaryStatus() { Vector3 previousGravityVectorNormalized = mPreviousGravityVector.normalized(); Vector3 currentGravityVectorNormalized = mCurrentGravityVector.normalized(); float angle = previousGravityVectorNormalized.angleBetween(currentGravityVectorNormalized); - if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle); - if ((angle < THRESHOLD_ANGLE) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) { + if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle + + " energy = " + mRunningStats.getEnergy()); + if ((angle < mThresholdAngle) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) { return RESULT_STATIONARY; } else if (Float.isNaN(angle)) { /** diff --git a/services/core/java/com/android/server/AppOpsPolicy.java b/services/core/java/com/android/server/AppOpsPolicy.java index 75bca05591f50..d51983f744f96 100644 --- a/services/core/java/com/android/server/AppOpsPolicy.java +++ b/services/core/java/com/android/server/AppOpsPolicy.java @@ -60,6 +60,11 @@ public class AppOpsPolicy { public static final int CONTROL_UNKNOWN = 2; + // Rate limiting thresholds for ask operations + public static final int RATE_LIMIT_OP_COUNT = 3; + public static final int RATE_LIMIT_OPS_TOTAL_PKG_COUNT = 4; + public static final int RATE_LIMIT_OP_DELAY_CEILING = 10; + public static int stringToControl(String show) { if ("true".equalsIgnoreCase(show)) { return CONTROL_SHOW; @@ -438,4 +443,4 @@ public int getDefualtMode(int code, String packageName) { Slog.d(TAG, "Returning mode=" + mode); return mode; } -} \ No newline at end of file +} diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index 83a0a99016799..b205d24fb9042 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -39,8 +39,10 @@ import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.Dialog; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -51,6 +53,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -96,6 +99,7 @@ public class AppOpsService extends IAppOpsService.Stub { final Looper mLooper; final boolean mStrictEnable; AppOpsPolicy mPolicy; + private PowerManager mPowerManager; private static final int[] PRIVACY_GUARD_OP_STATES = new int[] { AppOpsManager.OP_COARSE_LOCATION, @@ -184,6 +188,7 @@ public final static class Op { final ArrayList clientTokens; public int allowedCount; public int ignoredCount; + public int delayedCount; public Op(int _uid, String _packageName, int _op, int _mode) { uid = _uid; @@ -317,10 +322,17 @@ public void systemReady() { } catch (RemoteException ignored) { } if (curUid != ops.uidState.uid) { - Slog.i(TAG, "Pruning old package " + ops.packageName - + "/" + ops.uidState + ": new uid=" + curUid); - it.remove(); - changed = true; + // Do not prune apps that are not currently present in the device + // (like SDcard ones). While booting, SDcards are not available but + // must not be purged from AppOps, because they are still present + // in the Android app database. + String pkgName = mContext.getPackageManager().getNameForUid(ops.uidState.uid); + if (curUid != -1 || pkgName == null || !pkgName.equals(ops.packageName)) { + Slog.i(TAG, "Pruning old package " + ops.packageName + + "/" + ops.uidState + ": new uid=" + curUid); + it.remove(); + changed = true; + } } } @@ -360,8 +372,45 @@ public boolean hasExternalStorage(int uid, String packageName) { || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; } }); + + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(mIntentReceiver, filter); } + private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(Intent.ACTION_SCREEN_OFF)) { + synchronized (this) { + for (int i = mUidStates.size() - 1; i >= 0; i--) { + UidState uidState = mUidStates.valueAt(i); + + ArrayMap packages = uidState.pkgOps; + if (packages == null) { + continue; + } + + Iterator> it = packages.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry ent = it.next(); + Ops pkgOps = ent.getValue(); + for (int j = pkgOps.size() - 1; j >= 0; j--) { + Op curOp = pkgOps.valueAt(j); + if (DEBUG) + Log.d(TAG, "Ignoring " + curOp.packageName + " request " + + curOp.op); + curOp.dialogReqQueue.ignore(); + } + } + } + } + } + } + }; + public void packageRemoved(int uid, String packageName) { synchronized (this) { UidState uidState = mUidStates.get(uid); @@ -1058,8 +1107,50 @@ private int noteOperationUnchecked(int code, int uid, String packageName, + packageName + ")"); return switchOp.mode; } - op.noteOpCount++; - req = askOperationLocked(code, uid, packageName, switchOp); + + if (DEBUG) { + Log.d(TAG, "Package " + op.packageName + " has " + op.noteOpCount + + " requests and " + op.startOpCount + " start requests with " + + op.ignoredCount + " ignored at " + op.time + + " with a duration of " + + op.duration + " while being delayed " + op.delayedCount + + " times"); + Log.d(TAG, "Total pkops for " + ops.packageName + " " + + ops.uidState.pkgOps.size()); + } + + // First drop all request events if the device is not interactive, next + // check what the global pkg ops count for the package, + // then check op scoped count. High frequency request ops will be delayed until + // their delay count ceiling is met. This is to mitigate the overloading the + // main activity manager service handler and having watchdog kill our service. + // Google play services likes to share its uid with numerous packages to avoid + // having to grant permissions from the users perspective and thus is the worst + // example of overloading this queue -- so, to not encourage bad behavior, + // we move them to the back of the line. NOTE: these values are magic, and may need + // tuning. Ideally we'd want a ringbuffer or token bucket here to do proper rate + // limiting. + final boolean isInteractive = mPowerManager.isInteractive(); + if (isInteractive && + (ops.uidState.pkgOps.size() < AppOpsPolicy.RATE_LIMIT_OPS_TOTAL_PKG_COUNT + && op.noteOpCount < AppOpsPolicy.RATE_LIMIT_OP_COUNT + || op.delayedCount > AppOpsPolicy.RATE_LIMIT_OP_DELAY_CEILING)) { + + // Reset delayed count, most ops will never need this + if (op.delayedCount > 0) { + if (DEBUG) Log.d(TAG, "Resetting delayed count for " + op.packageName); + op.delayedCount = 0; + } + + op.noteOpCount++; + req = askOperationLocked(code, uid, packageName, switchOp); + } else { + if (isInteractive) { + op.delayedCount++; + } + op.ignoredCount++; + return AppOpsManager.MODE_IGNORED; + } } } diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 238e9c959fd26..97ad02c755d4c 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +26,10 @@ import com.android.server.lights.LightsManager; import android.app.ActivityManagerNative; +import android.app.IBatteryService; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -49,16 +54,10 @@ import android.provider.Settings; import android.util.EventLog; import android.util.Slog; -import cyanogenmod.providers.CMSettings; import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; @@ -86,6 +85,21 @@ * a degree Centigrade

*

"technology" - String, the type of battery installed, e.g. "Li-ion"

* + *

If a dock battery is present, then this Intent data will be present too related + * to dock battery information:

+ *

"dock_scale" - int, the maximum value for the charge level

+ *

"dock_level" - int, charge level, from 0 through "scale" inclusive

+ *

"dock_status" - String, the current charging status.
+ *

"dock_health" - String, the current battery health.
+ *

"dock_present" - boolean, true if the battery is present
+ *

"dock_icon-small" - int, suggested small icon to use for this state

+ *

"dock_plugged" - int, 0 if the device is not plugged in; 1 if plugged + * into an AC power adapter; 2 if plugged in via USB.

+ *

"dock_voltage" - int, current battery voltage in millivolts

+ *

"dock_temperature" - int, current battery temperature in tenths of + * a degree Centigrade

+ *

"dock_technology" - String, the type of battery installed, e.g. "Li-ion"

+ * *

* The battery service may be called by the power manager while holding its locks so * we take care to post all outcalls into the activity manager to a handler. @@ -134,11 +148,20 @@ public final class BatteryService extends SystemService { private boolean mLastBatteryLevelCritical; private int mLastMaxChargingCurrent; + private boolean mDockBatterySupported; + private int mLastDockBatteryStatus; + private int mLastDockBatteryHealth; + private boolean mLastDockBatteryPresent; + private int mLastDockBatteryLevel; + private int mLastDockBatteryVoltage; + private int mLastDockBatteryTemperature; + private int mInvalidCharger; private int mLastInvalidCharger; private boolean mAdjustableNotificationLedBrightness; private int mNotificationLedBrightnessLevel = LIGHT_BRIGHTNESS_MAXIMUM; + private boolean mUseSegmentedBatteryLed = false; private boolean mMultipleNotificationLeds; private boolean mMultipleLedsEnabled = false; @@ -149,8 +172,11 @@ public final class BatteryService extends SystemService { private int mPlugType; private int mLastPlugType = -1; // Extra state so we can detect first run + private int mDockPlugType; + private int mLastDockPlugType = -1; // Extra state so we can detect first run private boolean mBatteryLevelLow; + private boolean mDockBatteryLevelLow; private long mDischargeStartTime; private int mDischargeStartLevel; @@ -168,6 +194,9 @@ public final class BatteryService extends SystemService { private boolean mSentLowBatteryBroadcast = false; + private boolean mShowBatteryFullyChargedNotification; + private boolean mIsShowingBatteryFullyChargedNotification; + public BatteryService(Context context) { super(context); @@ -176,6 +205,10 @@ public BatteryService(Context context) { mLed = new Led(context, getLocalService(LightsManager.class)); mBatteryStats = BatteryStatsService.getService(); + // By default dock battery are not supported. The first events will refresh + // this status from the battery property bag + mDockBatterySupported = false; + mCriticalBatteryLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); mLowBatteryWarningLevel = mContext.getResources().getInteger( @@ -184,6 +217,8 @@ public BatteryService(Context context) { com.android.internal.R.integer.config_lowBatteryCloseWarningBump); mShutdownBatteryTemperature = mContext.getResources().getInteger( com.android.internal.R.integer.config_shutdownBatteryTemperature); + mShowBatteryFullyChargedNotification = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_showBatteryFullyChargedNotification); // watch for invalid charger messages if the invalid_charger switch exists if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) { @@ -203,7 +238,7 @@ public void onStart() { // Should never happen. } - publishBinderService("battery", new BinderService()); + publishBinderService(Context.BATTERY_SERVICE, new BinderService()); publishLocalService(BatteryManagerInternal.class, new LocalService()); } @@ -338,21 +373,31 @@ private void processValuesLocked(boolean force) { boolean logOutlier = false; long dischargeDuration = 0; + mDockBatterySupported = mBatteryProps.dockBatterySupported; + mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel); + mPlugType = BATTERY_PLUGGED_NONE; if (mBatteryProps.chargerAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mBatteryProps.chargerUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else if (mBatteryProps.chargerWirelessOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; - } else { - mPlugType = BATTERY_PLUGGED_NONE; + } + mDockPlugType = BATTERY_PLUGGED_NONE; + if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerAcOnline) { + mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_AC; + } else if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerUsbOnline) { + mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_USB; } if (DEBUG) { - Slog.d(TAG, "Processing new values: " - + "chargerAcOnline=" + mBatteryProps.chargerAcOnline - + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline + String msg = "Processing new values: " + + "chargerAcOnline=" + mBatteryProps.chargerAcOnline; + if (mDockBatterySupported) { + msg += ", chargerDockAcOnline=" + mBatteryProps.chargerDockAcOnline; + } + msg += ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline + ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent + ", batteryStatus=" + mBatteryProps.batteryStatus @@ -362,8 +407,22 @@ private void processValuesLocked(boolean force) { + ", batteryTechnology=" + mBatteryProps.batteryTechnology + ", batteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryTemperature=" + mBatteryProps.batteryTemperature - + ", mBatteryLevelCritical=" + mBatteryLevelCritical - + ", mPlugType=" + mPlugType); + + ", mBatteryLevelCritical=" + mBatteryLevelCritical; + if (mDockBatterySupported) { + msg += ", dockBatteryStatus=" + mBatteryProps.dockBatteryStatus + + ", dockBatteryHealth=" + mBatteryProps.dockBatteryHealth + + ", dockBatteryPresent=" + mBatteryProps.dockBatteryPresent + + ", dockBatteryLevel=" + mBatteryProps.dockBatteryLevel + + ", dockBatteryTechnology=" + mBatteryProps.dockBatteryTechnology + + ", dockBatteryVoltage=" + mBatteryProps.dockBatteryVoltage + + ", dockBatteryTemperature=" + mBatteryProps.dockBatteryTemperature; + } + msg += ", mPlugType=" + mPlugType; + if (mDockBatterySupported) { + msg += ", mDockPlugType=" + mDockPlugType; + } + + Slog.d(TAG, msg); } // Let the battery stats keep track of the current level. @@ -374,19 +433,40 @@ private void processValuesLocked(boolean force) { } catch (RemoteException e) { // Should never happen. } + if (mDockBatterySupported) { + try { + mBatteryStats.setDockBatteryState(mBatteryProps.dockBatteryStatus, + mBatteryProps.dockBatteryHealth, mDockPlugType, + mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryTemperature, + mBatteryProps.dockBatteryVoltage); + } catch (RemoteException e) { + // Should never happen. + } + } shutdownIfNoPowerLocked(); shutdownIfOverTempLocked(); - if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus || + final boolean batteryChanged = mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mBatteryProps.batteryLevel != mLastBatteryLevel || mPlugType != mLastPlugType || mBatteryProps.batteryVoltage != mLastBatteryVoltage || mBatteryProps.batteryTemperature != mLastBatteryTemperature || - mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent || - mInvalidCharger != mLastInvalidCharger)) { + mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent; + + final boolean dockBatteryChanged = mDockBatterySupported && + (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus || + mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth || + mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent || + mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel || + mDockPlugType != mLastDockPlugType || + mBatteryProps.dockBatteryVoltage != mLastDockBatteryVoltage || + mBatteryProps.dockBatteryTemperature != mLastDockBatteryTemperature); + + if (force || batteryChanged || dockBatteryChanged || + mInvalidCharger != mLastInvalidCharger) { if (mPlugType != mLastPlugType) { if (mLastPlugType == BATTERY_PLUGGED_NONE) { @@ -416,12 +496,30 @@ private void processValuesLocked(boolean force) { mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0, mPlugType, mBatteryProps.batteryTechnology); } + if (mDockBatterySupported && + (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus || + mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth || + mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent || + mDockPlugType != mLastDockPlugType)) { + EventLog.writeEvent(EventLogTags.DOCK_BATTERY_STATUS, + mBatteryProps.dockBatteryStatus, mBatteryProps.dockBatteryHealth, + mBatteryProps.dockBatteryPresent ? 1 : 0, + mDockPlugType, mBatteryProps.dockBatteryTechnology); + } if (mBatteryProps.batteryLevel != mLastBatteryLevel) { // Don't do this just from voltage or temperature changes, that is // too noisy. EventLog.writeEvent(EventLogTags.BATTERY_LEVEL, mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature); } + if (mDockBatterySupported && + (mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel)) { + // Don't do this just from voltage or temperature changes, that is + // too noisy. + EventLog.writeEvent(EventLogTags.DOCK_BATTERY_LEVEL, + mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryVoltage, + mBatteryProps.dockBatteryTemperature); + } if (mBatteryLevelCritical && !mLastBatteryLevelCritical && mPlugType == BATTERY_PLUGGED_NONE) { // We want to make sure we log discharge cycle outliers @@ -448,13 +546,34 @@ private void processValuesLocked(boolean force) { mBatteryLevelLow = false; } } + if (mDockBatterySupported) { + if (!mDockBatteryLevelLow) { + // Should we now switch in to low battery mode? + if (mDockPlugType == BATTERY_PLUGGED_NONE + && mBatteryProps.dockBatteryLevel <= mLowBatteryWarningLevel) { + mDockBatteryLevelLow = true; + } + } else { + // Should we now switch out of low battery mode? + if (mDockPlugType != BATTERY_PLUGGED_NONE) { + mDockBatteryLevelLow = false; + } else if (mBatteryProps.dockBatteryLevel >= mLowBatteryCloseWarningLevel) { + mDockBatteryLevelLow = false; + } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) { + // If being forced, the previous state doesn't matter, we will just + // absolutely check to see if we are now above the warning level. + mDockBatteryLevelLow = false; + } + } + } sendIntentLocked(); // Separate broadcast is sent for power connected / not connected // since the standard intent will not wake any applications and some // applications may want to have smart behavior based on this. - if (mPlugType != 0 && mLastPlugType == 0) { + if (mPlugType != 0 && mLastPlugType == 0 || + (mLastPlugType == 0 && mDockPlugType != 0 && mLastDockPlugType == 0)) { mHandler.post(new Runnable() { @Override public void run() { @@ -464,7 +583,8 @@ public void run() { } }); } - else if (mPlugType == 0 && mLastPlugType != 0) { + else if (mPlugType == 0 && mLastPlugType != 0 || + (mLastPlugType != 0 && mDockPlugType == 0 && mLastDockPlugType != 0)) { mHandler.post(new Runnable() { @Override public void run() { @@ -500,6 +620,12 @@ public void run() { // Update the battery LED mLed.updateLightsLocked(); + if (shouldShowBatteryFullyChargedNotificationLocked()) { + showBatteryFullyChargedNotificationLocked(); + } else if (shouldClearBatteryFullyChargedNotificationLocked()) { + clearBatteryFullyChargedNotificationLocked(); + } + // This needs to be done after sendIntent() so that we get the lastest battery stats. if (logOutlier && dischargeDuration != 0) { logOutlierLocked(dischargeDuration); @@ -514,6 +640,14 @@ public void run() { mLastBatteryTemperature = mBatteryProps.batteryTemperature; mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent; mLastBatteryLevelCritical = mBatteryLevelCritical; + mLastDockBatteryStatus = mBatteryProps.dockBatteryStatus; + mLastDockBatteryHealth = mBatteryProps.dockBatteryHealth; + mLastDockBatteryPresent = mBatteryProps.dockBatteryPresent; + mLastDockBatteryLevel = mBatteryProps.dockBatteryLevel; + mLastDockPlugType = mDockPlugType; + mLastDockBatteryVoltage = mBatteryProps.dockBatteryVoltage; + mLastDockBatteryTemperature = mBatteryProps.dockBatteryTemperature; + mLastInvalidCharger = mInvalidCharger; } } @@ -525,6 +659,7 @@ private void sendIntentLocked() { | Intent.FLAG_RECEIVER_REPLACE_PENDING); int icon = getIconLocked(mBatteryProps.batteryLevel); + int dockIcon = 0; intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus); intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth); @@ -539,19 +674,62 @@ private void sendIntentLocked() { intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger); intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent); + if (mDockBatterySupported) { + dockIcon = getDockIconLocked(mBatteryProps.dockBatteryLevel); + + intent.putExtra(BatteryManager.EXTRA_DOCK_STATUS, mBatteryProps.dockBatteryStatus); + intent.putExtra(BatteryManager.EXTRA_DOCK_HEALTH, mBatteryProps.dockBatteryHealth); + intent.putExtra(BatteryManager.EXTRA_DOCK_PRESENT, mBatteryProps.dockBatteryPresent); + intent.putExtra(BatteryManager.EXTRA_DOCK_LEVEL, mBatteryProps.dockBatteryLevel); + intent.putExtra(BatteryManager.EXTRA_DOCK_SCALE, BATTERY_SCALE); + intent.putExtra(BatteryManager.EXTRA_DOCK_ICON_SMALL, dockIcon); + intent.putExtra(BatteryManager.EXTRA_DOCK_PLUGGED, mDockPlugType); + intent.putExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, mBatteryProps.dockBatteryVoltage); + intent.putExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE, + mBatteryProps.dockBatteryTemperature); + intent.putExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY, + mBatteryProps.dockBatteryTechnology); + + // EEPAD legacy data + intent.putExtra("usb_wakeup", mBatteryProps.chargerUsbOnline); + intent.putExtra("ac_online", mBatteryProps.chargerAcOnline); + intent.putExtra("dock_ac_online", mBatteryProps.chargerDockAcOnline); + } + + if (DEBUG) { - Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel + - ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus + + String msg = "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel + + ", scale:" + BATTERY_SCALE + + ", status:" + mBatteryProps.batteryStatus + ", health:" + mBatteryProps.batteryHealth + ", present:" + mBatteryProps.batteryPresent + ", voltage: " + mBatteryProps.batteryVoltage + ", temperature: " + mBatteryProps.batteryTemperature + ", technology: " + mBatteryProps.batteryTechnology + - ", AC powered:" + mBatteryProps.chargerAcOnline + - ", USB powered:" + mBatteryProps.chargerUsbOnline + - ", Wireless powered:" + mBatteryProps.chargerWirelessOnline + - ", icon:" + icon + ", invalid charger:" + mInvalidCharger + - ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent); + ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent; + + if (mDockBatterySupported) { + msg += ", dock_level:" + mBatteryProps.dockBatteryLevel + + ", dock_status:" + mBatteryProps.dockBatteryStatus + + ", dock_health:" + mBatteryProps.dockBatteryHealth + + ", dock_present:" + mBatteryProps.dockBatteryPresent + + ", dock_voltage: " + mBatteryProps.dockBatteryVoltage + + ", dock_temperature: " + mBatteryProps.dockBatteryTemperature + + ", dock_technology: " + mBatteryProps.dockBatteryTechnology; + } + msg += ", AC powered:" + mBatteryProps.chargerAcOnline; + if (mDockBatterySupported) { + msg += ", Dock AC powered:" + mBatteryProps.chargerDockAcOnline; + } + msg += ", USB powered:" + mBatteryProps.chargerUsbOnline + + ", Wireless powered:" + mBatteryProps.chargerWirelessOnline; + msg += ", icon:" + icon; + if (mDockBatterySupported) { + msg += ", dock_icon:" + dockIcon; + } + msg += ", invalid charger:" + mInvalidCharger; + + Slog.d(TAG, msg); } mHandler.post(new Runnable() { @@ -646,6 +824,22 @@ private int getIconLocked(int level) { } } + private int getDockIconLocked(int level) { + if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { + return com.android.internal.R.drawable.stat_sys_battery_charge; + } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) { + return com.android.internal.R.drawable.stat_sys_battery; + } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING + || mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) { + if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY) + && mBatteryProps.dockBatteryLevel >= 100) { + return com.android.internal.R.drawable.stat_sys_battery_charge; + } + return com.android.internal.R.drawable.stat_sys_battery; + } + return com.android.internal.R.drawable.stat_sys_battery_unknown; + } + private void dumpInternal(PrintWriter pw, String[] args) { synchronized (mLock) { if (args == null || args.length == 0 || "-a".equals(args[0])) { @@ -654,6 +848,9 @@ private void dumpInternal(PrintWriter pw, String[] args) { pw.println(" (UPDATES STOPPED -- use 'reset' to restart)"); } pw.println(" AC powered: " + mBatteryProps.chargerAcOnline); + if (mDockBatterySupported) { + pw.println(" Dock AC powered: " + mBatteryProps.chargerDockAcOnline); + } pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline); pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline); pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent); @@ -665,7 +862,15 @@ private void dumpInternal(PrintWriter pw, String[] args) { pw.println(" voltage: " + mBatteryProps.batteryVoltage); pw.println(" temperature: " + mBatteryProps.batteryTemperature); pw.println(" technology: " + mBatteryProps.batteryTechnology); - + if (mDockBatterySupported) { + pw.println(" dock_status: " + mBatteryProps.dockBatteryStatus); + pw.println(" dock_health: " + mBatteryProps.dockBatteryHealth); + pw.println(" dock_present: " + mBatteryProps.dockBatteryPresent); + pw.println(" dock_level: " + mBatteryProps.dockBatteryLevel); + pw.println(" dock_voltage: " + mBatteryProps.dockBatteryVoltage); + pw.println(" dock_temperature: " + mBatteryProps.dockBatteryTemperature); + pw.println(" dock_technology: " + mBatteryProps.dockBatteryTechnology); + } } else if ("unplug".equals(args[0])) { if (!mUpdatesStopped) { mLastBatteryProps.set(mBatteryProps); @@ -691,6 +896,8 @@ private void dumpInternal(PrintWriter pw, String[] args) { boolean update = true; if ("ac".equals(key)) { mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0; + } else if (mDockBatterySupported && "dockac".equals(key)) { + mBatteryProps.chargerDockAcOnline = Integer.parseInt(value) != 0; } else if ("usb".equals(key)) { mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0; } else if ("wireless".equals(key)) { @@ -699,6 +906,10 @@ private void dumpInternal(PrintWriter pw, String[] args) { mBatteryProps.batteryStatus = Integer.parseInt(value); } else if ("level".equals(key)) { mBatteryProps.batteryLevel = Integer.parseInt(value); + } else if (mDockBatterySupported && "dockstatus".equals(key)) { + mBatteryProps.dockBatteryStatus = Integer.parseInt(value); + } else if (mDockBatterySupported && "docklevel".equals(key)) { + mBatteryProps.dockBatteryLevel = Integer.parseInt(value); } else if ("invalid".equals(key)) { mInvalidCharger = Integer.parseInt(value); } else { @@ -731,7 +942,12 @@ private void dumpInternal(PrintWriter pw, String[] args) { } } else { pw.println("Dump current battery state, or:"); - pw.println(" set [ac|usb|wireless|status|level|invalid] "); + if (mDockBatterySupported) { + pw.println(" set [ac|dockac|usb|wireless|status|level|dockstatus" + + "|docklevel|invalid] "); + } else { + pw.println(" set [ac|usb|wireless|status|level|invalid] "); + } pw.println(" unplug"); pw.println(" reset"); } @@ -754,6 +970,56 @@ private synchronized void updateLedPulse() { mLed.updateLightsLocked(); } + private boolean shouldShowBatteryFullyChargedNotificationLocked() { + return mShowBatteryFullyChargedNotification && mPlugType != 0 + && mBatteryProps.batteryLevel == BATTERY_SCALE + && !mIsShowingBatteryFullyChargedNotification; + } + + private void showBatteryFullyChargedNotificationLocked() { + NotificationManager nm = mContext.getSystemService(NotificationManager.class); + Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); + PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, + intent, 0, null, UserHandle.CURRENT); + + CharSequence title = mContext.getText( + com.android.internal.R.string.notify_battery_fully_charged_title); + CharSequence message = mContext.getText( + com.android.internal.R.string.notify_battery_fully_charged_text); + + Notification notification = new Notification.Builder(mContext) + .setSmallIcon(com.android.internal.R.drawable.stat_sys_battery_charge) + .setWhen(0) + .setOngoing(false) + .setAutoCancel(true) + .setTicker(title) + .setDefaults(0) // please be quiet + .setPriority(Notification.PRIORITY_DEFAULT) + .setColor(mContext.getColor( + com.android.internal.R.color.system_notification_accent_color)) + .setContentTitle(title) + .setContentText(message) + .setStyle(new Notification.BigTextStyle().bigText(message)) + .setContentIntent(pi) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .build(); + + nm.notifyAsUser(null, com.android.internal.R.string.notify_battery_fully_charged_title, + notification, UserHandle.ALL); + mIsShowingBatteryFullyChargedNotification = true; + } + + private boolean shouldClearBatteryFullyChargedNotificationLocked() { + return mIsShowingBatteryFullyChargedNotification && + (mPlugType == 0 || mBatteryProps.batteryLevel < BATTERY_SCALE); + } + + private void clearBatteryFullyChargedNotificationLocked() { + NotificationManager nm = mContext.getSystemService(NotificationManager.class); + nm.cancel(com.android.internal.R.string.notify_battery_fully_charged_title); + mIsShowingBatteryFullyChargedNotification = false; + } + private final class Led { private final Light mBatteryLight; @@ -761,52 +1027,29 @@ private final class Led { private final int mBatteryLedOff; public Led(Context context, LightsManager lights) { + NotificationManager nm = context.getSystemService(NotificationManager.class); mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY); // Does the Device support changing battery LED colors? - mMultiColorLed = context.getResources().getBoolean( - com.android.internal.R.bool.config_multiColorBatteryLed); + mMultiColorLed = nm.deviceLightsCan(NotificationManager.LIGHTS_RGB_BATTERY); // Is the notification LED brightness changeable ? - mAdjustableNotificationLedBrightness = context.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness); + mAdjustableNotificationLedBrightness = nm.deviceLightsCan( + NotificationManager.LIGHTS_ADJUSTABLE_NOTIFICATION_BRIGHTNESS); // Does the Device have multiple LEDs ? - mMultipleNotificationLeds = context.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds); + mMultipleNotificationLeds = nm.deviceLightsCan( + NotificationManager.LIGHTS_MULTIPLE_LED); mBatteryLedOn = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOn); mBatteryLedOff = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOff); - } - - private boolean isHvdcpPresent() { - File mChargerTypeFile = new File("/sys/class/power_supply/usb/type"); - FileReader fileReader; - BufferedReader br; - String type; - boolean ret; - try { - fileReader = new FileReader(mChargerTypeFile); - br = new BufferedReader(fileReader); - type = br.readLine(); - if (type.regionMatches(true, 0, "USB_HVDCP", 0, 9)) - ret = true; - else - ret = false; - br.close(); - fileReader.close(); - } catch (FileNotFoundException e) { - ret = false; - Slog.e(TAG, "Failure in reading charger type", e); - } catch (IOException e) { - ret = false; - Slog.e(TAG, "Failure in reading charger type", e); - } - - return ret; + // Does the Device have segmented battery LED support? In this case, we send the level + // in the alpha channel of the color and let the HAL sort it out. + mUseSegmentedBatteryLed = nm.deviceLightsCan( + NotificationManager.LIGHTS_SEGMENTED_BATTERY_LIGHTS); } /** @@ -821,6 +1064,9 @@ public void updateLightsLocked() { final int level = mBatteryProps.batteryLevel; final int status = mBatteryProps.batteryStatus; + mNotificationLedBrightnessLevel = mUseSegmentedBatteryLed ? level : + LIGHT_BRIGHTNESS_MAXIMUM; + if (!mLightEnabled) { // No lights if explicitly disabled mBatteryLight.turnOff(); @@ -846,14 +1092,8 @@ public void updateLightsLocked() { // Battery is full or charging and nearly full mBatteryLight.setColor(mBatteryFullARGB); } else { - if (isHvdcpPresent()) { - // Blinking orange if HVDCP charger - mBatteryLight.setFlashing(mBatteryMediumARGB, Light.LIGHT_FLASH_TIMED, - mBatteryLedOn, mBatteryLedOn); - } else { - // Battery is charging and halfway full - mBatteryLight.setColor(mBatteryMediumARGB); - } + // Battery is charging and halfway full + mBatteryLight.setColor(mBatteryMediumARGB); } } else { // No lights if not charging and not low @@ -874,7 +1114,12 @@ public void batteryPropertiesChanged(BatteryProperties props) { } } - private final class BinderService extends Binder { + private final class BinderService extends IBatteryService.Stub { + @Override + public boolean isDockBatterySupported() throws RemoteException { + return getLocalService(BatteryManagerInternal.class).isDockBatterySupported(); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -919,12 +1164,40 @@ public boolean getBatteryLevelLow() { } } + @Override + public int getDockPlugType() { + synchronized (mLock) { + return mDockPlugType; + } + } + + @Override + public int getDockBatteryLevel() { + synchronized (mLock) { + return mBatteryProps.dockBatteryLevel; + } + } + + @Override + public boolean getDockBatteryLevelLow() { + synchronized (mLock) { + return mDockBatteryLevelLow; + } + } + @Override public int getInvalidCharger() { synchronized (mLock) { return mInvalidCharger; } } + + @Override + public boolean isDockBatterySupported() { + synchronized (mLock) { + return mDockBatterySupported; + } + } } class SettingsObserver extends ContentObserver { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 6067bd20e2e06..dbdffef4a93a2 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -266,7 +266,8 @@ public void onReceive(Context context, Intent intent) { sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", UserHandle.USER_OWNER); } catch (PackageManager.NameNotFoundException e) { - Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e); + // Some platforms, such as wearables do not have a system ui. + Log.w(TAG, "Unable to resolve SystemUI's UID.", e); } mSystemUiUid = sysUiUid; } @@ -762,6 +763,7 @@ private void sendBluetoothServiceUpCallback() { } catch (RemoteException e) { Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); } + Log.d(TAG, "Broadcasted onBluetoothServiceUp() to " + mCallbacks.getBroadcastItem(i)); } } finally { mCallbacks.finishBroadcast(); @@ -783,6 +785,7 @@ private void sendBluetoothServiceDownCallback() { } catch (RemoteException e) { Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); } + Log.d(TAG, "Broadcasted onBluetoothServiceDown() to " + mCallbacks.getBroadcastItem(i)); } } finally { mCallbacks.finishBroadcast(); @@ -1144,8 +1147,13 @@ public void handleMessage(Message msg) { recoverBluetoothServiceFromError(); } if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && - (newState == BluetoothAdapter.STATE_BLE_ON) && - (mBluetooth != null) && mEnable) { + (newState == BluetoothAdapter.STATE_OFF) && + (mBluetooth != null) && mEnable) { + persistBluetoothSetting(BLUETOOTH_OFF); + } + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && + (newState == BluetoothAdapter.STATE_BLE_ON) && + (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(); } if (newState == BluetoothAdapter.STATE_ON || @@ -1645,7 +1653,11 @@ private void recoverBluetoothServiceFromError() { if (mBluetooth != null) { mBluetooth = null; //Unbind - mContext.unbindService(mConnection); + try { + mContext.unbindService(mConnection); + } catch (Exception e) { + Log.e(TAG, "Unable to unbind",e); + } } mBluetoothGatt = null; } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b053c3a1e9d77..1489fd8713a9d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -159,6 +159,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import java.util.Random; /** * @hide @@ -171,6 +172,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final boolean VDBG = false; private static final boolean LOGD_RULES = false; + private static final boolean LOGD_BLOCKED_NETWORKINFO = true; // TODO: create better separation between radio types and network types @@ -645,18 +647,23 @@ public ConnectivityService(Context context, INetworkManagementService netManager mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper()); // setup our unique device name - String hostname = CMSettings.Secure.getString(context.getContentResolver(), - CMSettings.Secure.DEVICE_HOSTNAME); - if (TextUtils.isEmpty(hostname) && - TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { + // either to (in order): current net.hostname + // DEVICE_HOSTNAME + // android-ANDROID_ID + // android-r-RANDOM_NUMBER + if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { + String hostname = CMSettings.Secure.getString(context.getContentResolver(), + CMSettings.Secure.DEVICE_HOSTNAME); String id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); - if (id != null && id.length() > 0) { + if (!TextUtils.isEmpty(hostname)) { + SystemProperties.set("net.hostname", hostname); + } else if (!TextUtils.isEmpty(id)) { String name = new String("android-").concat(id); SystemProperties.set("net.hostname", name); + } else { + SystemProperties.set("net.hostname", "android-r-" + new Random().nextInt()); } - } else { - SystemProperties.set("net.hostname", hostname); } // read our default dns server ip @@ -964,6 +971,21 @@ private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) { } } + private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) { + if (ni == null || !LOGD_BLOCKED_NETWORKINFO) return; + boolean removed = false; + boolean added = false; + synchronized (mBlockedAppUids) { + if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) { + added = true; + } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) { + removed = true; + } + } + if (added) log("Returning blocked NetworkInfo to uid=" + uid); + else if (removed) log("Returning unblocked NetworkInfo to uid=" + uid); + } + /** * Return a filtered {@link NetworkInfo}, potentially marked * {@link DetailedState#BLOCKED} based on @@ -974,10 +996,6 @@ private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, LinkProperties lp, // network is blocked; clone and override state info = new NetworkInfo(info); info.setDetailedState(DetailedState.BLOCKED, null, null); - if (VDBG) { - log("returning Blocked NetworkInfo for ifname=" + - lp.getInterfaceName() + ", uid=" + uid); - } } if (info != null && mLockdownTracker != null) { info = mLockdownTracker.augmentNetworkInfo(info); @@ -998,7 +1016,9 @@ public NetworkInfo getActiveNetworkInfo() { enforceAccessPermission(); final int uid = Binder.getCallingUid(); NetworkState state = getUnfilteredActiveNetworkState(uid); - return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid); + NetworkInfo ni = getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid); + maybeLogBlockedNetworkInfo(ni, uid); + return ni; } @Override @@ -3927,6 +3947,9 @@ private void handleUnregisterNetworkFactory(Messenger messenger) { private final HashMap mNetworkAgentInfos = new HashMap(); + @GuardedBy("mBlockedAppUids") + private final HashSet mBlockedAppUids = new HashSet(); + // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated. private final NetworkRequest mDefaultRequest; diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index abe8f5c81c8bc..71650c36e5a57 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -31,6 +31,8 @@ import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorManager; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.hardware.display.DisplayManager; @@ -111,7 +113,7 @@ public class DeviceIdleController extends SystemService private INetworkPolicyManager mNetworkPolicyManager; private DisplayManager mDisplayManager; private SensorManager mSensorManager; - private Sensor mSigMotionSensor; + private Sensor mMotionSensor; private LocationManager mLocationManager; private LocationRequest mLocationRequest; private PendingIntent mSensingAlarmIntent; @@ -123,12 +125,12 @@ public class DeviceIdleController extends SystemService private boolean mForceIdle; private boolean mScreenOn; private boolean mCharging; - private boolean mSigMotionActive; private boolean mSensing; private boolean mNotMoving; private boolean mLocating; private boolean mLocated; - private boolean mHaveGps; + private boolean mHasGps; + private boolean mHasNetworkLocation; private Location mLastGenericLocation; private Location mLastGpsLocation; @@ -275,13 +277,57 @@ private static String stateToString(int state) { } }; - private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { - @Override public void onTrigger(TriggerEvent event) { + private final class MotionListener extends TriggerEventListener + implements SensorEventListener { + + boolean active = false; + + @Override + public void onTrigger(TriggerEvent event) { synchronized (DeviceIdleController.this) { - significantMotionLocked(); + active = false; + motionLocked(); } } - }; + + @Override + public void onSensorChanged(SensorEvent event) { + synchronized (DeviceIdleController.this) { + mSensorManager.unregisterListener(this, mMotionSensor); + active = false; + motionLocked(); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) {} + + public boolean registerLocked() { + boolean success = false; + if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { + success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor); + } else { + success = mSensorManager.registerListener( + mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL); + } + if (success) { + active = true; + } else { + Slog.e(TAG, "Unable to register for " + mMotionSensor); + } + return success; + } + + public void unregisterLocked() { + if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { + mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor); + } else { + mSensorManager.unregisterListener(mMotionListener); + } + active = false; + } + } + private final MotionListener mMotionListener = new MotionListener(); private final LocationListener mGenericLocationListener = new LocationListener() { @Override @@ -356,7 +402,7 @@ private final class Constants extends ContentObserver { * This is the time, after becoming inactive, at which we start looking at the * motion sensor to determine if the device is being left alone. We don't do this * immediately after going inactive just because we don't want to be continually running - * the significant motion sensor whenever the screen is off. + * the motion sensor whenever the screen is off. * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_INACTIVE_TIMEOUT */ @@ -399,7 +445,7 @@ private final class Constants extends ContentObserver { /** * This is the time, after the inactive timeout elapses, that we will wait looking - * for significant motion until we truly consider the device to be idle. + * for motion until we truly consider the device to be idle. * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT */ @@ -896,17 +942,38 @@ public void onBootPhase(int phase) { mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); - mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); - mLocationManager = (LocationManager) getContext().getSystemService( - Context.LOCATION_SERVICE); - mLocationRequest = new LocationRequest() - .setQuality(LocationRequest.ACCURACY_FINE) - .setInterval(0) - .setFastestInterval(0) - .setNumUpdates(1); + int sigMotionSensorId = getContext().getResources().getInteger( + com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor); + if (sigMotionSensorId > 0) { + mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true); + } + if (mMotionSensor == null && getContext().getResources().getBoolean( + com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) { + mMotionSensor = mSensorManager.getDefaultSensor( + Sensor.TYPE_WRIST_TILT_GESTURE, true); + } + if (mMotionSensor == null) { + // As a last ditch, fall back to SMD. + mMotionSensor = mSensorManager.getDefaultSensor( + Sensor.TYPE_SIGNIFICANT_MOTION, true); + } + + if (getContext().getResources().getBoolean( + com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { + mLocationManager = (LocationManager) getContext().getSystemService( + Context.LOCATION_SERVICE); + mLocationRequest = new LocationRequest() + .setQuality(LocationRequest.ACCURACY_FINE) + .setInterval(0) + .setFastestInterval(0) + .setNumUpdates(1); + } + + float angleThreshold = getContext().getResources().getInteger( + com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f; mAnyMotionDetector = new AnyMotionDetector( (PowerManager) getContext().getSystemService(Context.POWER_SERVICE), - mHandler, mSensorManager, this); + mHandler, mSensorManager, this, angleThreshold); Intent intent = new Intent(ACTION_STEP_IDLE_STATE) .setPackage("android") @@ -1242,7 +1309,7 @@ void resetIdleManagementLocked() { cancelAlarmLocked(); cancelSensingAlarmLocked(); cancelLocatingLocked(); - stopMonitoringSignificantMotion(); + stopMonitoringMotionLocked(); mAnyMotionDetector.stop(); } @@ -1271,8 +1338,8 @@ void stepIdleStateLocked() { switch (mState) { case STATE_INACTIVE: // We have now been inactive long enough, it is time to start looking - // for significant motion and sleep some more while doing so. - startMonitoringSignificantMotion(); + // for motion and sleep some more while doing so. + startMonitoringMotionLocked(); scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false); // Reset the upcoming idle delays. mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT; @@ -1298,17 +1365,30 @@ void stepIdleStateLocked() { if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); EventLogTags.writeDeviceIdle(mState, "step"); scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT); - mLocating = true; - mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener, - mHandler.getLooper()); - if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { - mHaveGps = true; + if (mLocationManager != null + && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { + mLocationManager.requestLocationUpdates(mLocationRequest, + mGenericLocationListener, mHandler.getLooper()); + mLocating = true; + } else { + mHasNetworkLocation = false; + } + if (mLocationManager != null + && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { + mHasGps = true; mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, mGpsLocationListener, mHandler.getLooper()); + mLocating = true; } else { - mHaveGps = false; + mHasGps = false; } - break; + // If we have a location provider, we're all set, the listeners will move state + // forward. + if (mLocating) { + break; + } + + // Otherwise, we have to move from locating into idle maintenance. case STATE_LOCATING: cancelSensingAlarmLocked(); cancelLocatingLocked(); @@ -1338,17 +1418,16 @@ void stepIdleStateLocked() { } } - void significantMotionLocked() { - if (DEBUG) Slog.d(TAG, "significantMotionLocked()"); - // When the sensor goes off, its trigger is automatically removed. - mSigMotionActive = false; + void motionLocked() { + if (DEBUG) Slog.d(TAG, "motionLocked()"); + // The motion sensor will have been disabled at this point handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion"); } void handleMotionDetectedLocked(long timeout, String type) { // The device is not yet active, so we want to go back to the pending idle - // state to wait again for no motion. Note that we only monitor for significant - // motion after moving out of the inactive state, so no need to worry about that. + // state to wait again for no motion. Note that we only monitor for motion + // after moving out of the inactive state, so no need to worry about that. if (mState != STATE_ACTIVE) { scheduleReportActiveLocked(type, Process.myUid()); mState = STATE_ACTIVE; @@ -1366,7 +1445,7 @@ void receivedGenericLocationLocked(Location location) { } if (DEBUG) Slog.d(TAG, "Generic location: " + location); mLastGenericLocation = new Location(location); - if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) { + if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) { return; } mLocated = true; @@ -1391,19 +1470,17 @@ void receivedGpsLocationLocked(Location location) { } } - void startMonitoringSignificantMotion() { - if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()"); - if (mSigMotionSensor != null && !mSigMotionActive) { - mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = true; + void startMonitoringMotionLocked() { + if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()"); + if (mMotionSensor != null && !mMotionListener.active) { + mMotionListener.registerLocked(); } } - void stopMonitoringSignificantMotion() { - if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()"); - if (mSigMotionActive) { - mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = false; + void stopMonitoringMotionLocked() { + if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()"); + if (mMotionSensor != null && mMotionListener.active) { + mMotionListener.unregisterLocked(); } } @@ -1432,10 +1509,10 @@ void cancelLocatingLocked() { void scheduleAlarmLocked(long delay, boolean idleUntil) { if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")"); - if (mSigMotionSensor == null) { - // If there is no significant motion sensor on this device, then we won't schedule + if (mMotionSensor == null) { + // If there is no motion sensor on this device, then we won't schedule // alarms, because we can't determine if the device is not moving. This effectively - // turns off normal exeuction of device idling, although it is still possible to + // turns off normal execution of device idling, although it is still possible to // manually poke it by pretending like the alarm is going off. return; } @@ -1917,15 +1994,16 @@ void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print(" mEnabled="); pw.println(mEnabled); pw.print(" mForceIdle="); pw.println(mForceIdle); - pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); + pw.print(" mMotionSensor="); pw.println(mMotionSensor); pw.print(" mCurDisplay="); pw.println(mCurDisplay); pw.print(" mScreenOn="); pw.println(mScreenOn); pw.print(" mCharging="); pw.println(mCharging); - pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); + pw.print(" mMotionActive="); pw.println(mMotionListener.active); pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving="); pw.println(mNotMoving); - pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHaveGps="); - pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated); + pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps="); + pw.print(mHasGps); pw.print(" mHasNetwork="); + pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated); if (mLastGenericLocation != null) { pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation); } diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index ab2ea8b67e7be..8bb158e3e9343 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -11,6 +11,10 @@ option java_package com.android.server # It lets us count the total amount of time between charges and the discharge level 2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6) +# dock battery +2738 dock_battery_level (level|1|6),(voltage|1|1),(temperature|1|1) +2739 dock_battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3) + # --------------------------- # PowerManagerService.java @@ -29,9 +33,13 @@ option java_package com.android.server # This is logged when the partial wake lock (keeping the device awake # regardless of whether the screen is off) is acquired or released. 2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3) +# The device is being asked to go into a soft sleep (typically by the ungaze gesture). +# It logs the time remaining before the device would've normally gone to sleep without the request. +2731 power_soft_sleep_requested (savedwaketimems|2) # -# Leave IDs through 2739 for more power logs (2730 used by battery_discharge above) +# Leave IDs through 2739 for more power logs (2730 used by battery_discharge and +# 2738-2739 used by dock battery above) # diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 4f9f972e78350..63484602da640 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -143,6 +143,7 @@ import java.util.List; import java.util.Locale; +import cyanogenmod.hardware.CMHardwareManager; import cyanogenmod.providers.CMSettings; import org.cyanogenmod.internal.util.QSUtils; @@ -239,6 +240,7 @@ public void onQSChanged() { private boolean mShowOngoingImeSwitcherForPhones; private boolean mNotificationShown; private final boolean mImeSelectedOnBoot; + private CMHardwareManager mCMHardware; static class SessionState { final ClientState client; @@ -506,15 +508,32 @@ public void onChange(boolean selfChange) { } }, userId); + if (mCMHardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE), false, this, userId); + } + if (mCMHardware.isSupported(CMHardwareManager.FEATURE_TOUCH_HOVERING)) { + resolver.registerContentObserver(CMSettings.Secure.getUriFor( + CMSettings.Secure.FEATURE_TOUCH_HOVERING), false, this, userId); + } + mRegistered = true; } @Override public void onChange(boolean selfChange, Uri uri) { final Uri showImeUri = Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); + final Uri touchSensitivityUri = + CMSettings.System.getUriFor(CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE); + final Uri touchHoveringUri = + CMSettings.Secure.getUriFor(CMSettings.Secure.FEATURE_TOUCH_HOVERING); synchronized (mMethodMap) { if (showImeUri.equals(uri)) { updateKeyboardFromSettingsLocked(); + } else if (touchSensitivityUri.equals(uri)) { + updateTouchSensitivity(); + } else if (touchHoveringUri.equals(uri)) { + updateTouchHovering(); } else { boolean enabledChanged = false; String newEnabled = mSettings.getEnabledInputMethodsStr(); @@ -943,11 +962,6 @@ public String[] getPackages(int userId) { } } - synchronized (mMethodMap) { - mSettingsObserver.registerContentObserverLocked(userId); - updateFromSettingsLocked(true); - } - // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME // according to the new system locale. final IntentFilter filter = new IntentFilter(); @@ -1072,6 +1086,9 @@ private void switchUserLocked(int newUserId) { mContext.getBasePackageName()); } + updateTouchHovering(); + updateTouchSensitivity(); + if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId + " selectedIme=" + mSettings.getSelectedInputMethod()); } @@ -1108,6 +1125,16 @@ public void systemRunning(StatusBarManagerService statusBar) { } if (!mSystemReady) { mSystemReady = true; + // Must happen before registerContentObserverLocked + mCMHardware = CMHardwareManager.getInstance(mContext); + + mSettingsObserver.registerContentObserverLocked( + mSettings.getCurrentUserId()); + updateFromSettingsLocked(true); + + updateTouchHovering(); + updateTouchSensitivity(); + mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mNotificationManager = (NotificationManager) @@ -1836,8 +1863,8 @@ private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) { com.android.internal.R.string.select_input_method, mImeSwitcherNotification.build(), UserHandle.ALL); mNotificationShown = true; - publishImeSelectorCustomTile(imi); } + publishImeSelectorCustomTile(imi); } else { if (mNotificationShown && mNotificationManager != null) { if (DEBUG) { @@ -1846,8 +1873,8 @@ private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) { mNotificationManager.cancelAsUser(null, com.android.internal.R.string.select_input_method, UserHandle.ALL); mNotificationShown = false; - unpublishImeSelectorCustomTile(); } + unpublishImeSelectorCustomTile(); } } finally { Binder.restoreCallingIdentity(ident); @@ -1970,6 +1997,26 @@ void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) { } + private void updateTouchSensitivity() { + if (!mCMHardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + return; + } + boolean touchSensitivityEnable = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE, 0) == 1; + mCMHardware.set(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY, + touchSensitivityEnable); + } + + private void updateTouchHovering() { + if (!mCMHardware.isSupported(CMHardwareManager.FEATURE_TOUCH_HOVERING)) { + return; + } + boolean touchHovering = CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.FEATURE_TOUCH_HOVERING, 0) == 1; + mCMHardware.set(CMHardwareManager.FEATURE_TOUCH_HOVERING, + touchHovering); + } + public void updateKeyboardFromSettingsLocked() { mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled(); if (mSwitchingDialog != null @@ -2982,10 +3029,8 @@ void buildInputMethodListLocked(ArrayList list, Slog.d(TAG, "Found an input method " + p); } - } catch (XmlPullParserException e) { - Slog.w(TAG, "Unable to load input method " + compName, e); - } catch (IOException e) { - Slog.w(TAG, "Unable to load input method " + compName, e); + } catch (Exception e) { + Slog.wtf(TAG, "Unable to load input method " + compName, e); } } @@ -3633,9 +3678,7 @@ private void processQSChangedLocked() { imi = mMethodMap.get(mCurMethodId); } } - final boolean hasInputMethod = isIMEVisible && imi != null && mCurrentSubtype != null; - boolean enabled = hasInputMethod; - if (enabled) { + if (shouldShowImeSwitcherLocked(isIMEVisible ? 1 : 0)) { publishImeSelectorCustomTile(imi); } else { unpublishImeSelectorCustomTile(); diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index ebe875964ed72..6cd8e1003da5e 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -2418,11 +2418,8 @@ private Location screenLocationLocked(Location location, String provider) { Bundle extras = location.getExtras(); boolean isBeingScreened = false; - if (extras == null) { - extras = new Bundle(); - } - if (!extras.containsKey(mComboNlpReadyMarker)) { + if (extras == null || !extras.containsKey(mComboNlpReadyMarker)) { // see if Combo Nlp is a passive listener ArrayList records = mRecordsByProvider.get(LocationManager.PASSIVE_PROVIDER); @@ -2431,6 +2428,10 @@ private Location screenLocationLocked(Location location, String provider) { if (r.mReceiver.mPackageName.equals(mComboNlpPackageName)) { if (!isBeingScreened) { isBeingScreened = true; + if (extras == null) { + location.setExtras(new Bundle()); + extras = location.getExtras(); + } extras.putBoolean(mComboNlpScreenMarker, true); } // send location to Combo Nlp for screening diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index bb0615d83e64b..10b0bdd270bac 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -61,6 +61,8 @@ import java.util.Timer; import java.util.TimerTask; +import cyanogenmod.providers.CMSettings; + /** * Keeps the lock pattern/password data and related settings for each user. * Used by LockPatternUtils. Needs to be a service because Settings app also needs @@ -261,6 +263,17 @@ private void migrateOldData() { setString("migrated_lockscreen_disabled", "true", 0); Slog.i(TAG, "Migrated lockscreen disabled flag"); } + + if (getString("migrated_pattern_size", null, 0) == null) { + final String val = getString(Secure.LOCK_PATTERN_SIZE, null, + UserHandle.USER_CURRENT); + if (val != null) { + setString(Secure.LOCK_PATTERN_SIZE, val, 0); + } + + setString("migrated_pattern_size", "true", 0); + Slog.i(TAG, "Migrated primary user pattern size"); + } } catch (RemoteException re) { Slog.e(TAG, "Unable to migrate old data", re); } @@ -356,6 +369,10 @@ public String getStringUnchecked(String key, String defaultValue, int userId) { } } + if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) { + key = Settings.Secure.LOCK_PATTERN_ENABLED; + } + return mStorage.readKeyValue(key, defaultValue, userId); } @@ -453,6 +470,7 @@ public byte getLockPatternSize(int userId) { @Override public void setLockPattern(String pattern, String savedCredential, int userId) throws RemoteException { + checkWritePermission(userId); byte[] currentHandle = getCurrentHandle(userId); if (pattern == null) { @@ -481,6 +499,7 @@ public void setLockPattern(String pattern, String savedCredential, int userId) @Override public void setLockPassword(String password, String savedCredential, int userId) throws RemoteException { + checkWritePermission(userId); byte[] currentHandle = getCurrentHandle(userId); if (password == null) { @@ -546,6 +565,9 @@ public VerifyCredentialResponse verifyPattern(String pattern, long challenge, in private VerifyCredentialResponse doVerifyPattern(String pattern, boolean hasChallenge, long challenge, int userId) throws RemoteException { checkPasswordReadPermission(userId); + if (TextUtils.isEmpty(pattern)) { + throw new IllegalArgumentException("Pattern can't be null or empty"); + } CredentialHash storedHash = mStorage.readPatternHash(userId); boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern; @@ -609,6 +631,9 @@ public VerifyCredentialResponse verifyPassword(String password, long challenge, private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge, long challenge, int userId) throws RemoteException { checkPasswordReadPermission(userId); + if (TextUtils.isEmpty(password)) { + throw new IllegalArgumentException("Password can't be null or empty"); + } CredentialHash storedHash = mStorage.readPasswordHash(userId); return verifyCredential(userId, storedHash, password, hasChallenge, challenge, new CredentialUtil() { @@ -810,6 +835,7 @@ public void requireStrongAuth(int strongAuthReason, int userId) { Secure.LOCK_BIOMETRIC_WEAK_FLAGS, Secure.LOCK_PATTERN_VISIBLE, Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + CMSettings.Secure.LOCK_PASS_TO_SECURITY_VIEW, Secure.LOCK_PATTERN_SIZE, Secure.LOCK_DOTS_VISIBLE, Secure.LOCK_SHOW_ERROR_PATH, diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java index 1b42dfeec0048..7ac2e42ee61a2 100644 --- a/services/core/java/com/android/server/LockSettingsStorage.java +++ b/services/core/java/com/android/server/LockSettingsStorage.java @@ -62,6 +62,7 @@ class LockSettingsStorage { private static final String LOCK_PATTERN_FILE = "gatekeeper.pattern.key"; private static final String BASE_ZERO_LOCK_PATTERN_FILE = "gatekeeper.gesture.key"; private static final String LEGACY_LOCK_PATTERN_FILE = "gesture.key"; + private static final String CM_LEGACY_LOCK_PATTERN_FILE = "cm_gesture.key"; private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key"; private static final String LEGACY_LOCK_PASSWORD_FILE = "password.key"; @@ -241,6 +242,11 @@ public CredentialHash readPatternHash(int userId) { return new CredentialHash(stored, CredentialHash.VERSION_LEGACY); } + stored = readFile(getCmLegacyLockPatternFilename(userId)); + if (stored != null && stored.length > 0) { + return new CredentialHash(stored, CredentialHash.VERSION_LEGACY); + } + return null; } @@ -253,7 +259,8 @@ public boolean hasPassword(int userId) { public boolean hasPattern(int userId) { return hasFile(getLockPatternFilename(userId)) || hasFile(getBaseZeroLockPatternFilename(userId)) || - hasFile(getLegacyLockPatternFilename(userId)); + hasFile(getLegacyLockPatternFilename(userId)) || + hasFile(getCmLegacyLockPatternFilename(userId)); } private boolean hasFile(String name) { @@ -380,6 +387,10 @@ String getLegacyLockPatternFilename(int userId) { return getLockCredentialFilePathForUser(userId, LEGACY_LOCK_PATTERN_FILE); } + String getCmLegacyLockPatternFilename(int userId) { + return getLockCredentialFilePathForUser(userId, CM_LEGACY_LOCK_PATTERN_FILE); + } + @VisibleForTesting String getLegacyLockPasswordFilename(int userId) { return getLockCredentialFilePathForUser(userId, LEGACY_LOCK_PASSWORD_FILE); diff --git a/services/core/java/com/android/server/LockSettingsStrongAuth.java b/services/core/java/com/android/server/LockSettingsStrongAuth.java index c023f4aa17a0f..5add4c08f3596 100644 --- a/services/core/java/com/android/server/LockSettingsStrongAuth.java +++ b/services/core/java/com/android/server/LockSettingsStrongAuth.java @@ -16,6 +16,7 @@ package com.android.server; +import android.os.Looper; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils.StrongAuthTracker; @@ -47,6 +48,12 @@ public class LockSettingsStrongAuth { private final ArrayList mStrongAuthTrackers = new ArrayList<>(); private final SparseIntArray mStrongAuthForUser = new SparseIntArray(); + private final Handler mHandler; + + public LockSettingsStrongAuth() { + mHandler = new Handler(Looper.getMainLooper(), mHandlerCallback); + } + private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) { for (int i = 0; i < mStrongAuthTrackers.size(); i++) { if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) { @@ -145,9 +152,9 @@ public void reportUnlock(int userId) { requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId); } - private final Handler mHandler = new Handler() { + private final Handler.Callback mHandlerCallback = new Handler.Callback() { @Override - public void handleMessage(Message msg) { + public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_REGISTER_TRACKER: handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj); @@ -162,6 +169,7 @@ public void handleMessage(Message msg) { handleRemoveUser(msg.arg1); break; } + return true; } }; } diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index 23556c01c72a2..3fa02bafc66c3 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -57,7 +57,7 @@ public void onReceive(final Context context, final Intent intent) { @Override public void run() { try { - boolean wipeMedia = intent.getBooleanExtra(EXTRA_WIPE_MEDIA, false); + boolean wipeMedia = intent.getBooleanExtra(EXTRA_WIPE_MEDIA, true); RecoverySystem.rebootWipeUserData(context, shutdown, reason, wipeMedia); Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 4847de39ac442..d539201ed20c4 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -1742,6 +1742,8 @@ public void setVolumeNickname(String fsUuid, String nickname) { Preconditions.checkNotNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); + if (rec == null) + return; rec.nickname = nickname; mCallbacks.notifyVolumeRecordChanged(rec); writeSettingsLocked(); @@ -1756,6 +1758,8 @@ public void setVolumeUserFlags(String fsUuid, int flags, int mask) { Preconditions.checkNotNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); + if (rec == null) + return; rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); mCallbacks.notifyVolumeRecordChanged(rec); writeSettingsLocked(); @@ -2388,6 +2392,12 @@ public int decryptStorage(String password) { // to let the UI to clear itself mHandler.postDelayed(new Runnable() { public void run() { + // unmount the internal emulated volume first + try { + mConnector.execute("volume", "unmount", "emulated"); + } catch (NativeDaemonConnectorException e) { + Slog.e(TAG, "unable to shut down internal volume", e); + } try { mCryptConnector.execute("cryptfs", "restart"); } catch (NativeDaemonConnectorException e) { diff --git a/services/core/java/com/android/server/net/NetPluginDelegate.java b/services/core/java/com/android/server/NetPluginDelegate.java similarity index 82% rename from services/core/java/com/android/server/net/NetPluginDelegate.java rename to services/core/java/com/android/server/NetPluginDelegate.java index 6716a6b6c29ae..18365f1e04c60 100644 --- a/services/core/java/com/android/server/net/NetPluginDelegate.java +++ b/services/core/java/com/android/server/NetPluginDelegate.java @@ -27,17 +27,16 @@ *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.android.server.net; +package com.android.server; import dalvik.system.PathClassLoader; -import java.lang.reflect.Constructor; - import android.util.Slog; +import android.net.Network; import android.net.NetworkStats; import android.util.Log; -class NetPluginDelegate { +public class NetPluginDelegate { private static final String TAG = "ConnectivityExtension"; private static final boolean LOGV = false; @@ -47,7 +46,7 @@ class NetPluginDelegate { private static boolean extensionFailed; - static void getTetherStats(NetworkStats uidStats, NetworkStats devStats, + public static void getTetherStats(NetworkStats uidStats, NetworkStats devStats, NetworkStats xtStats) { if (!loadTetherExtJar()) { return; @@ -60,9 +59,10 @@ static void getTetherStats(NetworkStats uidStats, NetworkStats devStats, e.printStackTrace(); Log.w(TAG, "error in invoke method"); } + if (LOGV) Slog.v(TAG, "getTetherStats() X"); } - static void setQuota(String iface, long quota) { + public static void setQuota(String iface, long quota) { if (!loadTetherExtJar()) { return; } @@ -72,8 +72,20 @@ static void setQuota(String iface, long quota) { } catch (Exception ex) { Log.w(TAG, "Error calling setQuota Method on extension jar"); } + if (LOGV) Slog.v(TAG, "setQuota(" + iface + ", " + quota + ") X"); } + public static void setUpstream(Network net) { + if (LOGV) Slog.v(TAG, "setUpstream(" + net + ") E"); + loadTetherExtJar(); + try { + tetherExtensionClass.getMethod("setUpstream", Network.class).invoke( + tetherExtensionObj, net); + } catch (Exception ex) { + Log.w(TAG, "Error calling setUpstream Method on extension jar"); + } + if (LOGV) Slog.v(TAG, "setUpstream(" + net + ") E"); + } private static boolean loadTetherExtJar() { diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index fd42b0ab647e0..f53c4ef881300 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -46,12 +46,16 @@ import android.annotation.NonNull; import android.app.ActivityManagerNative; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; +import android.net.LinkProperties; import android.net.Network; import android.net.NetworkPolicyManager; import android.net.NetworkStats; @@ -77,11 +81,13 @@ import android.telephony.PhoneStateListener; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.net.NetworkStatsFactory; @@ -110,6 +116,7 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.StringTokenizer; import java.util.concurrent.CountDownLatch; @@ -188,7 +195,7 @@ class NetdResponseCode { private final Handler mFgHandler; private final Handler mDaemonHandler; private final PhoneStateListener mPhoneStateListener; - + private String mWifiInterfaceName, mDataInterfaceName; private IBatteryStats mBatteryStats; private final Thread mThread; @@ -231,6 +238,10 @@ class NetdResponseCode { /** Set of states for the child firewall chains. True if the chain is active. */ @GuardedBy("mQuotaLock") final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); + @GuardedBy("mQuotaLock") + final Map mWlanBlacklist = new HashMap(); + @GuardedBy("mQuotaLock") + final Map mDataBlacklist = new HashMap(); private Object mIdleTimerLock = new Object(); /** Set of interfaces with active idle timers. */ @@ -258,6 +269,7 @@ private static class IdleTimerParams { private final RemoteCallbackList mNetworkActivityListeners = new RemoteCallbackList(); private boolean mNetworkActive; + private HashMap mPendingRestrictOnData = new HashMap(); /** * Constructs a new NetworkManagementService instance @@ -282,6 +294,7 @@ private NetworkManagementService(Context context, String socket) { FgThread.get().getLooper()); mThread = new Thread(mConnector, NETD_TAG); + mWifiInterfaceName = SystemProperties.get("wifi.interface"); mDaemonHandler = new Handler(FgThread.get().getLooper()); mPhoneStateListener = new PhoneStateListener(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, @@ -292,6 +305,7 @@ public void onDataConnectionRealTimeInfoChanged( if (DBG) Slog.d(TAG, "onDataConnectionRealTimeInfoChanged: " + dcRtInfo); notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE, dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true); + processPendingDataRestrictRequests(); } }; TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); @@ -322,6 +336,12 @@ public static NetworkManagementService create(Context context) throws Interrupte public void systemReady() { prepareNativeDaemon(); + // Register the receiver for Zerobalance blocking/unblocking + if (mContext.getResources().getBoolean(R.bool.config_zero_balance_operator)) { + final IntentFilter restrictFilter = new IntentFilter(); + restrictFilter.addAction("org.codeaurora.restrictData"); + mContext.registerReceiver(mZeroBalanceReceiver, restrictFilter); + } if (DBG) Slog.d(TAG, "Prepared"); } @@ -1821,6 +1841,85 @@ public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { } } + private void processPendingDataRestrictRequests() { + initDataInterface(); + if (TextUtils.isEmpty(mDataInterfaceName) || mPendingRestrictOnData.isEmpty()) { + return; + } + for (Integer key : mPendingRestrictOnData.keySet()) { + restrictAppOnData(key, mPendingRestrictOnData.get(key)); + } + mPendingRestrictOnData.clear(); + } + + @Override + public void restrictAppOnData(int uid, boolean restrict) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + initDataInterface(); + if (TextUtils.isEmpty(mDataInterfaceName)) { + // We don't have an interface name since data is not active + // yet, so queue up the request for when it comes up alive + mPendingRestrictOnData.put(uid, restrict); + return; + } + + synchronized (mQuotaLock) { + if (!mDataBlacklist.containsKey(uid) && !restrict) { + return; + } + Boolean wasRestricted = mDataBlacklist.get(uid); + if (Objects.equals(wasRestricted, restrict)) { + return; + } + mDataBlacklist.put(uid, restrict); + } + + try { + if (restrict) { + mConnector.execute("bandwidth", "addrestrictappsondata", mDataInterfaceName, uid); + } else { + mConnector.execute("bandwidth", "removerestrictappsondata", mDataInterfaceName, uid); + } + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + + @Override + public void restrictAppOnWlan(int uid, boolean restrict) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + synchronized (mQuotaLock) { + if (!mWlanBlacklist.containsKey(uid) && !restrict) { + return; + } + Boolean wasRestricted = mWlanBlacklist.get(uid); + if (Objects.equals(wasRestricted, restrict) || TextUtils.isEmpty(mWifiInterfaceName)) { + return; + } + mWlanBlacklist.put(uid, restrict); + } + + + try { + if (restrict) { + mConnector.execute("bandwidth", "addrestrictappsonwlan", mWifiInterfaceName, uid); + } else { + mConnector.execute("bandwidth", "removerestrictappsonwlan", mWifiInterfaceName, uid); + } + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + @Override public void setUidCleartextNetworkPolicy(int uid, int policy) { if (Binder.getCallingUid() != uid) { @@ -2573,4 +2672,41 @@ public void addInterfaceToLocalNetwork(String iface, List routes) { public void removeInterfaceFromLocalNetwork(String iface) { modifyInterfaceInNetwork("remove", "local", iface); } + + private void initDataInterface() { + if (!TextUtils.isEmpty(mDataInterfaceName)) { + return; + } + ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + LinkProperties linkProperties = cm.getLinkProperties(ConnectivityManager.TYPE_MOBILE); + if (linkProperties != null) { + mDataInterfaceName = linkProperties.getInterfaceName(); + } + } + + private BroadcastReceiver mZeroBalanceReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + boolean isBlockAllData = false; + if (intent != null + && intent.getAction().equals("org.codeaurora.restrictData")) { + isBlockAllData = intent.getBooleanExtra("Restrict", false); + Log.wtf("ZeroBalance", "Intent value to block unblock data" + isBlockAllData); + } + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + // Silently discard when control disabled + // TODO: Eventually migrate to always be enabled + if (!mBandwidthControlEnabled) return; + try { + Log.wtf("ZeroBalance", "before calling connector Intent" + + "value to block unblock data" + isBlockAllData); + mConnector.execute("bandwidth", + isBlockAllData ? "blockAllData" : "unblockAllData"); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + }; } diff --git a/services/core/java/com/android/server/PermissionDialog.java b/services/core/java/com/android/server/PermissionDialog.java index 0f337b80e2667..fd676b5f8935b 100644 --- a/services/core/java/com/android/server/PermissionDialog.java +++ b/services/core/java/com/android/server/PermissionDialog.java @@ -102,6 +102,10 @@ public PermissionDialog(Context context, AppOpsService service, mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT), DISMISS_TIMEOUT); } + public void ignore() { + mHandler.sendMessage(mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT)); + } + private String getAppName(String packageName) { ApplicationInfo appInfo = null; PackageManager pm = mContext.getPackageManager(); diff --git a/services/core/java/com/android/server/PermissionDialogReqQueue.java b/services/core/java/com/android/server/PermissionDialogReqQueue.java index ee944271f341a..5b602e33a607b 100644 --- a/services/core/java/com/android/server/PermissionDialogReqQueue.java +++ b/services/core/java/com/android/server/PermissionDialogReqQueue.java @@ -79,4 +79,10 @@ public void notifyAll(int mode) { } } } + + public void ignore() { + if (mDialog != null) { + mDialog.ignore(); + } + } } diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java index 2d9437058003a..fe69d98842ed5 100644 --- a/services/core/java/com/android/server/SystemConfig.java +++ b/services/core/java/com/android/server/SystemConfig.java @@ -16,7 +16,14 @@ package com.android.server; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; + import android.app.ActivityManager; +import android.content.ComponentName; import android.content.pm.FeatureInfo; import android.content.pm.Signature; import android.os.*; @@ -98,11 +105,14 @@ public static final class PermissionEntry { // These are the package names of apps which should be in the 'always' // URL-handling state upon factory reset. - final ArraySet mLinkedApps = new ArraySet<>(); + final ArraySet mLinkedApps = new ArraySet<>(); final ArrayMap> mSignatureAllowances = new ArrayMap>(); + // These are the permitted backup transport service components + final ArraySet mBackupTransportWhitelist = new ArraySet<>(); + public static SystemConfig getInstance() { synchronized (SystemConfig.class) { if (sInstance == null) { @@ -144,7 +154,7 @@ public ArraySet getFixedImeApps() { return mFixedImeApps; } - public ArraySet getLinkedApps() { + public ArraySet getLinkedApps() { return mLinkedApps; } @@ -152,6 +162,10 @@ public ArrayMap> getSignatureAllowances() { return mSignatureAllowances; } + public ArraySet getBackupTransportWhitelist() { + return mBackupTransportWhitelist; + } + SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( @@ -418,11 +432,29 @@ private void readPermissionsFromXml(File permFile, boolean onlyFeatures) { } else if ("app-link".equals(name)) { String pkgname = parser.getAttributeValue(null, "package"); + String state = parser.getAttributeValue(null, "state"); if (pkgname == null) { Slog.w(TAG, " without package in " + permFile + " at " + parser.getPositionDescription()); } else { - mLinkedApps.add(pkgname); + mLinkedApps.add(makeLink(pkgname, state)); + } + XmlUtils.skipCurrentTag(parser); + } else if ("backup-transport-whitelisted-service".equals(name)) { + String serviceName = parser.getAttributeValue(null, "service"); + if (serviceName == null) { + Slog.w(TAG, " without service in " + + permFile + " at " + parser.getPositionDescription()); + } else { + ComponentName cn = ComponentName.unflattenFromString(serviceName); + if (cn == null) { + Slog.w(TAG, + " with invalid service name " + + serviceName + " in "+ permFile + + " at " + parser.getPositionDescription()); + } else { + mBackupTransportWhitelist.add(cn); + } } XmlUtils.skipCurrentTag(parser); @@ -446,6 +478,23 @@ private void readPermissionsFromXml(File permFile, boolean onlyFeatures) { } } + private AppLink makeLink(String pkgname, String state) { + AppLink al = new AppLink(); + al.pkgname = pkgname; + if (state == null || "always".equals(state)) { // default + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; + } else if ("always-ask".equals(state)) { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; + } else if ("ask".equals("state")) { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; + } else if ("never".equals("state")) { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; + } else { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + } + return al; + } + void readPermission(XmlPullParser parser, String name) throws IOException, XmlPullParserException { if (mPermissions.containsKey(name)) { @@ -480,4 +529,20 @@ void readPermission(XmlPullParser parser, String name) XmlUtils.skipCurrentTag(parser); } } + + /** Simple value class to hold an app-link entry. + * It is public because PackageManagerService needs to see it */ + public static class AppLink { + public String pkgname; + public int state; + + @Override + public int hashCode() { return pkgname.hashCode(); } + + @Override + public boolean equals(Object other) { + if (!(other instanceof AppLink)) { return false; } + return pkgname.equals(((AppLink)other).pkgname); + } + } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 19a4851525a65..c7f4d0f9714ae 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -159,7 +159,7 @@ public String toString() { private String[] mDataConnectionApn; - private ArrayList mConnectedApns; + private ArrayList[] mConnectedApns; private LinkProperties[] mDataConnectionLinkProperties; @@ -292,11 +292,11 @@ public void onReceive(Context context, Intent intent) { mContext = context; mBatteryStats = BatteryStatsService.getService(); - mConnectedApns = new ArrayList(); int numPhones = TelephonyManager.getDefault().getPhoneCount(); if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones); mNumPhones = numPhones; + mConnectedApns = new ArrayList[numPhones]; mCallState = new int[numPhones]; mDataActivity = new int[numPhones]; mDataConnectionState = new int[numPhones]; @@ -314,6 +314,7 @@ public void onReceive(Context context, Intent intent) { mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones]; mCellInfo = new ArrayList>(); for (int i = 0; i < numPhones; i++) { + mConnectedApns[i] = new ArrayList(); mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; mDataConnectionState[i] = TelephonyManager.DATA_UNKNOWN; @@ -336,7 +337,6 @@ public void onReceive(Context context, Intent intent) { location.fillInNotifierBundle(mCellLocation[i]); } } - mConnectedApns = new ArrayList(); mAppOps = mContext.getSystemService(AppOpsManager.class); } @@ -1019,7 +1019,8 @@ public void notifyDataActivityForSubscriber(int subId, int state) { if (validatePhoneId(phoneId)) { mDataActivity[phoneId] = state; for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY)) { + if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onDataActivity(state); } catch (RemoteException ex) { @@ -1057,18 +1058,22 @@ public void notifyDataConnectionForSubscriber(int subId, int state, synchronized (mRecords) { int phoneId = SubscriptionManager.getPhoneId(subId); if (validatePhoneId(phoneId)) { + if (VDBG) { + log(" mConnectedApns[" + phoneId + "]=" + mConnectedApns[phoneId].toString()); + } boolean modified = false; if (state == TelephonyManager.DATA_CONNECTED) { - if (!mConnectedApns.contains(apnType)) { - mConnectedApns.add(apnType); + if (!mConnectedApns[phoneId].contains(apnType) + && !apnType.equals(PhoneConstants.APN_TYPE_IMS)) { + mConnectedApns[phoneId].add(apnType); if (mDataConnectionState[phoneId] != state) { mDataConnectionState[phoneId] = state; modified = true; } } } else { - if (mConnectedApns.remove(apnType)) { - if (mConnectedApns.isEmpty()) { + if (mConnectedApns[phoneId].remove(apnType)) { + if (mConnectedApns[phoneId].isEmpty()) { mDataConnectionState[phoneId] = state; modified = true; } else { @@ -1245,7 +1250,41 @@ public void notifyPreciseCallState(int ringingCallState, int foregroundCallState } broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, DisconnectCause.NOT_VALID, - PreciseDisconnectCause.NOT_VALID); + PreciseDisconnectCause.NOT_VALID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + public void notifyPreciseCallStateForSubscriber(int subId, int ringingCallState, + int foregroundCallState, int backgroundCallState) { + if (!checkNotifyPermission("notifyPreciseCallStateForSubscriber()")) { + return; + } + synchronized (mRecords) { + int phoneId = SubscriptionManager.getPhoneId(subId); + if (validatePhoneId(phoneId)) { + mRingingCallState = ringingCallState; + mForegroundCallState = foregroundCallState; + mBackgroundCallState = backgroundCallState; + mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState, + backgroundCallState, + DisconnectCause.NOT_VALID, + PreciseDisconnectCause.NOT_VALID); + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE) + && ((r.subId == subId) || + (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID))) { + try { + r.callback.onPreciseCallStateChanged(mPreciseCallState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, + DisconnectCause.NOT_VALID, + PreciseDisconnectCause.NOT_VALID, subId); } public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) { @@ -1267,7 +1306,8 @@ public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCaus handleRemoveListLocked(); } broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState, - mBackgroundCallState, disconnectCause, preciseDisconnectCause); + mBackgroundCallState, disconnectCause, preciseDisconnectCause, + SubscriptionManager.INVALID_SUBSCRIPTION_ID); } public void notifyPreciseDataConnectionFailed(String reason, String apnType, @@ -1507,13 +1547,16 @@ private void broadcastDataConnectionFailed(String reason, String apnType, } private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState, - int backgroundCallState, int disconnectCause, int preciseDisconnectCause) { + int backgroundCallState, int disconnectCause, int preciseDisconnectCause, int subId) { Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED); intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState); intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState); intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState); intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause); intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause); + if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); + } mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.READ_PRECISE_PHONE_STATE); } diff --git a/services/core/java/com/android/server/ThemeService.java b/services/core/java/com/android/server/ThemeService.java deleted file mode 100644 index dd85ad97f7e96..0000000000000 --- a/services/core/java/com/android/server/ThemeService.java +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod 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; - -import android.Manifest; -import android.app.ActivityManager; -import android.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.WallpaperManager; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ResolveInfo; -import android.content.pm.ThemeUtils; -import android.content.res.AssetManager; -import android.content.res.Configuration; -import android.content.res.IThemeProcessingListener; -import android.content.res.ThemeChangeRequest; -import android.content.res.ThemeConfig; -import android.content.res.IThemeChangeListener; -import android.content.res.IThemeService; -import android.graphics.Bitmap; -import android.media.RingtoneManager; -import android.os.Binder; -import android.os.Environment; -import android.os.FileUtils; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.SystemProperties; -import android.os.UserHandle; -import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; -import android.provider.ThemesContract; -import android.provider.ThemesContract.MixnMatchColumns; -import android.provider.ThemesContract.ThemesColumns; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.R; -import com.android.internal.util.cm.ImageUtils; -import cyanogenmod.providers.CMSettings; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import static android.content.pm.ThemeUtils.SYSTEM_THEME_PATH; -import static android.content.pm.ThemeUtils.THEME_BOOTANIMATION_PATH; -import static android.content.res.ThemeConfig.SYSTEM_DEFAULT; - -import java.util.List; - -/** - * {@hide} - */ -public class ThemeService extends IThemeService.Stub { - private static final String TAG = ThemeService.class.getName(); - - private static final boolean DEBUG = false; - - private static final String GOOGLE_SETUPWIZARD_PACKAGE = "com.google.android.setupwizard"; - private static final String CM_SETUPWIZARD_PACKAGE = "com.cyanogenmod.account"; - - private static final long MAX_ICON_CACHE_SIZE = 33554432L; // 32MB - private static final long PURGED_ICON_CACHE_SIZE = 25165824L; // 24 MB - - // Defines a min and max compatible api level for themes on this system. - private static final int MIN_COMPATIBLE_VERSION = 21; - - private HandlerThread mWorker; - private ThemeWorkerHandler mHandler; - private ResourceProcessingHandler mResourceProcessingHandler; - private Context mContext; - private PackageManager mPM; - private int mProgress; - private boolean mWallpaperChangedByUs = false; - private long mIconCacheSize = 0L; - private int mCurrentUserId = UserHandle.USER_OWNER; - - private boolean mIsThemeApplying = false; - - private final RemoteCallbackList mClients = - new RemoteCallbackList(); - - private final RemoteCallbackList mProcessingListeners = - new RemoteCallbackList(); - - final private ArrayList mThemesToProcessQueue = new ArrayList(0); - - private class ThemeWorkerHandler extends Handler { - private static final int MESSAGE_CHANGE_THEME = 1; - private static final int MESSAGE_APPLY_DEFAULT_THEME = 2; - private static final int MESSAGE_REBUILD_RESOURCE_CACHE = 3; - - public ThemeWorkerHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_CHANGE_THEME: - final ThemeChangeRequest request = (ThemeChangeRequest) msg.obj; - doApplyTheme(request, msg.arg1 == 1); - break; - case MESSAGE_APPLY_DEFAULT_THEME: - doApplyDefaultTheme(); - break; - case MESSAGE_REBUILD_RESOURCE_CACHE: - doRebuildResourceCache(); - break; - default: - Log.w(TAG, "Unknown message " + msg.what); - break; - } - } - } - - private class ResourceProcessingHandler extends Handler { - private static final int MESSAGE_QUEUE_THEME_FOR_PROCESSING = 3; - private static final int MESSAGE_DEQUEUE_AND_PROCESS_THEME = 4; - - public ResourceProcessingHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_QUEUE_THEME_FOR_PROCESSING: - String pkgName = (String) msg.obj; - synchronized (mThemesToProcessQueue) { - if (!mThemesToProcessQueue.contains(pkgName)) { - if (DEBUG) Log.d(TAG, "Adding " + pkgName + " for processing"); - mThemesToProcessQueue.add(pkgName); - if (mThemesToProcessQueue.size() == 1) { - this.sendEmptyMessage(MESSAGE_DEQUEUE_AND_PROCESS_THEME); - } - } - } - break; - case MESSAGE_DEQUEUE_AND_PROCESS_THEME: - synchronized (mThemesToProcessQueue) { - pkgName = mThemesToProcessQueue.get(0); - } - if (pkgName != null) { - if (DEBUG) Log.d(TAG, "Processing " + pkgName); - String name; - try { - PackageInfo pi = mPM.getPackageInfo(pkgName, 0); - name = getThemeName(pi); - } catch (PackageManager.NameNotFoundException e) { - name = null; - } - - int result = mPM.processThemeResources(pkgName); - if (result < 0) { - postFailedThemeInstallNotification(name != null ? name : pkgName); - } - sendThemeResourcesCachedBroadcast(pkgName, result); - - synchronized (mThemesToProcessQueue) { - mThemesToProcessQueue.remove(0); - if (mThemesToProcessQueue.size() > 0 && - !hasMessages(MESSAGE_DEQUEUE_AND_PROCESS_THEME)) { - this.sendEmptyMessage(MESSAGE_DEQUEUE_AND_PROCESS_THEME); - } - } - postFinishedProcessing(pkgName); - } - break; - default: - Log.w(TAG, "Unknown message " + msg.what); - break; - } - } - } - - public ThemeService(Context context) { - super(); - mContext = context; - mWorker = new HandlerThread("ThemeServiceWorker", Process.THREAD_PRIORITY_BACKGROUND); - mWorker.start(); - mHandler = new ThemeWorkerHandler(mWorker.getLooper()); - Log.i(TAG, "Spawned worker thread"); - - HandlerThread processingThread = new HandlerThread("ResourceProcessingThread", - Process.THREAD_PRIORITY_BACKGROUND); - processingThread.start(); - mResourceProcessingHandler = - new ResourceProcessingHandler(processingThread.getLooper()); - - // create the theme directory if it does not exist - ThemeUtils.createThemeDirIfNotExists(); - ThemeUtils.createFontDirIfNotExists(); - ThemeUtils.createAlarmDirIfNotExists(); - ThemeUtils.createNotificationDirIfNotExists(); - ThemeUtils.createRingtoneDirIfNotExists(); - ThemeUtils.createIconCacheDirIfNotExists(); - } - - public void systemRunning() { - // listen for wallpaper changes - IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); - mContext.registerReceiver(mWallpaperChangeReceiver, filter); - - filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); - mContext.registerReceiver(mUserChangeReceiver, filter); - - mPM = mContext.getPackageManager(); - - processInstalledThemes(); - - if (!isThemeApiUpToDate()) { - Log.d(TAG, "The system has been upgraded to a theme new api, " + - "checking if currently set theme is compatible"); - removeObsoleteThemeOverlayIfExists(); - updateThemeApi(); - } - } - - private void removeObsoleteThemeOverlayIfExists() { - // Get the current overlay theme so we can see it it's overlay should be unapplied - final IActivityManager am = ActivityManagerNative.getDefault(); - ThemeConfig config = null; - try { - if (am != null) { - config = am.getConfiguration().themeConfig; - } else { - Log.e(TAG, "ActivityManager getDefault() " + - "returned null, cannot remove obsolete theme"); - } - } catch(RemoteException e) { - Log.e(TAG, "Failed to get the theme config ", e); - } - if (config == null) return; // No need to unapply a theme if one isn't set - - // Populate the currentTheme map for the components we care about, we'll look - // at the compatibility of each pkg below. - HashMap currentThemeMap = new HashMap(); - currentThemeMap.put(ThemesColumns.MODIFIES_STATUS_BAR, config.getOverlayForStatusBar()); - currentThemeMap.put(ThemesColumns.MODIFIES_NAVIGATION_BAR, - config.getOverlayForNavBar()); - currentThemeMap.put(ThemesColumns.MODIFIES_OVERLAYS, config.getOverlayPkgName()); - - // Look at each component's theme (that we care about at least) and check compatibility - // of the pkg with the system. If it is not compatible then we will add it to a theme - // change request. - Map defaults = ThemeUtils.getDefaultComponents(mContext); - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - for(Map.Entry entry : currentThemeMap.entrySet()) { - String component = entry.getKey(); - String pkgName = entry.getValue(); - String defaultPkg = defaults.get(component); - - // Check that the default overlay theme is not currently set - if (defaultPkg.equals(pkgName)) { - Log.d(TAG, "Current overlay theme is same as default. " + - "Not doing anything for " + component); - continue; - } - - // No need to unapply a system theme since it is always compatible - if (ThemeConfig.SYSTEM_DEFAULT.equals(pkgName)) { - Log.d(TAG, "Current overlay theme for " - + component + " was system. no need to unapply"); - continue; - } - - if (!isThemeCompatibleWithUpgradedApi(pkgName)) { - Log.d(TAG, pkgName + "is incompatible with latest theme api for component " + - component + ", Applying " + defaultPkg); - builder.setComponent(component, pkgName); - } - } - - // Now actually unapply the incompatible themes - ThemeChangeRequest request = builder.build(); - if (!request.getThemeComponentsMap().isEmpty()) { - try { - requestThemeChange(request, true); - } catch(RemoteException e) { - // This cannot happen - } - } else { - Log.d(TAG, "Current theme is compatible with the system. Not unapplying anything"); - } - } - - private boolean isThemeCompatibleWithUpgradedApi(String pkgName) { - // Note this function does not cover the case of a downgrade. That case is out of scope and - // would require predicting whether the future API levels will be compatible or not. - boolean compatible = false; - try { - PackageInfo pi = mPM.getPackageInfo(pkgName, 0); - Log.d(TAG, "Comparing theme target: " + pi.applicationInfo.targetSdkVersion + - "to " + android.os.Build.VERSION.SDK_INT); - compatible = pi.applicationInfo.targetSdkVersion >= MIN_COMPATIBLE_VERSION; - } catch (NameNotFoundException e) { - Log.e(TAG, "Unable to get package info for " + pkgName, e); - } - return compatible; - } - - private boolean isThemeApiUpToDate() { - // We can't be 100% sure its an upgrade. If the field is undefined it - // could have been a factory reset. - final ContentResolver resolver = mContext.getContentResolver(); - int recordedApiLevel = android.os.Build.VERSION.SDK_INT; - try { - recordedApiLevel = CMSettings.Secure.getInt(resolver, - CMSettings.Secure.THEME_PREV_BOOT_API_LEVEL); - } catch (CMSettings.CMSettingNotFoundException e) { - recordedApiLevel = -1; - Log.d(TAG, "Previous api level not found. First time booting?"); - } - Log.d(TAG, "Prev api level was: " + recordedApiLevel - + ", api is now: " + android.os.Build.VERSION.SDK_INT); - - return recordedApiLevel == android.os.Build.VERSION.SDK_INT; - } - - private void updateThemeApi() { - final ContentResolver resolver = mContext.getContentResolver(); - boolean success = CMSettings.Secure.putInt(resolver, - CMSettings.Secure.THEME_PREV_BOOT_API_LEVEL, android.os.Build.VERSION.SDK_INT); - if (!success) { - Log.e(TAG, "Unable to store latest API level to secure settings"); - } - } - - private void doApplyTheme(ThemeChangeRequest request, boolean removePerAppTheme) { - synchronized(this) { - mProgress = 0; - } - - if (request == null || request.getNumChangesRequested() == 0) { - postFinish(true, request, 0); - return; - } - mIsThemeApplying = true; - long updateTime = System.currentTimeMillis(); - - incrementProgress(5); - - // TODO: provide progress updates that reflect the time needed for each component - final int progressIncrement = 75 / request.getNumChangesRequested(); - - if (request.getIconsThemePackageName() != null) { - updateIcons(request.getIconsThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getWallpaperThemePackageName() != null) { - if (updateWallpaper(request.getWallpaperThemePackageName(), - request.getWallpaperId())) { - mWallpaperChangedByUs = true; - } - incrementProgress(progressIncrement); - } - - if (request.getLockWallpaperThemePackageName() != null) { - updateLockscreen(request.getLockWallpaperThemePackageName()); - incrementProgress(progressIncrement); - } - - Environment.setUserRequired(false); - if (request.getNotificationThemePackageName() != null) { - updateNotifications(request.getNotificationThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getAlarmThemePackageName() != null) { - updateAlarms(request.getAlarmThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getRingtoneThemePackageName() != null) { - updateRingtones(request.getRingtoneThemePackageName()); - incrementProgress(progressIncrement); - } - Environment.setUserRequired(true); - - if (request.getBootanimationThemePackageName() != null) { - updateBootAnim(request.getBootanimationThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getFontThemePackageName() != null) { - updateFonts(request.getFontThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getLiveLockScreenThemePackageName() != null) { - updateLiveLockScreen(request.getLiveLockScreenThemePackageName()); - incrementProgress(progressIncrement); - } - - try { - updateProvider(request, updateTime); - } catch(IllegalArgumentException e) { - // Safeguard against provider not being ready yet. - Log.e(TAG, "Not updating the theme provider since it is unavailable"); - } - - if (shouldUpdateConfiguration(request)) { - updateConfiguration(request, removePerAppTheme); - } - - killLaunchers(request); - - postFinish(true, request, updateTime); - mIsThemeApplying = false; - } - - private void doApplyDefaultTheme() { - final ContentResolver resolver = mContext.getContentResolver(); - final String defaultThemePkg = Settings.Secure.getString(resolver, - Settings.Secure.DEFAULT_THEME_PACKAGE); - if (!TextUtils.isEmpty(defaultThemePkg)) { - String defaultThemeComponents = CMSettings.Secure.getString(resolver, - CMSettings.Secure.DEFAULT_THEME_COMPONENTS); - List components; - if (TextUtils.isEmpty(defaultThemeComponents)) { - components = ThemeUtils.getAllComponents(); - } else { - components = new ArrayList( - Arrays.asList(defaultThemeComponents.split("\\|"))); - } - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - for (String component : components) { - builder.setComponent(component, defaultThemePkg); - } - try { - requestThemeChange(builder.build(), true); - } catch (RemoteException e) { - Log.w(TAG, "Unable to set default theme", e); - } - } - } - - private void doRebuildResourceCache() { - FileUtils.deleteContents(new File(ThemeUtils.RESOURCE_CACHE_DIR)); - processInstalledThemes(); - } - - private void updateProvider(ThemeChangeRequest request, long updateTime) { - ContentValues values = new ContentValues(); - values.put(MixnMatchColumns.COL_UPDATE_TIME, updateTime); - Map componentMap = request.getThemeComponentsMap(); - for (String component : componentMap.keySet()) { - values.put(ThemesContract.MixnMatchColumns.COL_VALUE, componentMap.get(component)); - String where = ThemesContract.MixnMatchColumns.COL_KEY + "=?"; - String[] selectionArgs = { MixnMatchColumns.componentToMixNMatchKey(component) }; - if (selectionArgs[0] == null) { - continue; // No equivalence between mixnmatch and theme - } - - // Add component ID for multiwallpaper - if (ThemesColumns.MODIFIES_LAUNCHER.equals(component)) { - values.put(MixnMatchColumns.COL_COMPONENT_ID, request.getWallpaperId()); - } - - mContext.getContentResolver().update(MixnMatchColumns.CONTENT_URI, values, where, - selectionArgs); - } - } - - private boolean updateIcons(String pkgName) { - ThemeUtils.clearIconCache(); - try { - if (pkgName.equals(SYSTEM_DEFAULT)) { - mPM.updateIconMaps(null); - } else { - mPM.updateIconMaps(pkgName); - } - } catch (Exception e) { - Log.w(TAG, "Changing icons failed", e); - return false; - } - return true; - } - - private boolean updateFonts(String pkgName) { - //Clear the font dir - FileUtils.deleteContents(new File(ThemeUtils.SYSTEM_THEME_FONT_PATH)); - - if (!pkgName.equals(SYSTEM_DEFAULT)) { - //Get Font Assets - Context themeCtx; - String[] assetList; - try { - themeCtx = mContext.createPackageContext(pkgName, Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - assetList = assetManager.list("fonts"); - } catch (Exception e) { - Log.e(TAG, "There was an error getting assets for pkg " + pkgName, e); - return false; - } - if (assetList == null || assetList.length == 0) { - Log.e(TAG, "Could not find any font assets"); - return false; - } - - //Copy font assets to font dir - for(String asset : assetList) { - InputStream is = null; - OutputStream os = null; - try { - is = ThemeUtils.getInputStreamFromAsset(themeCtx, - "file:///android_asset/fonts/" + asset); - File outFile = new File(ThemeUtils.SYSTEM_THEME_FONT_PATH, asset); - FileUtils.copyToFile(is, outFile); - FileUtils.setPermissions(outFile, - FileUtils.S_IRWXU|FileUtils.S_IRGRP|FileUtils.S_IRWXO, -1, -1); - } catch (Exception e) { - Log.e(TAG, "There was an error installing the new fonts for pkg " + pkgName, e); - return false; - } finally { - ThemeUtils.closeQuietly(is); - ThemeUtils.closeQuietly(os); - } - } - } - - //Notify zygote that themes need a refresh - SystemProperties.set("sys.refresh_theme", "1"); - return true; - } - - private boolean updateBootAnim(String pkgName) { - if (SYSTEM_DEFAULT.equals(pkgName)) { - clearBootAnimation(); - return true; - } - - try { - final ApplicationInfo ai = mPM.getApplicationInfo(pkgName, 0); - applyBootAnimation(ai.sourceDir); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Changing boot animation failed", e); - return false; - } - return true; - } - - private boolean updateAlarms(String pkgName) { - return updateAudible(ThemeUtils.SYSTEM_THEME_ALARM_PATH, "alarms", - RingtoneManager.TYPE_ALARM, pkgName); - } - - private boolean updateNotifications(String pkgName) { - return updateAudible(ThemeUtils.SYSTEM_THEME_NOTIFICATION_PATH, "notifications", - RingtoneManager.TYPE_NOTIFICATION, pkgName); - } - - private boolean updateRingtones(String pkgName) { - return updateAudible(ThemeUtils.SYSTEM_THEME_RINGTONE_PATH, "ringtones", - RingtoneManager.TYPE_RINGTONE, pkgName); - } - - private boolean updateAudible(String dirPath, String assetPath, int type, String pkgName) { - //Clear the dir - ThemeUtils.clearAudibles(mContext, dirPath); - if (pkgName.equals(SYSTEM_DEFAULT)) { - if (!ThemeUtils.setDefaultAudible(mContext, type)) { - Log.e(TAG, "There was an error installing the default audio file"); - return false; - } - return true; - } - - PackageInfo pi = null; - try { - pi = mPM.getPackageInfo(pkgName, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Unable to update audible " + dirPath, e); - return false; - } - - //Get theme Assets - Context themeCtx; - String[] assetList; - try { - themeCtx = mContext.createPackageContext(pkgName, Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - assetList = assetManager.list(assetPath); - } catch (Exception e) { - Log.e(TAG, "There was an error getting assets for pkg " + pkgName, e); - return false; - } - if (assetList == null || assetList.length == 0) { - Log.e(TAG, "Could not find any audio assets"); - return false; - } - - // TODO: right now we just load the first file but this will need to be changed - // in the future if multiple audio files are supported. - final String asset = assetList[0]; - if (!ThemeUtils.isValidAudible(asset)) return false; - - InputStream is = null; - OutputStream os = null; - try { - is = ThemeUtils.getInputStreamFromAsset(themeCtx, "file:///android_asset/" - + assetPath + File.separator + asset); - File outFile = new File(dirPath, asset); - FileUtils.copyToFile(is, outFile); - FileUtils.setPermissions(outFile, - FileUtils.S_IRWXU|FileUtils.S_IRGRP|FileUtils.S_IRWXO,-1, -1); - ThemeUtils.setAudible(mContext, outFile, type, pi.themeInfo.name); - } catch (Exception e) { - Log.e(TAG, "There was an error installing the new audio file for pkg " + pkgName, e); - return false; - } finally { - ThemeUtils.closeQuietly(is); - ThemeUtils.closeQuietly(os); - } - return true; - } - - private boolean updateLockscreen(String pkgName) { - boolean success; - success = setCustomLockScreenWallpaper(pkgName); - - // TODO: uncomment once Keyguard wallpaper is re-implemented - /* - if (success) { - mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED), - UserHandle.ALL); - } - */ - return success; - } - - private boolean setCustomLockScreenWallpaper(String pkgName) { - // TODO: uncomment once Keyguard wallpaper is re-implemented - /* - WallpaperManager wm = WallpaperManager.getInstance(mContext); - try { - if (SYSTEM_DEFAULT.equals(pkgName) || TextUtils.isEmpty(pkgName)) { - wm.clearKeyguardWallpaper(); - } else { - InputStream in = ImageUtils.getCroppedKeyguardStream(pkgName, mContext); - if (in != null) { - wm.setKeyguardStream(in); - ThemeUtils.closeQuietly(in); - } - } - } catch (Exception e) { - Log.e(TAG, "There was an error setting lockscreen wp for pkg " + pkgName, e); - return false; - } - */ - return true; - } - - private boolean updateWallpaper(String pkgName, long id) { - WallpaperManager wm = WallpaperManager.getInstance(mContext); - if (SYSTEM_DEFAULT.equals(pkgName)) { - try { - wm.clear(); - } catch (IOException e) { - return false; - } - } else if (TextUtils.isEmpty(pkgName)) { - try { - wm.clear(false); - } catch (IOException e) { - return false; - } - } else { - InputStream in = null; - try { - in = ImageUtils.getCroppedWallpaperStream(pkgName, id, mContext); - if (in != null) - wm.setStream(in); - } catch (Exception e) { - return false; - } finally { - ThemeUtils.closeQuietly(in); - } - } - return true; - } - - private boolean updateLiveLockScreen(String pkgName) { - // TODO: do something meaningful here once ready - return true; - } - - private boolean updateConfiguration(ThemeChangeRequest request, - boolean removePerAppThemes) { - final IActivityManager am = ActivityManagerNative.getDefault(); - if (am != null) { - final long token = Binder.clearCallingIdentity(); - try { - Configuration config = am.getConfiguration(); - ThemeConfig.Builder themeBuilder = createBuilderFrom(config, request, null, - removePerAppThemes); - ThemeConfig newConfig = themeBuilder.build(); - - config.themeConfig = newConfig; - am.updateConfiguration(config); - } catch (RemoteException e) { - return false; - } finally { - Binder.restoreCallingIdentity(token); - } - } - return true; - } - - private boolean updateConfiguration(ThemeConfig themeConfig) { - final IActivityManager am = ActivityManagerNative.getDefault(); - if (am != null) { - final long token = Binder.clearCallingIdentity(); - try { - Configuration config = am.getConfiguration(); - - config.themeConfig = themeConfig; - am.updateConfiguration(config); - } catch (RemoteException e) { - return false; - } finally { - Binder.restoreCallingIdentity(token); - } - } - return true; - } - - private boolean shouldUpdateConfiguration(ThemeChangeRequest request) { - return request.getOverlayThemePackageName() != null || - request.getFontThemePackageName() != null || - request.getIconsThemePackageName() != null || - request.getStatusBarThemePackageName() != null || - request.getNavBarThemePackageName() != null || - request.getPerAppOverlays().size() > 0; - } - - private static ThemeConfig.Builder createBuilderFrom(Configuration config, - ThemeChangeRequest request, String pkgName, boolean removePerAppThemes) { - ThemeConfig.Builder builder = new ThemeConfig.Builder(config.themeConfig); - - if (removePerAppThemes) removePerAppThemesFromConfig(builder, config.themeConfig); - - if (request.getIconsThemePackageName() != null) { - builder.defaultIcon(pkgName == null ? request.getIconsThemePackageName() : pkgName); - } - - if (request.getOverlayThemePackageName() != null) { - builder.defaultOverlay(pkgName == null ? - request.getOverlayThemePackageName() : pkgName); - } - - if (request.getFontThemePackageName() != null) { - builder.defaultFont(pkgName == null ? request.getFontThemePackageName() : pkgName); - } - - if (request.getStatusBarThemePackageName() != null) { - builder.overlay(ThemeConfig.SYSTEMUI_STATUS_BAR_PKG, pkgName == null ? - request.getStatusBarThemePackageName() : pkgName); - } - - if (request.getNavBarThemePackageName() != null) { - builder.overlay(ThemeConfig.SYSTEMUI_NAVBAR_PKG, pkgName == null ? - request.getNavBarThemePackageName() : pkgName); - } - - // check for any per app overlays being applied - Map appOverlays = request.getPerAppOverlays(); - for (String appPkgName : appOverlays.keySet()) { - if (appPkgName != null) { - builder.overlay(appPkgName, appOverlays.get(appPkgName)); - } - } - - builder.setLastThemeChangeRequestType(request.getReqeustType()); - - return builder; - } - - private static void removePerAppThemesFromConfig(ThemeConfig.Builder builder, - ThemeConfig themeConfig) { - if (themeConfig != null) { - Map themes = themeConfig.getAppThemes(); - for (String appPkgName : themes.keySet()) { - if (ThemeUtils.isPerAppThemeComponent(appPkgName)) { - builder.overlay(appPkgName, null); - } - } - } - } - - // Kill the current Home process, they tend to be evil and cache - // drawable references in all apps - private void killLaunchers(ThemeChangeRequest request) { - if (request.getOverlayThemePackageName() == null - && request.getIconsThemePackageName() == null) { - return; - } - - final ActivityManager am = - (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - - Intent homeIntent = new Intent(); - homeIntent.setAction(Intent.ACTION_MAIN); - homeIntent.addCategory(Intent.CATEGORY_HOME); - - List infos = mPM.queryIntentActivities(homeIntent, 0); - List themeChangeInfos = mPM.queryBroadcastReceivers( - new Intent(ThemeUtils.ACTION_THEME_CHANGED), 0); - for(ResolveInfo info : infos) { - if (info.activityInfo != null && info.activityInfo.applicationInfo != null && - !isSetupActivity(info) && !handlesThemeChanges( - info.activityInfo.applicationInfo.packageName, themeChangeInfos)) { - String pkgToStop = info.activityInfo.applicationInfo.packageName; - Log.d(TAG, "Force stopping " + pkgToStop + " for theme change"); - try { - am.forceStopPackage(pkgToStop); - } catch(Exception e) { - Log.e(TAG, "Unable to force stop package, did you forget platform signature?", - e); - } - } - } - } - - private boolean isSetupActivity(ResolveInfo info) { - return GOOGLE_SETUPWIZARD_PACKAGE.equals(info.activityInfo.packageName) || - CM_SETUPWIZARD_PACKAGE.equals(info.activityInfo.packageName); - } - - private boolean handlesThemeChanges(String pkgName, List infos) { - if (infos != null && infos.size() > 0) { - for (ResolveInfo info : infos) { - if (info.activityInfo.applicationInfo.packageName.equals(pkgName)) { - return true; - } - } - } - return false; - } - - private void postProgress() { - int N = mClients.beginBroadcast(); - for(int i=0; i < N; i++) { - IThemeChangeListener listener = mClients.getBroadcastItem(0); - try { - listener.onProgress(mProgress); - } catch(RemoteException e) { - Log.w(TAG, "Unable to post progress to client listener", e); - } - } - mClients.finishBroadcast(); - } - - private void postFinish(boolean isSuccess, ThemeChangeRequest request, long updateTime) { - synchronized(this) { - mProgress = 0; - } - - int N = mClients.beginBroadcast(); - for(int i=0; i < N; i++) { - IThemeChangeListener listener = mClients.getBroadcastItem(0); - try { - listener.onFinish(isSuccess); - } catch(RemoteException e) { - Log.w(TAG, "Unable to post progress to client listener", e); - } - } - mClients.finishBroadcast(); - - // if successful, broadcast that the theme changed - if (isSuccess) { - broadcastThemeChange(request, updateTime); - } - } - - private void postFinishedProcessing(String pkgName) { - int N = mProcessingListeners.beginBroadcast(); - for(int i=0; i < N; i++) { - IThemeProcessingListener listener = mProcessingListeners.getBroadcastItem(0); - try { - listener.onFinishedProcessing(pkgName); - } catch(RemoteException e) { - Log.w(TAG, "Unable to post progress to listener", e); - } - } - mProcessingListeners.finishBroadcast(); - } - - private void broadcastThemeChange(ThemeChangeRequest request, long updateTime) { - Map componentMap = request.getThemeComponentsMap(); - if (componentMap == null || componentMap.size() == 0) return; - - final Intent intent = new Intent(ThemeUtils.ACTION_THEME_CHANGED); - ArrayList componentsArrayList = new ArrayList(componentMap.keySet()); - intent.putStringArrayListExtra(ThemeUtils.EXTRA_COMPONENTS, componentsArrayList); - intent.putExtra(ThemeUtils.EXTRA_REQUEST_TYPE, request.getReqeustType().ordinal()); - intent.putExtra(ThemeUtils.EXTRA_UPDATE_TIME, updateTime); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - private void incrementProgress(int increment) { - synchronized(this) { - mProgress += increment; - if (mProgress > 100) mProgress = 100; - } - postProgress(); - } - - @Override - public void requestThemeChangeUpdates(IThemeChangeListener listener) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mClients.register(listener); - } - - @Override - public void removeUpdates(IThemeChangeListener listener) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mClients.unregister(listener); - } - - @Override - public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - Message msg; - - /** - * Since the ThemeService handles compiling theme resource we need to make sure that any - * of the components we are trying to apply are either already processed or put to the - * front of the queue and handled before the theme change takes place. - * - * TODO: create a callback that can be sent to any ThemeChangeListeners to notify them that - * the theme will be applied once the processing is done. - */ - synchronized (mThemesToProcessQueue) { - Map componentMap = request.getThemeComponentsMap(); - for (Object key : componentMap.keySet()) { - if (ThemesColumns.MODIFIES_OVERLAYS.equals(key) || - ThemesColumns.MODIFIES_NAVIGATION_BAR.equals(key) || - ThemesColumns.MODIFIES_STATUS_BAR.equals(key) || - ThemesColumns.MODIFIES_ICONS.equals(key)) { - String pkgName = (String) componentMap.get(key); - if (mThemesToProcessQueue.indexOf(pkgName) > 0) { - mThemesToProcessQueue.remove(pkgName); - mThemesToProcessQueue.add(0, pkgName); - // We want to make sure these resources are taken care of first so - // send the dequeue message and place it in the front of the queue - msg = mResourceProcessingHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_DEQUEUE_AND_PROCESS_THEME); - mResourceProcessingHandler.sendMessageAtFrontOfQueue(msg); - } - } - } - } - msg = Message.obtain(); - msg.what = ThemeWorkerHandler.MESSAGE_CHANGE_THEME; - msg.obj = request; - msg.arg1 = removePerAppThemes ? 1 : 0; - mHandler.sendMessage(msg); - } - - @Override - public void applyDefaultTheme() { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - Message msg = Message.obtain(); - msg.what = ThemeWorkerHandler.MESSAGE_APPLY_DEFAULT_THEME; - mHandler.sendMessage(msg); - } - - @Override - public boolean isThemeApplying() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_THEME_MANAGER, null); - return mIsThemeApplying; - } - - @Override - public int getProgress() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_THEME_MANAGER, null); - synchronized(this) { - return mProgress; - } - } - - @Override - public boolean cacheComposedIcon(Bitmap icon, String fileName) throws RemoteException { - final long token = Binder.clearCallingIdentity(); - boolean success; - FileOutputStream os; - final File cacheDir = new File(ThemeUtils.SYSTEM_THEME_ICON_CACHE_DIR); - if (cacheDir.listFiles().length == 0) { - mIconCacheSize = 0; - } - try { - File outFile = new File(cacheDir, fileName); - os = new FileOutputStream(outFile); - icon.compress(Bitmap.CompressFormat.PNG, 90, os); - os.close(); - FileUtils.setPermissions(outFile, - FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH, - -1, -1); - mIconCacheSize += outFile.length(); - if (mIconCacheSize > MAX_ICON_CACHE_SIZE) { - purgeIconCache(); - } - success = true; - } catch (Exception e) { - success = false; - Log.w(TAG, "Unable to cache icon " + fileName, e); - } - Binder.restoreCallingIdentity(token); - return success; - } - - @Override - public boolean processThemeResources(String themePkgName) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - try { - mPM.getPackageInfo(themePkgName, 0); - } catch (PackageManager.NameNotFoundException e) { - // Package doesn't exist so nothing to process - return false; - } - // Obtain a message and send it to the handler to process this theme - Message msg = mResourceProcessingHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_QUEUE_THEME_FOR_PROCESSING, 0, 0, themePkgName); - mResourceProcessingHandler.sendMessage(msg); - return true; - } - - @Override - public boolean isThemeBeingProcessed(String themePkgName) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - synchronized (mThemesToProcessQueue) { - return mThemesToProcessQueue.contains(themePkgName); - } - } - - @Override - public void registerThemeProcessingListener(IThemeProcessingListener listener) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mProcessingListeners.register(listener); - } - - @Override - public void unregisterThemeProcessingListener(IThemeProcessingListener listener) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mProcessingListeners.unregister(listener); - } - - @Override - public void rebuildResourceCache() throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mHandler.sendEmptyMessage(ThemeWorkerHandler.MESSAGE_REBUILD_RESOURCE_CACHE); - } - - private void purgeIconCache() { - Log.d(TAG, "Purging icon cahe of size " + mIconCacheSize); - File cacheDir = new File(ThemeUtils.SYSTEM_THEME_ICON_CACHE_DIR); - File[] files = cacheDir.listFiles(); - Arrays.sort(files, mOldestFilesFirstComparator); - for (File f : files) { - if (!f.isDirectory()) { - final long size = f.length(); - if(f.delete()) mIconCacheSize -= size; - } - if (mIconCacheSize <= PURGED_ICON_CACHE_SIZE) break; - } - } - - private boolean applyBootAnimation(String themePath) { - boolean success = false; - try { - ZipFile zip = new ZipFile(new File(themePath)); - ZipEntry ze = zip.getEntry(THEME_BOOTANIMATION_PATH); - if (ze != null) { - clearBootAnimation(); - BufferedInputStream is = new BufferedInputStream(zip.getInputStream(ze)); - final String bootAnimationPath = SYSTEM_THEME_PATH + File.separator - + "bootanimation.zip"; - ThemeUtils.copyAndScaleBootAnimation(mContext, is, bootAnimationPath); - FileUtils.setPermissions(bootAnimationPath, - FileUtils.S_IRWXU|FileUtils.S_IRGRP|FileUtils.S_IROTH, -1, -1); - } - zip.close(); - success = true; - } catch (Exception e) { - Log.w(TAG, "Unable to load boot animation for " + themePath, e); - } - - return success; - } - - private void clearBootAnimation() { - File anim = new File(SYSTEM_THEME_PATH + File.separator + "bootanimation.zip"); - if (anim.exists()) - anim.delete(); - } - - private BroadcastReceiver mWallpaperChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!mWallpaperChangedByUs) { - // In case the mixnmatch table has a mods_launcher entry, we'll clear it - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - builder.setWallpaper(""); - updateProvider(builder.build(), System.currentTimeMillis()); - } else { - mWallpaperChangedByUs = false; - } - } - }; - - private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userHandle >= 0 && userHandle != mCurrentUserId) { - mCurrentUserId = userHandle; - ThemeConfig config = ThemeConfig.getBootThemeForUser(mContext.getContentResolver(), - userHandle); - if (DEBUG) { - Log.d(TAG, - "Changing theme for user " + userHandle + " to " + config.toString()); - } - ThemeChangeRequest request = new ThemeChangeRequest.Builder(config).build(); - try { - requestThemeChange(request, true); - } catch (RemoteException e) { - Log.e(TAG, "Unable to change theme for user change", e); - } - } - } - }; - - private Comparator mOldestFilesFirstComparator = new Comparator() { - @Override - public int compare(File lhs, File rhs) { - return (int) (lhs.lastModified() - rhs.lastModified()); - } - }; - - private void processInstalledThemes() { - final String defaultTheme = ThemeUtils.getDefaultThemePackageName(mContext); - Message msg; - // Make sure the default theme is the first to get processed! - if (!ThemeConfig.SYSTEM_DEFAULT.equals(defaultTheme)) { - msg = mHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_QUEUE_THEME_FOR_PROCESSING, - 0, 0, defaultTheme); - mResourceProcessingHandler.sendMessage(msg); - } - // Iterate over all installed packages and queue up the ones that are themes or icon packs - List packages = mPM.getInstalledPackages(0); - for (PackageInfo info : packages) { - if (!defaultTheme.equals(info.packageName) && - (info.isThemeApk || info.isLegacyIconPackApk)) { - msg = mHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_QUEUE_THEME_FOR_PROCESSING, - 0, 0, info.packageName); - mResourceProcessingHandler.sendMessage(msg); - } - } - } - - private void sendThemeResourcesCachedBroadcast(String themePkgName, int resultCode) { - final Intent intent = new Intent(Intent.ACTION_THEME_RESOURCES_CACHED); - intent.putExtra(Intent.EXTRA_THEME_PACKAGE_NAME, themePkgName); - intent.putExtra(Intent.EXTRA_THEME_RESULT, resultCode); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /** - * Posts a notification to let the user know the theme was not installed. - * @param name - */ - private void postFailedThemeInstallNotification(String name) { - NotificationManager nm = - (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - Notification notice = new Notification.Builder(mContext) - .setAutoCancel(true) - .setOngoing(false) - .setContentTitle( - mContext.getString(R.string.theme_install_error_title)) - .setContentText(String.format(mContext.getString( - R.string.theme_install_error_message), - name)) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setWhen(System.currentTimeMillis()) - .build(); - nm.notify(name.hashCode(), notice); - } - - private String getThemeName(PackageInfo pi) { - if (pi.themeInfo != null) { - return pi.themeInfo.name; - } else if (pi.isLegacyIconPackApk) { - return pi.applicationInfo.name; - } - - return null; - } -} diff --git a/services/core/java/com/android/server/ThermalObserver.java b/services/core/java/com/android/server/ThermalObserver.java new file mode 100644 index 0000000000000..aee28fb6b2958 --- /dev/null +++ b/services/core/java/com/android/server/ThermalObserver.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.Handler; +import android.os.Message; +import android.os.PowerManager; +import android.os.UEventObserver; +import android.os.UserHandle; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +/** + * ThermalObserver for monitoring temperature changes. + */ +public class ThermalObserver extends SystemService { + private static final String TAG = "ThermalObserver"; + + private static final String CALLSTATE_UEVENT_MATCH = + "DEVPATH=/devices/virtual/switch/thermalstate"; + + private static final int MSG_THERMAL_STATE_CHANGED = 0; + + private static final int SWITCH_STATE_NORMAL = 0; + private static final int SWITCH_STATE_WARNING = 1; + private static final int SWITCH_STATE_EXCEEDED = 2; + + private final PowerManager mPowerManager; + private final PowerManager.WakeLock mWakeLock; + + private final Object mLock = new Object(); + private Integer mLastState; + + private final UEventObserver mThermalWarningObserver = new UEventObserver() { + @Override + public void onUEvent(UEventObserver.UEvent event) { + updateLocked(Integer.parseInt(event.get("SWITCH_STATE"))); + } + }; + + private final Handler mHandler = new Handler(true /*async*/) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_THERMAL_STATE_CHANGED: + handleThermalStateChange(msg.arg1); + mWakeLock.release(); + break; + } + } + }; + + public ThermalObserver(Context context) { + super(context); + mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + + mThermalWarningObserver.startObserving(CALLSTATE_UEVENT_MATCH); + } + + private void updateLocked(int state) { + Message message = new Message(); + message.what = MSG_THERMAL_STATE_CHANGED; + message.arg1 = state; + + mWakeLock.acquire(); + mHandler.sendMessage(message); + } + + private void handleThermalStateChange(int state) { + synchronized (mLock) { + mLastState = state; + Intent intent = new Intent(Intent.ACTION_THERMAL_EVENT); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + + final int thermalState; + + switch (state) { + case SWITCH_STATE_WARNING: + thermalState = Intent.EXTRA_THERMAL_STATE_WARNING; + break; + case SWITCH_STATE_EXCEEDED: + thermalState = Intent.EXTRA_THERMAL_STATE_EXCEEDED; + break; + case SWITCH_STATE_NORMAL: + default: + thermalState = Intent.EXTRA_THERMAL_STATE_NORMAL; + break; + } + + intent.putExtra(Intent.EXTRA_THERMAL_STATE, thermalState); + + getContext().sendBroadcastAsUser(intent, UserHandle.ALL); + } + } + + @Override + public void onStart() { + publishBinderService(TAG, new BinderService()); + } + + private final class BinderService extends Binder { + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump thermal observer service from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (args == null || args.length == 0 || "-a".equals(args[0])) { + pw.println("Current Thermal Observer Service state:"); + pw.println(" last state change: " + + (mLastState != null ? mLastState : "none")); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } +} diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index c2284224502d0..f637c4f6af783 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -24,6 +24,7 @@ import android.content.pm.PackageManager; import android.database.ContentObserver; import android.hardware.input.InputManager; +import android.net.Uri; import android.os.BatteryStats; import android.os.Handler; import android.os.IVibratorService; @@ -55,6 +56,9 @@ import java.util.LinkedList; import java.util.ListIterator; +import cyanogenmod.hardware.CMHardwareManager; +import cyanogenmod.providers.CMSettings; + public class VibratorService extends IVibratorService.Stub implements InputManager.InputDeviceListener { private static final String TAG = "VibratorService"; @@ -86,6 +90,10 @@ public class VibratorService extends IVibratorService.Stub private int mCurVibUid = -1; private boolean mLowPowerMode; private SettingsObserver mSettingObserver; + private CMHardwareManager mHardware; + private int mMinVibratorIntensity; + private int mMaxVibratorIntensity; + private int mVibratorIntensity; native static boolean vibratorExists(); native static void vibratorOn(long milliseconds); @@ -241,9 +249,20 @@ public void onLowPowerModeChanged(boolean enabled) { @Override public void onReceive(Context context, Intent intent) { updateInputDeviceVibrators(); + updateVibratorIntensity(); } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); + mHardware = CMHardwareManager.getInstance(mContext); + if (mHardware.isSupported(CMHardwareManager.FEATURE_VIBRATOR)) { + mContext.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.VIBRATOR_INTENSITY), + true, mSettingObserver, UserHandle.USER_ALL); + mMinVibratorIntensity = mHardware.getVibratorMinIntensity(); + mMaxVibratorIntensity = mHardware.getVibratorMaxIntensity(); + updateVibratorIntensity(); + } + updateInputDeviceVibrators(); } @@ -253,11 +272,22 @@ public SettingsObserver(Handler handler) { } @Override - public void onChange(boolean SelfChange) { - updateInputDeviceVibrators(); + public void onChange(boolean selfChange, Uri uri) { + if (uri.equals(CMSettings.Secure.getUriFor(CMSettings.Secure.VIBRATOR_INTENSITY))) { + updateVibratorIntensity(); + } else { + updateInputDeviceVibrators(); + } } } + private void updateVibratorIntensity() { + mVibratorIntensity = CMSettings.Secure.getIntForUser(mContext.getContentResolver(), + CMSettings.Secure.VIBRATOR_INTENSITY, mHardware.getVibratorDefaultIntensity(), + UserHandle.USER_CURRENT); + mHardware.setVibratorIntensity(mVibratorIntensity); + } + @Override // Binder call public boolean hasVibrator() { return doVibratorExists(); diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java index 1b82ed6811ca8..3b52fce7f2815 100644 --- a/services/core/java/com/android/server/WiredAccessoryManager.java +++ b/services/core/java/com/android/server/WiredAccessoryManager.java @@ -22,6 +22,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.WakeLock; +import android.os.SystemProperties; import android.os.UEventObserver; import android.util.Slog; import android.media.AudioManager; @@ -66,6 +67,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private static final String NAME_H2W = "h2w"; private static final String NAME_USB_AUDIO = "usb_audio"; + private static final String NAME_EMU_AUDIO = "semu_audio"; private static final String NAME_SAMSUNG_USB_AUDIO = "dock"; private static final String NAME_HDMI_AUDIO = "hdmi_audio"; private static final String NAME_HDMI = "hdmi"; @@ -386,13 +388,17 @@ private List makeObservedUEventList() { Slog.w(TAG, "This kernel does not have usb audio support"); } + // Monitor Motorola EMU audio jack + uei = new UEventInfo(NAME_EMU_AUDIO, BIT_USB_HEADSET_ANLG, 0, 0); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } + // Monitor Samsung USB audio uei = new UEventInfo(NAME_SAMSUNG_USB_AUDIO, BIT_USB_HEADSET_DGTL, BIT_USB_HEADSET_ANLG, 0); if (uei.checkSwitchExists()) { retVal.add(uei); - } else { - Slog.w(TAG, "This kernel does not have samsung usb dock audio support"); } // Monitor HDMI @@ -425,6 +431,13 @@ public void onUEvent(UEventObserver.UEvent event) { try { String devPath = event.get("DEVPATH"); String name = event.get("SWITCH_NAME"); + if (SystemProperties.getBoolean("tcmd.whisper", false) && + (name.equals("CAR") || name.equals("DESK"))) { + // Motorola dock - ignore this event and don't change + // the audio routing just because we're docked. + // Let only the dock emu audio jack sensing do that. + return; + } int state = validateSwitchState(Integer.parseInt(event.get("SWITCH_STATE"))); synchronized (mLock) { updateStateLocked(devPath, name, state); diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java index be91f9831113a..81c6b0e386b50 100644 --- a/services/core/java/com/android/server/accounts/TokenCache.java +++ b/services/core/java/com/android/server/accounts/TokenCache.java @@ -125,7 +125,7 @@ protected void entryRemoved(boolean evicted, Key k, Value oldVal, Value newVal) * This is recursive, but it won't spiral out of control because LruCache is * thread safe and the Evictor can only be removed once. */ - Evictor evictor = mTokenEvictors.remove(oldVal.token); + Evictor evictor = mTokenEvictors.remove(new Pair<>(k.account.type, oldVal.token)); if (evictor != null) { evictor.evict(); } @@ -133,13 +133,15 @@ protected void entryRemoved(boolean evicted, Key k, Value oldVal, Value newVal) } public void putToken(Key k, Value v) { - // Prepare for removal by token string. - Evictor tokenEvictor = mTokenEvictors.get(v.token); + // Prepare for removal by pair of account type and token string. + Pair pair = new Pair<>(k.account.type, v.token); + + Evictor tokenEvictor = mTokenEvictors.get(pair); if (tokenEvictor == null) { tokenEvictor = new Evictor(); } tokenEvictor.add(k); - mTokenEvictors.put(new Pair<>(k.account.type, v.token), tokenEvictor); + mTokenEvictors.put(pair, tokenEvictor); // Prepare for removal by associated account. Evictor accountEvictor = mAccountEvictors.get(k.account); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 542268eb4e6aa..db3d4745c8a07 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -121,6 +121,10 @@ public final class ActiveServices { // at the same time. final int mMaxStartingBackground; + // Flag to reschedule the services during app launch. Disable by default. + private static final boolean SERVICE_RESCHEDULE + = SystemProperties.getBoolean("ro.am.reschedule_service", false); + final SparseArray mServiceMap = new SparseArray<>(); /** @@ -1229,6 +1233,14 @@ private final boolean scheduleServiceRestartLocked(ServiceRecord r, r.pendingStarts.add(0, si); long dur = SystemClock.uptimeMillis() - si.deliveredTime; dur *= 2; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"Can add more delay !!!" + +" si.deliveredTime "+si.deliveredTime + +" dur "+dur + +" si.deliveryCount "+si.deliveryCount + +" si.doneExecutingCount "+si.doneExecutingCount + +" allowCancel "+allowCancel); + } if (minDuration < dur) minDuration = dur; if (resetTime < dur) resetTime = dur; } else { @@ -1241,6 +1253,13 @@ private final boolean scheduleServiceRestartLocked(ServiceRecord r, } r.totalRestartCount++; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" allowCancel "+allowCancel); + } if (r.restartDelay == 0) { r.restartCount++; r.restartDelay = minDuration; @@ -1262,6 +1281,14 @@ private final boolean scheduleServiceRestartLocked(ServiceRecord r, } r.nextRestartTime = now + r.restartDelay; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" r.nextRestartTime "+r.nextRestartTime + +" allowCancel "+allowCancel); + } // Make sure that we don't end up restarting a bunch of services // all at the same time. @@ -1304,6 +1331,15 @@ private final boolean scheduleServiceRestartLocked(ServiceRecord r, r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " + r.shortName + " in " + r.restartDelay + "ms"); + + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + for (int i=mRestartingServices.size()-1; i>=0; i--) { + ServiceRecord r2 = mRestartingServices.get(i); + Slog.w(TAG,"Restarting list - i "+i+" r2.nextRestartTime " + +r2.nextRestartTime+" r2.name "+r2.name); + } + } + EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortName, r.restartDelay); @@ -1324,7 +1360,31 @@ final void performServiceRestartLocked(ServiceRecord r) { return; } try { - bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); + if(SERVICE_RESCHEDULE == true) { + boolean shouldDelay = false; + ActivityRecord top_rc = null; + ActivityStack stack = mAm.getFocusedStack(); + if(stack != null) { + top_rc = stack.topRunningActivityLocked(null); + } + if(top_rc != null) { + if(!top_rc.nowVisible && !r.shortName.contains(top_rc.packageName)) { + shouldDelay = true; + } + } + if(!shouldDelay) { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); + } else { + if (DEBUG_DELAYED_SERVICE) { + Slog.v(TAG, "Reschedule service restart due to app launch" + +" r.shortName "+r.shortName+" r.app = "+r.app); + } + r.resetRestartCounter(); + scheduleServiceRestartLocked(r, true); + } + } else { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); + } } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } @@ -1547,6 +1607,11 @@ private final void realStartServiceLocked(ServiceRecord r, if (newService) { app.services.remove(r); r.app = null; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG, " Failed to create Service !!!! ." + +"This will introduce huge delay... " + +r.shortName + " in " + r.restartDelay + "ms"); + } } // Retry. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b34a6ef2bd711..23f34e617be3b 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -44,6 +44,7 @@ import android.app.BroadcastOptions; import android.app.IActivityContainer; import android.app.IActivityContainerCallback; +import android.app.IActivityManager; import android.app.IAppTask; import android.app.ITaskStackListener; import android.app.ProfilerInfo; @@ -174,7 +175,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; -import android.content.pm.ThemeUtils; import android.content.pm.UserInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PathPermission; @@ -219,6 +219,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.telecom.TelecomManager; import android.text.format.DateUtils; import android.text.format.Time; import android.util.AtomicFile; @@ -265,9 +266,14 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; + +import cyanogenmod.power.PerformanceManagerInternal; + import java.util.Date; import java.text.SimpleDateFormat; +import org.cyanogenmod.internal.util.ThemeUtils; + public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { @@ -333,6 +339,11 @@ public final class ActivityManagerService extends ActivityManagerNative // before we decide it must be hung. static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000; + // How long we will retain processes hosting content providers in the "last activity" + // state before allowing them to drop down to the regular cached LRU list. This is + // to avoid thrashing of provider processes under low memory situations. + static final int CONTENT_PROVIDER_RETAIN_TIME = 20*1000; + // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was // started with a wrapper for instrumentation (such as Valgrind) because it @@ -1019,6 +1030,7 @@ private class Identity { * For example, references to the commonly used services. */ HashMap mAppBindArgs; + HashMap mIsolatedAppBindArgs; /** * Temporary to avoid allocations. Protected by main lock. @@ -1088,6 +1100,8 @@ private class Identity { */ private IVoiceInteractionSession mRunningVoice; + PerformanceManagerInternal mPerf; + /** * For some direct access we need to power manager. */ @@ -1399,6 +1413,8 @@ public void binderDied() { static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59; static final int POST_PRIVACY_NOTIFICATION_MSG = 60; static final int CANCEL_PRIVACY_NOTIFICATION_MSG = 61; + static final int POST_COMPONENT_PROTECTED_MSG = 62; + static final int CANCEL_PROTECTED_APP_NOTIFICATION = 63; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -2122,7 +2138,7 @@ public void handleMessage(Message msg) { context.getApplicationInfo().loadLabel(context.getPackageManager())); String title = mContext.getString(R.string.privacy_guard_notification); - Intent infoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Intent infoIntent = new Intent(Settings.ACTION_APP_OPS_DETAILS_SETTINGS, Uri.fromParts("package", root.packageName, null)); Notification notification = new Notification(); @@ -2167,6 +2183,92 @@ public void handleMessage(Message msg) { } catch (RemoteException e) { } } break; + case POST_COMPONENT_PROTECTED_MSG: { + INotificationManager inm = NotificationManager.getService(); + if (inm == null) { + return; + } + + Intent targetIntent = (Intent) msg.obj; + if (targetIntent == null) { + return; + } + + int targetUserId = targetIntent.getIntExtra( + "com.android.settings.PROTECTED_APPS_USER_ID", mCurrentUserId); + // Resolve for labels and whatnot + ActivityInfo root = resolveActivityInfo(targetIntent, targetIntent.getFlags(), + targetUserId); + + if (root == null) { + Slog.w(ActivityManagerService.TAG, + "No activity info found for given intent " + targetIntent.toString()); + return; + } + + try { + Intent protectedAppIntent = new Intent(); + protectedAppIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + protectedAppIntent.setComponent( + new ComponentName("com.android.settings", + "com.android.settings.applications.ProtectedAppsActivity")); + protectedAppIntent.putExtra( + "com.android.settings.PROTECTED_APP_TARGET_INTENT", + targetIntent); + Context context = mContext.createPackageContext("com.android.settings", 0); + String title = mContext.getString( + com.android.internal.R.string + .notify_package_component_protected_title); + String text = mContext.getString( + com.android.internal.R.string + .notify_package_component_protected_text, + root.applicationInfo.loadLabel(mContext.getPackageManager())); + Notification notification = new Notification.Builder(context) + .setSmallIcon(com.android.internal.R.drawable.stat_notify_protected) + .setWhen(0) + .setTicker(title) + .setColor(mContext.getColor( + com.android.internal.R.color + .system_notification_accent_color)) + .setContentTitle(title) + .setContentText(text) + .setDefaults(Notification.DEFAULT_VIBRATE) + .setPriority(Notification.PRIORITY_MAX) + .setStyle(new Notification.BigTextStyle().bigText(text)) + .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, + protectedAppIntent, PendingIntent.FLAG_CANCEL_CURRENT, null, + new UserHandle(mCurrentUserId))) + .build(); + try { + int[] outId = new int[1]; + inm.cancelNotificationWithTag("android", null, + R.string.notify_package_component_protected_title, msg.arg1); + inm.enqueueNotificationWithTag("android", "android", null, + R.string.notify_package_component_protected_title, + notification, outId, mCurrentUserId); + } catch (RuntimeException e) { + Slog.w(ActivityManagerService.TAG, + "Error showing notification for protected app component", e); + } catch (RemoteException e) { + } + } catch (NameNotFoundException e) { + Slog.w(TAG, "Unable to create context for protected app notification", e); + } + } break; + case CANCEL_PROTECTED_APP_NOTIFICATION: { + INotificationManager inm = NotificationManager.getService(); + if (inm == null) { + return; + } + try { + inm.cancelNotificationWithTag("android", null, + R.string.notify_package_component_protected_title, msg.arg1); + } catch (RuntimeException e) { + Slog.w(ActivityManagerService.TAG, + "Error canceling notification for service", e); + } catch (RemoteException e) { + } + } break; } } }; @@ -2730,18 +2832,24 @@ private Context getUiContext() { * lazily setup to make sure the services are running when they're asked for. */ private HashMap getCommonServicesLocked(boolean isolated) { + // Isolated processes won't get this optimization, so that we don't + // violate the rules about which services they have access to. + if (isolated) { + if (mIsolatedAppBindArgs == null) { + mIsolatedAppBindArgs = new HashMap<>(); + mIsolatedAppBindArgs.put("package", ServiceManager.getService("package")); + } + return mIsolatedAppBindArgs; + } + if (mAppBindArgs == null) { mAppBindArgs = new HashMap<>(); - // Isolated processes won't get this optimization, so that we don't - // violate the rules about which services they have access to. - if (!isolated) { - // Setup the application init args - mAppBindArgs.put("package", ServiceManager.getService("package")); - mAppBindArgs.put("window", ServiceManager.getService("window")); - mAppBindArgs.put(Context.ALARM_SERVICE, - ServiceManager.getService(Context.ALARM_SERVICE)); - } + // Setup the application init args + mAppBindArgs.put("package", ServiceManager.getService("package")); + mAppBindArgs.put("window", ServiceManager.getService("window")); + mAppBindArgs.put(Context.ALARM_SERVICE, + ServiceManager.getService(Context.ALARM_SERVICE)); } return mAppBindArgs; } @@ -2919,7 +3027,7 @@ final void removeLruProcessLocked(ProcessRecord app) { if (!app.killed) { Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app); Process.killProcessQuiet(app.pid); - killProcessGroup(app.info.uid, app.pid); + killProcessGroup(app.uid, app.pid); } if (lrui <= mLruProcessActivityStart) { mLruProcessActivityStart--; @@ -3294,7 +3402,7 @@ final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, // clean it up now. if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app); checkTime(startTime, "startProcess: bad proc running, killing"); - killProcessGroup(app.info.uid, app.pid); + killProcessGroup(app.uid, app.pid); handleAppDiedLocked(app, true, true); checkTime(startTime, "startProcess: done killing old proc"); } @@ -3349,6 +3457,17 @@ private final void startProcessLocked(ProcessRecord app, null /* entryPoint */, null /* entryPointArgs */); } + void launchBoost(int pid, String packageName) { + if (mPerf == null) { + mPerf = LocalServices.getService(PerformanceManagerInternal.class); + if (mPerf == null) { + Slog.e(TAG, "PerformanceManager not ready!"); + return; + } + } + mPerf.launchBoost(pid, packageName); + } + private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { long startTime = SystemClock.elapsedRealtime(); @@ -3511,6 +3630,9 @@ private final void startProcessLocked(ProcessRecord app, String hostingType, checkTime(startTime, "startProcess: building log message"); StringBuilder buf = mStringBuilder; buf.setLength(0); + if (hostingType.equals("activity")) { + launchBoost(startResult.pid, app.processName); + } buf.append("Start proc "); buf.append(startResult.pid); buf.append(':'); @@ -3535,6 +3657,18 @@ private final void startProcessLocked(ProcessRecord app, String hostingType, app.killed = false; app.killedByAm = false; checkTime(startTime, "startProcess: starting to update pids map"); + ProcessRecord oldApp; + synchronized (mPidsSelfLocked) { + oldApp = mPidsSelfLocked.get(startResult.pid); + } + // If there is already an app occupying that pid that hasn't been cleaned up + if (oldApp != null && !app.isolated) { + // Clean up anything relating to this pid first + Slog.w(TAG, "Reusing pid " + startResult.pid + + " while app is still mapped to it"); + cleanUpApplicationRecordLocked(oldApp, false, false, -1, + true /*replacingPid*/); + } synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(startResult.pid, app); if (isActivityProcess) { @@ -4689,7 +4823,8 @@ public void overridePendingTransition(IBinder token, String packageName, private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; - boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); + boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, + false /*replacingPid*/); if (!kept && !restarting) { removeLruProcessLocked(app); if (pid > 0) { @@ -4830,7 +4965,7 @@ final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread, if (!fromBinderDied) { Process.killProcessQuiet(pid); } - killProcessGroup(app.info.uid, pid); + killProcessGroup(app.uid, pid); app.killed = true; } @@ -6444,12 +6579,14 @@ void enableScreenAfterBoot() { } @Override - public void showBootMessage(final CharSequence msg, final boolean always) { + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount, final boolean always) { if (Binder.getCallingUid() != Process.myUid()) { // These days only the core system can call this, so apps can't get in // the way of what we show about running them. } - mWindowManager.showBootMessage(msg, always); + mWindowManager.updateBootProgress(stage, optimizedApp, + currentAppPos, totalAppCount, always); } @Override @@ -8514,6 +8651,14 @@ public List getTasks(int maxNum, int flags) { return list; } + @Override + public boolean isPackageInForeground(String packageName) { + synchronized (this) { + ActivityRecord activity = mStackSupervisor.topRunningActivityLocked(); + return activity != null && activity.packageName.equals(packageName); + } + } + /** * Creates a new RecentTaskInfo from a TaskRecord. */ @@ -8948,6 +9093,27 @@ private void cleanupDisabledPackageTasksLocked(String packageName, Set f } } + private void cleanupProtectedComponentTasksLocked() { + for (int i = mRecentTasks.size() - 1; i >= 0; i--) { + TaskRecord tr = mRecentTasks.get(i); + + for (int j = tr.mActivities.size() - 1; j >= 0; j--) { + ActivityRecord r = tr.mActivities.get(j); + ComponentName cn = r.realActivity; + + try { + boolean isProtected = AppGlobals.getPackageManager() + .isComponentProtected(null, -1, cn, getCurrentUserIdLocked()); + if (isProtected) { + removeTaskByIdLocked(tr.taskId, false); + } + } catch (RemoteException re) { + + } + } + } + } + /** * Removes the task with the specified task id. * @@ -9354,6 +9520,10 @@ public void stopLockTaskMode() { mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE, "stopLockTask", true); } + TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); + if (tm != null) { + tm.showInCallScreen(false); + } } finally { Binder.restoreCallingIdentity(ident); } @@ -9623,6 +9793,14 @@ boolean decProviderCountLocked(ContentProviderConnection conn, if (conn.stableCount == 0 && conn.unstableCount == 0) { cpr.connections.remove(conn); conn.client.conProviders.remove(conn); + if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { + // The client is more important than last activity -- note the time this + // is happening, so we keep the old provider process around a bit as last + // activity to avoid thrashing it. + if (cpr.proc != null) { + cpr.proc.lastProviderTime = SystemClock.uptimeMillis(); + } + } stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name); return true; } @@ -11830,8 +12008,8 @@ void go() { intent.setComponent(comp); doneReceivers.add(comp); lastRi = curRi; - CharSequence label = ai.loadLabel(mContext.getPackageManager()); - showBootMessage(mContext.getString(R.string.android_preparing_apk, label), false); + updateBootProgress(IActivityManager.BOOT_STAGE_PREPARING_APPS, + ai.applicationInfo, 0, 0, false); } Slog.i(TAG, "Pre-boot of " + intent.getComponent().toShortString() + " for user " + users[curUser]); @@ -11939,6 +12117,7 @@ public void systemReady(final Runnable goingCallback) { mRecentTasks.clear(); mRecentTasks.addAll(mTaskPersister.restoreTasksLocked()); + cleanupProtectedComponentTasksLocked(); mRecentTasks.cleanupLocked(UserHandle.USER_ALL); mTaskPersister.startPersisting(); @@ -11953,9 +12132,8 @@ public void run() { synchronized (ActivityManagerService.this) { mDidUpdate = true; } - showBootMessage(mContext.getText( - R.string.android_upgrading_complete), - false); + updateBootProgress(IActivityManager.BOOT_STAGE_COMPLETE, + null, 0, 0, false); writeLastDonePreBootReceivers(doneReceivers); systemReady(goingCallback); } @@ -12202,7 +12380,7 @@ void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) { } private void sendAppFailureBroadcast(String pkgName) { - Intent intent = new Intent(Intent.ACTION_APP_FAILURE, + Intent intent = new Intent(cyanogenmod.content.Intent.ACTION_APP_FAILURE, (pkgName != null)? Uri.fromParts("package", pkgName, null) : null); mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF); } @@ -12445,6 +12623,7 @@ private void logStrictModeViolationToDropBox( synchronized (sb) { bufferWasEmpty = sb.length() == 0; appendDropBoxProcessHeaders(process, processName, sb); + sb.append("CM Version: ").append(cyanogenmod.os.Build.CYANOGENMOD_VERSION).append("\n"); sb.append("Build: ").append(Build.FINGERPRINT).append("\n"); sb.append("System-App: ").append(isSystemApp).append("\n"); sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n"); @@ -12714,6 +12893,7 @@ public void addErrorToDropBox(String eventType, if (subject != null) { sb.append("Subject: ").append(subject).append("\n"); } + sb.append("CM Version: ").append(cyanogenmod.os.Build.CYANOGENMOD_VERSION).append("\n"); sb.append("Build: ").append(Build.FINGERPRINT).append("\n"); if (Debug.isDebuggerConnected()) { sb.append("Debugger: Connected\n"); @@ -15312,6 +15492,10 @@ final void dumpApplicationMemoryUsage(FileDescriptor fd, pw.print(" Lost RAM: "); pw.print(memInfo.getTotalSizeKb() - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb()); pw.println(" kB"); + } else { + pw.print("lostram,"); pw.println(memInfo.getTotalSizeKb() + - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() + - memInfo.getKernelUsedSizeKb()); } if (!brief) { if (memInfo.getZramTotalSizeKb() != 0) { @@ -15739,7 +15923,8 @@ private final boolean removeDyingProviderLocked(ProcessRecord proc, * app that was passed in must remain on the process lists. */ private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, - boolean restarting, boolean allowRestart, int index) { + boolean restarting, boolean allowRestart, int index, boolean replacingPid) { + Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid); if (index >= 0) { removeLruProcessLocked(app); ProcessList.remove(app.pid); @@ -15869,7 +16054,9 @@ private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, if (!app.persistent || app.isolated) { if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Removing non-persistent process during cleanup: " + app); - removeProcessNameLocked(app.processName, app.uid); + if (!replacingPid) { + removeProcessNameLocked(app.processName, app.uid); + } if (mHeavyWeightProcess == app) { mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG, mHeavyWeightProcess.userId, 0)); @@ -16276,11 +16463,22 @@ public void serviceDoneExecuting(IBinder token, int type, int startId, int res) // Cause the target app to be launched if necessary and its backup agent // instantiated. The backup agent will invoke backupAgentCreated() on the // activity manager to announce its creation. - public boolean bindBackupAgent(ApplicationInfo app, int backupMode) { - if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, - "bindBackupAgent: app=" + app + " mode=" + backupMode); + public boolean bindBackupAgent(String packageName, int backupMode, int userId) { + if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode); enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "bindBackupAgent"); + IPackageManager pm = AppGlobals.getPackageManager(); + ApplicationInfo app = null; + try { + app = pm.getApplicationInfo(packageName, 0, userId); + } catch (RemoteException e) { + // can't happen; package manager is process-local + } + if (app == null) { + Slog.w(TAG, "Unable to bind backup agent for " + packageName); + return false; + } + synchronized(this) { // !!! TODO: currently no check here that we're already bound BatteryStatsImpl.Uid.Pkg.Serv ss = null; @@ -16805,7 +17003,8 @@ private final int broadcastIntentLocked(ProcessRecord callerApp, } else if (callerApp == null || !callerApp.persistent) { try { if (AppGlobals.getPackageManager().isProtectedBroadcast( - intent.getAction())) { + intent.getAction()) && !AppGlobals.getPackageManager() + .isProtectedBroadcastAllowed(intent.getAction(), callingUid)) { String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from pid=" + callingPid + ", uid=" + callingUid; @@ -16976,6 +17175,14 @@ private final int broadcastIntentLocked(ProcessRecord callerApp, ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO); mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy)); break; + case cyanogenmod.content.Intent.ACTION_PROTECTED_CHANGED: + final boolean state = + intent.getBooleanExtra( + cyanogenmod.content.Intent.EXTRA_PROTECTED_STATE, false); + if (state == PackageManager.COMPONENT_PROTECTED_STATUS) { + cleanupProtectedComponentTasksLocked(); + } + break; } } @@ -17642,6 +17849,11 @@ boolean updateConfigurationLocked(Configuration values, !values.themeConfig.equals(mConfiguration.themeConfig)); } + if ((changes & ActivityInfo.CONFIG_THEME_FONT) != 0) { + // Notify zygote that themes need a refresh + SystemProperties.set(PROP_REFRESH_THEME, "1"); + } + mConfigurationSeq++; if (mConfigurationSeq <= 0) { mConfigurationSeq = 1; @@ -18469,6 +18681,18 @@ private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessR } } + if (app.lastProviderTime > 0 && (app.lastProviderTime+CONTENT_PROVIDER_RETAIN_TIME) > now) { + if (adj > ProcessList.PREVIOUS_APP_ADJ) { + adj = ProcessList.PREVIOUS_APP_ADJ; + schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.cached = false; + app.adjType = "provider"; + } + if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { + procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; + } + } + if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { // A client of one of our services or providers is in the top state. We // *may* want to be in the top state, but not if we are already running in @@ -19800,7 +20024,7 @@ final void trimApplications() { // Ignore exceptions. } } - cleanUpApplicationRecordLocked(app, false, true, -1); + cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/); mRemovedProcesses.remove(i); if (app.persistent) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index f48b4489d888b..f676db9779b15 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -25,6 +25,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import android.text.TextUtils; import android.util.ArraySet; import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.ReferrerIntent; @@ -271,6 +272,8 @@ static class ScheduleDestroyArgs { } private final PerformanceManagerInternal mPerf; + private static final String PROTECTED_APPS_TARGET_VALIDATION_COMPONENT = + "com.android.settings/com.android.settings.applications.ProtectedAppsActivity"; final Handler mHandler; @@ -1144,6 +1147,7 @@ private void completeResumeLocked(ActivityRecord next) { } updatePrivacyGuardNotificationLocked(next); + updateProtectedAppNotificationLocked(next); } private void setVisible(ActivityRecord r, boolean visible) { @@ -1697,10 +1701,10 @@ private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); // Some activities may want to alter the system power management - if (mStackSupervisor.mPerf != null) { - mStackSupervisor.mPerf.activityResumed(next.intent); + if (mStackSupervisor.mService.mPerf != null) { + mStackSupervisor.mService.mPerf.activityResumed(next.intent); } - + // If we are currently pausing an activity, then don't do anything // until that is done. if (!mStackSupervisor.allPausedActivitiesComplete()) { @@ -1834,8 +1838,8 @@ private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options ? AppTransition.TRANSIT_ACTIVITY_CLOSE : AppTransition.TRANSIT_TASK_CLOSE, false); if (prev.task != next.task) { - if (mStackSupervisor.mPerf != null) { - mStackSupervisor.mPerf.cpuBoost(2000 * 1000); + if (mStackSupervisor.mService.mPerf != null) { + mStackSupervisor.mService.mPerf.cpuBoost(2000 * 1000); } } } @@ -1854,8 +1858,8 @@ private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options ? AppTransition.TRANSIT_TASK_OPEN_BEHIND : AppTransition.TRANSIT_TASK_OPEN, false); if (prev.task != next.task) { - if (mStackSupervisor.mPerf != null) { - mStackSupervisor.mPerf.cpuBoost(2000 * 1000); + if (mStackSupervisor.mService.mPerf != null) { + mStackSupervisor.mService.mPerf.cpuBoost(2000 * 1000); } } } @@ -2100,6 +2104,16 @@ private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) { updateTaskMovement(task, true); } + private final void updateProtectedAppNotificationLocked(ActivityRecord next) { + ComponentName componentName = ComponentName.unflattenFromString(next.shortComponentName); + if (TextUtils.equals(componentName.flattenToString(), + PROTECTED_APPS_TARGET_VALIDATION_COMPONENT)) { + Message msg = mService.mHandler.obtainMessage( + ActivityManagerService.CANCEL_PROTECTED_APP_NOTIFICATION, next); + msg.sendToTarget(); + } + } + private final void updatePrivacyGuardNotificationLocked(ActivityRecord next) { String privacyGuardPackageName = mStackSupervisor.mPrivacyGuardPackageName; @@ -4216,7 +4230,8 @@ void getTasksLocked(List list, int callingUid, boolean allowed) if (focusedStack && topTask) { // Give the latest time to ensure foreground task can be sorted // at the first, because lastActiveTime of creating task is 0. - ci.lastActiveTime = System.currentTimeMillis(); + // Only do this if the clock didn't run backwards, though. + ci.lastActiveTime = Math.max(ci.lastActiveTime, System.currentTimeMillis()); topTask = false; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index be90dc8b1d75e..bde32e7243a6e 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -118,8 +118,6 @@ import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.WindowManagerService; -import cyanogenmod.power.PerformanceManagerInternal; - import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -276,8 +274,6 @@ public final class ActivityStackSupervisor implements DisplayListener { PowerManager mPm; - PerformanceManagerInternal mPerf; - /** * Is the privacy guard currently enabled? Shared between ActivityStacks */ @@ -354,17 +350,6 @@ public ActivityStackSupervisor(ActivityManagerService service, RecentTasks recen mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper()); } - private void launchBoost() { - if (mPerf == null) { - mPerf = LocalServices.getService(PerformanceManagerInternal.class); - } - if (mPerf == null) { - Slog.e(TAG, "PerformanceManager not ready!"); - } else { - mPerf.launchBoost(); - } - } - /** * At the time when the constructor runs, the power manager has not yet been * initialized. So we initialize our wakelocks afterwards. @@ -971,6 +956,40 @@ final int startActivityMayWait(IApplicationThread caller, int callingUid, // Cannot start a child activity if the parent is not resumed. return ActivityManager.START_CANCELED; } + + if (intent.getAction() != null && !isProvisioned()) { + switch (intent.getAction()) { + case Intent.ACTION_SEARCH: + case Intent.ACTION_WEB_SEARCH: + case Intent.ACTION_PROCESS_TEXT: + case Intent.ACTION_ASSIST: + case Intent.ACTION_VOICE_ASSIST: + Slog.w(TAG, "not starting assist intent while not provisioned"); + return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY; + } + } + try { + //TODO: This needs to be a flushed out API in the future. + boolean isProtected = intent.getComponent() != null + && AppGlobals.getPackageManager() + .isComponentProtected(callingPackage, callingUid, + intent.getComponent(), userId) && + (intent.getFlags()&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0; + + if (isProtected) { + Message msg = mService.mHandler.obtainMessage( + ActivityManagerService.POST_COMPONENT_PROTECTED_MSG); + //Store start flags, userid + intent.setFlags(startFlags); + intent.putExtra("com.android.settings.PROTECTED_APPS_USER_ID", userId); + msg.obj = intent; + mService.mHandler.sendMessage(msg); + return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY; + } + } catch (RemoteException e) { + e.printStackTrace(); + } + final int realCallingPid = Binder.getCallingPid(); final int realCallingUid = Binder.getCallingUid(); int callingPid; @@ -1451,8 +1470,6 @@ final int startActivityLocked(IApplicationThread caller, Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) : (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY : container.mActivityDisplay.mDisplayId))); - /* Acquire perf lock during new app launch */ - launchBoost(); } ActivityRecord sourceRecord = null; @@ -1869,6 +1886,29 @@ final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord so inTask = null; } + try { + //TODO: This needs to be a flushed out API in the future. + boolean isProtected = intent.getComponent() != null + && AppGlobals.getPackageManager() + .isComponentProtected(sourceRecord == null ? "android" : + sourceRecord.launchedFromPackage, r.launchedFromUid, + intent.getComponent(), r.userId) && + (intent.getFlags()&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0; + + if (isProtected && r.state == INITIALIZING) { + Message msg = mService.mHandler.obtainMessage( + ActivityManagerService.POST_COMPONENT_PROTECTED_MSG); + //Store start flags, userid + intent.setFlags(startFlags); + intent.putExtra("com.android.settings.PROTECTED_APPS_USER_ID", r.userId); + msg.obj = intent; + mService.mHandler.sendMessage(msg); + return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY; + } + } catch (RemoteException e) { + e.printStackTrace(); + } + final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP; final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE; final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK; @@ -2805,7 +2845,7 @@ void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options, Str ActivityRecord top = task.stack.topRunningActivityLocked(null); /* App is launching from recent apps and it's a new process */ if(top != null && top.state == ActivityState.DESTROYED) { - launchBoost(); + mService.launchBoost(-1, top.packageName); } if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) { @@ -3090,15 +3130,15 @@ ActivityRecord findTaskLocked(ActivityRecord r) { final ActivityRecord ar = stack.findTaskLocked(r); if (ar != null) { if (ar.state == ActivityState.DESTROYED) { - launchBoost(); + mService.launchBoost(-1, r.packageName); } return ar; } } } - if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found"); - launchBoost(); + mService.launchBoost(-1, r.packageName); + if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found"); return null; } @@ -3907,7 +3947,9 @@ void removeLockedTaskLocked(final TaskRecord task) { } void showLockTaskToast() { - mLockTaskNotify.showToast(mLockTaskModeState); + if (mLockTaskNotify != null) { + mLockTaskNotify.showToast(mLockTaskModeState); + } } void showLockTaskEscapeMessageLocked(TaskRecord task) { @@ -4646,4 +4688,9 @@ private boolean isLeanbackOnlyDevice() { return onLeanbackOnly; } + + private boolean isProvisioned() { + return Settings.Global.getInt(mService.mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 0) == 1; + } } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 62768c3b6475d..5fd3510683bf1 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006-2007 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +51,8 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; +import com.android.internal.os.DockBatteryStatsImpl; + import com.android.internal.os.PowerProfile; import com.android.server.FgThread; import com.android.server.LocalServices; @@ -75,6 +78,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub static IBatteryStats sService; final BatteryStatsImpl mStats; + // The dock stats only collect statistics about battery (no wakelocks, no counters, ...), + // just the dock battery history + final DockBatteryStatsImpl mDockStats; final BatteryStatsHandler mHandler; Context mContext; PowerManagerInternal mPowerManagerInternal; @@ -167,6 +173,7 @@ private void scheduleSyncLocked(String reason, int updateFlags) { // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through. mStats = new BatteryStatsImpl(systemDir, handler, mHandler); + mDockStats = new DockBatteryStatsImpl(systemDir, handler, mHandler); } public void publish(Context context) { @@ -196,6 +203,9 @@ public void shutdown() { synchronized (mStats) { mStats.shutdownLocked(); } + synchronized (mDockStats) { + mDockStats.shutdownLocked(); + } } public static IBatteryStats getService() { @@ -231,6 +241,16 @@ public void scheduleWriteToDisk() { mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK); } + /** + * @return the current dock statistics object, which may be modified + * to reflect events that affect battery usage. You must lock the + * stats object before doing anything with it. + * @hide + */ + public BatteryStatsImpl getActiveDockStatistics() { + return mDockStats; + } + // These are for direct use by the activity manager... /** @@ -327,6 +347,48 @@ public boolean isCharging() { } } + /** @hide */ + public byte[] getDockStatistics() { + mContext.enforceCallingPermission( + android.Manifest.permission.BATTERY_STATS, null); + //Slog.i("foo", "SENDING DOCK BATTERY INFO:"); + //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); + Parcel out = Parcel.obtain(); + mDockStats.writeToParcel(out, 0); + byte[] data = out.marshall(); + out.recycle(); + return data; + } + + /** @hide */ + public ParcelFileDescriptor getDockStatisticsStream() { + mContext.enforceCallingPermission( + android.Manifest.permission.BATTERY_STATS, null); + //Slog.i("foo", "SENDING DOCK BATTERY INFO:"); + //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); + Parcel out = Parcel.obtain(); + mDockStats.writeToParcel(out, 0); + byte[] data = out.marshall(); + out.recycle(); + try { + return ParcelFileDescriptor.fromData(data, "dock-battery-stats"); + } catch (IOException e) { + Slog.w(TAG, "Unable to create shared memory", e); + return null; + } + } + + public void resetStatistics() { + mContext.enforceCallingPermission( + android.Manifest.permission.RESET_BATTERY_STATS, null); + synchronized (mStats) { + mStats.resetAllStatsCmdLocked(); + } + synchronized (mDockStats) { + mDockStats.resetAllStatsCmdLocked(); + } + } + public long computeBatteryTimeRemaining() { synchronized (mStats) { long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); @@ -901,6 +963,31 @@ public long getAwakeTimePlugged() { return mStats.getAwakeTimePlugged(); } + /** @hide */ + public boolean isOnDockBattery() { + return mDockStats.isOnBattery(); + } + + /** @hide */ + public void setDockBatteryState(int status, int health, int plugType, int level, + int temp, int volt) { + enforceCallingPermission(); + mDockStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); + } + + /** @hide */ + public long getAwakeTimeDockBattery() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.BATTERY_STATS, null); + return mDockStats.getAwakeTimeBattery(); + } + + public long getAwakeTimeDockPlugged() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.BATTERY_STATS, null); + return mDockStats.getAwakeTimePlugged(); + } + public void enforceCallingPermission() { if (Binder.getCallingPid() == Process.myPid()) { return; @@ -1065,6 +1152,7 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { } else if ("--reset".equals(arg)) { synchronized (mStats) { mStats.resetAllStatsCmdLocked(); + mDockStats.resetAllStatsCmdLocked(); pw.println("Battery stats reset."); noOutput = true; } @@ -1073,6 +1161,7 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { updateExternalStats("dump", UPDATE_ALL); synchronized (mStats) { mStats.writeSyncLocked(); + mDockStats.writeSyncLocked(); pw.println("Battery stats written."); noOutput = true; } @@ -1176,19 +1265,44 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mStats.mCheckinFile.getBaseFile(), e); } } + if (mDockStats.mCheckinFile.exists()) { + try { + byte[] raw = mDockStats.mCheckinFile.readFully(); + if (raw != null) { + Parcel in = Parcel.obtain(); + in.unmarshall(raw, 0, raw.length); + in.setDataPosition(0); + DockBatteryStatsImpl checkinStats = new DockBatteryStatsImpl( + null, mStats.mHandler, null); + checkinStats.readSummaryFromParcel(in); + in.recycle(); + checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, + historyStart); + mDockStats.mCheckinFile.delete(); + return; + } + } catch (IOException e) { + Slog.w(TAG, "Failure reading dock checkin file " + + mDockStats.mCheckinFile.getBaseFile(), e); + } + } } } synchronized (mStats) { mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); + mDockStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); if (writeData) { mStats.writeAsyncLocked(); + mDockStats.writeAsyncLocked(); } } } else { synchronized (mStats) { mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); + mDockStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); if (writeData) { mStats.writeAsyncLocked(); + mDockStats.writeAsyncLocked(); } } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 589a4b8555851..e7fec1944c63f 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -297,6 +297,11 @@ public boolean sendPendingBroadcastsLocked(ProcessRecord app) { boolean didSomething = false; final BroadcastRecord br = mPendingBroadcast; if (br != null && br.curApp.pid == app.pid) { + if (br.curApp != app) { + Slog.e(TAG, "App mismatch when sending pending broadcast to " + + app.processName + ", intended target is " + br.curApp.processName); + return false; + } try { mPendingBroadcast = null; processCurBroadcastLocked(br, app); diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java index d1917db4be8c3..a5d37f01622d4 100644 --- a/services/core/java/com/android/server/am/LockTaskNotify.java +++ b/services/core/java/com/android/server/am/LockTaskNotify.java @@ -21,13 +21,13 @@ import android.os.Handler; import android.os.Message; import android.os.RemoteException; -import android.view.IWindowManager; +import android.os.UserHandle; import android.view.WindowManager; -import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; import com.android.internal.R; +import cyanogenmod.providers.CMSettings; /** * Helper to manage showing/hiding a image to notify them that they are entering @@ -40,23 +40,19 @@ public class LockTaskNotify { private final H mHandler; private AccessibilityManager mAccessibilityManager; private Toast mLastToast; - private final IWindowManager mWindowManagerService; public LockTaskNotify(Context context) { mContext = context; mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); mHandler = new H(); - mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); } private boolean hasNavigationBar() { - try { - return mWindowManagerService.hasNavigationBar(); - } catch (RemoteException e) { - //ignore - } - return false; + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_showNavigationBar) + || CMSettings.Global.getIntForUser(mContext.getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; } public void showToast(int lockTaskModeState) { @@ -67,9 +63,9 @@ public void handleShowToast(int lockTaskModeState) { final int textResId; if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) { textResId = R.string.lock_to_app_toast_locked; - } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED) { - textResId = mAccessibilityManager.isEnabled() - ? R.string.lock_to_app_toast_accessible : R.string.lock_to_app_toast; + } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED && + mAccessibilityManager.isEnabled() && hasNavigationBar()) { + textResId = R.string.lock_to_app_toast_accessible; } else { textResId = hasNavigationBar() ? R.string.lock_to_app_toast : R.string.lock_to_app_toast_no_navbar; diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 9c9a42127a3f4..4def2fb9ceed7 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -260,8 +260,8 @@ private void updateOomLevels(int displayWidth, int displayHeight, boolean write) int maxSize = 1280*800; // 1024000 230400 870400 .264 float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize); if (false) { - Slog.i("XXXXXX", "scaleMem=" + scaleMem); - Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + Slog.i(TAG, "scaleMem=" + scaleMem); + Slog.i(TAG, "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight); } @@ -273,7 +273,7 @@ private void updateOomLevels(int displayWidth, int displayHeight, boolean write) int minfree_abs = Resources.getSystem().getInteger( com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute); if (false) { - Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs); + Slog.i(TAG, "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs); } // We've now baked in the increase to the basic oom values above, since @@ -286,12 +286,12 @@ private void updateOomLevels(int displayWidth, int displayHeight, boolean write) int low = mOomMinFreeLow[i]; int high = mOomMinFreeHigh[i]; if (is64bit) { - Slog.i("XXXXXX", "choosing minFree values for 64 Bit"); + Slog.i(TAG, "choosing minFree values for 64 Bit"); // Increase the high min-free levels for cached processes for 64-bit if (i == 4) high = (high*3)/2; else if (i == 5) high = (high*7)/4; } else { - Slog.i("XXXXXX", "choosing minFree values for 32 Bit"); + Slog.i(TAG, "choosing minFree values for 32 Bit"); low = mOomMinFreeLow32Bit[i]; high = mOomMinFreeHigh32Bit[i]; } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 9cab95bfad9be..30f2c3ef7f650 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -136,6 +136,7 @@ final class ProcessRecord { long curCpuTime; // How long proc has run CPU most recently long lastRequestedGc; // When we last asked the app to do a gc long lastLowMemory; // When we last told the app that memory is low + long lastProviderTime; // The last time someone else was using a provider in this process. boolean reportLowMemory; // Set to true when waiting to report low mem boolean empty; // Is this an empty background process? boolean cached; // Is this a cached process? @@ -317,6 +318,11 @@ void dump(PrintWriter pw, String prefix) { pw.print(" foregroundActivities="); pw.print(foregroundActivities); pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")"); } + if (lastProviderTime > 0) { + pw.print(prefix); pw.print("lastProviderTime="); + TimeUtils.formatDuration(lastProviderTime, now, pw); + pw.println(); + } if (hasStartedServices) { pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices); } @@ -572,7 +578,7 @@ void kill(String reason, boolean noisy) { } EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason); Process.killProcessQuiet(pid); - Process.killProcessGroup(info.uid, pid); + Process.killProcessGroup(uid, pid); if (!persistent) { killed = true; killedByAm = true; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c7e08bbb9a550..fe3df610e952d 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -35,6 +35,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; +import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -126,6 +127,8 @@ import java.util.NoSuchElementException; import java.util.Objects; +import cyanogenmod.providers.CMSettings; + /** * The implementation of the volume manager service. *

@@ -583,11 +586,14 @@ private String makeDeviceListKey(int device, String deviceAddress) { // If absolute volume is supported in AVRCP device private boolean mAvrcpAbsVolSupported = false; + private boolean mLinkNotificationWithVolume; + private final boolean mVoiceCapable; private static Long mLastDeviceConnectMsgTime = new Long(0); private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate; private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT; private long mLoweredFromNormalToVibrateTime; + private boolean mVolumeKeysControlRingStream; // Intent "extra" data keys. public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName"; @@ -640,6 +646,9 @@ public AudioService(Context context) { mForcedUseForComm = AudioSystem.FORCE_NONE; + mVoiceCapable = context.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable); + createAudioSystemThread(); AudioSystem.setErrorCallback(mAudioSystemCallback); @@ -671,6 +680,10 @@ public AudioService(Context context) { mForceAnalogCarDock = mContext.getResources().getBoolean( com.android.internal.R.bool.config_forceAnalogCarDock); + // read this in before readPersistedSettings() because updateStreamVolumeAlias needs it + mLinkNotificationWithVolume = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1; + // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] // array initialized by updateStreamVolumeAlias() updateStreamVolumeAlias(false /*updateVolumes*/, TAG); @@ -701,6 +714,7 @@ public AudioService(Context context) { intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + intentFilter.addAction(Intent.ACTION_SHUTDOWN); // TODO merge orientation and rotation mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); if (mMonitorOrientation) { @@ -897,59 +911,63 @@ private void waitForAudioHandlerCreation() { * @hide */ public void addMediaPlayerAndUpdateRemoteController (String packageName) { - Log.v(TAG, "addMediaPlayerAndUpdateRemoteController: size of existing list: " + - mMediaPlayers.size()); - boolean playerToAdd = true; - if (mMediaPlayers.size() > 0) { - final Iterator rccIterator = mMediaPlayers.iterator(); - while (rccIterator.hasNext()) { - final MediaPlayerInfo player = rccIterator.next(); - if (packageName.equals(player.getPackageName())) { - Log.e(TAG, "Player entry present, no need to add"); - playerToAdd = false; - player.setFocus(true); - } else { - Log.e(TAG, "Player: " + player.getPackageName()+ "Lost Focus"); - player.setFocus(false); + synchronized(mMediaPlayers) { + Log.v(TAG, "addMediaPlayerAndUpdateRemoteController: size of existing list: " + + mMediaPlayers.size()); + boolean playerToAdd = true; + if (mMediaPlayers.size() > 0) { + final Iterator rccIterator = mMediaPlayers.iterator(); + while (rccIterator.hasNext()) { + final MediaPlayerInfo player = rccIterator.next(); + if (packageName.equals(player.getPackageName())) { + Log.e(TAG, "Player entry present, no need to add"); + playerToAdd = false; + player.setFocus(true); + } else { + Log.e(TAG, "Player: " + player.getPackageName()+ "Lost Focus"); + player.setFocus(false); + } } } + if (playerToAdd) { + Log.e(TAG, "Adding Player: " + packageName + " to available player list"); + mMediaPlayers.add(new MediaPlayerInfo(packageName, true)); + } + Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); + intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, true); + intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); + sendBroadcastToAll(intent); + Log.v(TAG, "updating focussed RCC change to RCD: CallingPackageName:" + + packageName); } - if (playerToAdd) { - Log.e(TAG, "Adding Player: " + packageName + " to available player list"); - mMediaPlayers.add(new MediaPlayerInfo(packageName, true)); - } - Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); - intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, true); - intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); - sendBroadcastToAll(intent); - Log.v(TAG, "updating focussed RCC change to RCD: CallingPackageName:" - + packageName); } /** * @hide */ public void updateRemoteControllerOnExistingMediaPlayers() { - Log.v(TAG, "updateRemoteControllerOnExistingMediaPlayers: size of Player list: " + + synchronized(mMediaPlayers) { + Log.v(TAG, "updateRemoteControllerOnExistingMediaPlayers: size of Player list: " + mMediaPlayers.size()); - if (mMediaPlayers.size() > 0) { - Log.v(TAG, "Inform RemoteController regarding existing RCC entry"); - final Iterator rccIterator = mMediaPlayers.iterator(); - while (rccIterator.hasNext()) { - final MediaPlayerInfo player = rccIterator.next(); - Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, - player.getPackageName()); - intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, - player.isFocussed()); - intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); - sendBroadcastToAll(intent); - Log.v(TAG, "updating RCC change: CallingPackageName:" + - player.getPackageName()); + if (mMediaPlayers.size() > 0) { + Log.v(TAG, "Inform RemoteController regarding existing RCC entry"); + final Iterator rccIterator = mMediaPlayers.iterator(); + while (rccIterator.hasNext()) { + final MediaPlayerInfo player = rccIterator.next(); + Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, + player.getPackageName()); + intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, + player.isFocussed()); + intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); + sendBroadcastToAll(intent); + Log.v(TAG, "updating RCC change: CallingPackageName:" + + player.getPackageName()); + } + } else { + Log.e(TAG, "No RCC entry present to update"); } - } else { - Log.e(TAG, "No RCC entry present to update"); } } @@ -957,34 +975,36 @@ public void updateRemoteControllerOnExistingMediaPlayers() { * @hide */ public void removeMediaPlayerAndUpdateRemoteController (String packageName) { - Log.v(TAG, "removeMediaPlayerAndUpdateRemoteController: size of existing list: " + - mMediaPlayers.size()); - boolean playerToRemove = false; - int index = -1; - if (mMediaPlayers.size() > 0) { - final Iterator rccIterator = mMediaPlayers.iterator(); - while (rccIterator.hasNext()) { - index++; - final MediaPlayerInfo player = rccIterator.next(); - if (packageName.equals(player.getPackageName())) { - Log.v(TAG, "Player entry present remove and update RemoteController"); - playerToRemove = true; - break; - } else { - Log.v(TAG, "Player entry for " + player.getPackageName()+ " is not present"); + synchronized(mMediaPlayers) { + Log.v(TAG, "removeMediaPlayerAndUpdateRemoteController: size of existing list: " + + mMediaPlayers.size()); + boolean playerToRemove = false; + int index = -1; + if (mMediaPlayers.size() > 0) { + final Iterator rccIterator = mMediaPlayers.iterator(); + while (rccIterator.hasNext()) { + index++; + final MediaPlayerInfo player = rccIterator.next(); + if (packageName.equals(player.getPackageName())) { + Log.v(TAG, "Player entry present remove and update RemoteController"); + playerToRemove = true; + break; + } else { + Log.v(TAG, "Player entry for " + player.getPackageName()+ " is not present"); + } } } + if (playerToRemove) { + Log.e(TAG, "Removing Player: " + packageName + " from index" + index); + mMediaPlayers.remove(index); + } + Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); + intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, false); + intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, false); + sendBroadcastToAll(intent); + Log.v(TAG, "Updated List size: " + mMediaPlayers.size()); } - if (playerToRemove) { - Log.e(TAG, "Removing Player: " + packageName + " from index" + index); - mMediaPlayers.remove(index); - } - Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); - intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, false); - intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, false); - sendBroadcastToAll(intent); - Log.v(TAG, "Updated List size: " + mMediaPlayers.size()); } private void checkAllAliasStreamVolumes() { @@ -1080,6 +1100,13 @@ private void updateStreamVolumeAlias(boolean updateVolumes, String caller) { } mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; + + if (mLinkNotificationWithVolume && mVoiceCapable) { + mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; + } else { + mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION; + } + if (updateVolumes) { mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias], caller); @@ -1150,8 +1177,15 @@ private void readPersistedSettings() { updateRingerModeAffectedStreams(); readDockAudioSettings(cr); + + mVolumeKeysControlRingStream = CMSettings.System.getIntForUser(cr, + CMSettings.System.VOLUME_KEYS_CONTROL_RING_STREAM, 1, + UserHandle.USER_CURRENT) == 1; } + mLinkNotificationWithVolume = Settings.Secure.getInt(cr, + Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1; + mMuteAffectedStreams = System.getIntForUser(cr, System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED, UserHandle.USER_CURRENT); @@ -3588,10 +3622,16 @@ private int getActiveStreamType(int suggestedStreamType) { if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); return AudioSystem.STREAM_MUSIC; - } else { + } else { + if (mVolumeKeysControlRingStream) { if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); return AudioSystem.STREAM_RING; + } else { + if (DEBUG_VOL) + Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC b/c default"); + return AudioSystem.STREAM_MUSIC; + } } } else if (isAfMusicActiveRecently(0)) { if (DEBUG_VOL) @@ -3626,9 +3666,16 @@ private int getActiveStreamType(int suggestedStreamType) { if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); return AudioSystem.STREAM_MUSIC; } else { - if (DEBUG_VOL) Log.v(TAG, - "getActiveStreamType: using STREAM_NOTIFICATION as default"); - return AudioSystem.STREAM_NOTIFICATION; + if (mVolumeKeysControlRingStream) { + if (DEBUG_VOL) + Log.v(TAG, + "getActiveStreamType: using STREAM_NOTIFICATION as default"); + return AudioSystem.STREAM_NOTIFICATION; + } else { + if (DEBUG_VOL) + Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC b/c default"); + return AudioSystem.STREAM_MUSIC; + } } } break; @@ -3962,8 +4009,29 @@ public void applyDeviceVolume_syncVSS(int device) { int index; if (mIsMuted) { index = 0; - } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) - || ((device & mFullVolumeDevices) != 0)) { + } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) { + /* Special handling for Bluetooth Absolute Volume scenario + * If we send full audio gain, some accessories are too loud even at its lowest + * volume. We are not able to enumerate all such accessories, so here is the + * workaround from phone side. + * For the lowest volume steps 1 and 2, restrict audio gain to 50% and 75%. + * For volume step 0, set audio gain to 0 as some accessories won't mute on their end. + */ + int i = (getIndex(device) + 5)/10; + if (i == 0) { + // 0% for volume 0 + index = 0; + } else if (i == 1) { + // 50% for volume 1 + index = (int)(mIndexMax * 0.5) /10; + } else if (i == 2) { + // 75% for volume 2 + index = (int)(mIndexMax * 0.75) /10; + } else { + // otherwise, full gain + index = (mIndexMax + 5)/10; + } + } else if ((device & mFullVolumeDevices) != 0) { index = (mIndexMax + 5)/10; } else { index = (getIndex(device) + 5)/10; @@ -4587,7 +4655,11 @@ public void handleMessage(Message msg) { break; case MSG_PLAY_SOUND_EFFECT: - onPlaySoundEffect(msg.arg1, msg.arg2); + if (isStreamMute(AudioSystem.STREAM_SYSTEM)) { + Log.d(TAG, "Stream muted, skip playback"); + } else { + onPlaySoundEffect(msg.arg1, msg.arg2); + } break; case MSG_BTA2DP_DOCK_TIMEOUT: @@ -4705,6 +4777,10 @@ private class SettingsObserver extends ContentObserver { Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); mContentResolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); + mContentResolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.VOLUME_LINK_NOTIFICATION), false, this); + mContentResolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.VOLUME_KEYS_CONTROL_RING_STREAM), false, this); } @Override @@ -4723,6 +4799,17 @@ public void onChange(boolean selfChange) { setRingerModeInt(getRingerModeInternal(), false); } readDockAudioSettings(mContentResolver); + + boolean linkNotificationWithVolume = Settings.Secure.getInt(mContentResolver, + Settings.Secure.VOLUME_LINK_NOTIFICATION, 1) == 1; + if (linkNotificationWithVolume != mLinkNotificationWithVolume) { + mLinkNotificationWithVolume = linkNotificationWithVolume; + createStreamStates(); + updateStreamVolumeAlias(true, TAG); + } + mVolumeKeysControlRingStream = CMSettings.System.getIntForUser(mContentResolver, + CMSettings.System.VOLUME_KEYS_CONTROL_RING_STREAM, 1, + UserHandle.USER_CURRENT) == 1; } } } @@ -5029,12 +5116,18 @@ private void sendDeviceConnectionIntent(int device, int state, String address, connType = AudioRoutesInfo.MAIN_HEADSET; intent.setAction(Intent.ACTION_HEADSET_PLUG); intent.putExtra("microphone", 1); + if (state == 1) { + startMusicPlayer(); + } } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE || device == AudioSystem.DEVICE_OUT_LINE) { /*do apps care about line-out vs headphones?*/ connType = AudioRoutesInfo.MAIN_HEADPHONES; intent.setAction(Intent.ACTION_HEADSET_PLUG); intent.putExtra("microphone", 0); + if (state == 1) { + startMusicPlayer(); + } } else if (device == AudioSystem.DEVICE_OUT_HDMI || device == AudioSystem.DEVICE_OUT_HDMI_ARC) { connType = AudioRoutesInfo.MAIN_HDMI; @@ -5067,6 +5160,23 @@ private void sendDeviceConnectionIntent(int device, int state, String address, } } + private void startMusicPlayer() { + boolean launchPlayer = CMSettings.System.getIntForUser(mContext.getContentResolver(), + CMSettings.System.HEADSET_CONNECT_PLAYER, 0, UserHandle.USER_CURRENT) != 0; + TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); + + if (launchPlayer && !tm.isInCall()) { + try { + Intent playerIntent = new Intent(Intent.ACTION_MAIN); + playerIntent.addCategory(Intent.CATEGORY_APP_MUSIC); + playerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(playerIntent); + } catch (ActivityNotFoundException | IllegalArgumentException e) { + Log.w(TAG, "No music player Activity could be found"); + } + } + } + private void onSetWiredDeviceConnectionState(int device, int state, String address, String deviceName, String caller) { if (DEBUG_DEVICES) { @@ -5324,6 +5434,8 @@ public void onReceive(Context context, Intent intent) { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); UserManagerService.getInstance().setSystemControlledUserRestriction( UserManager.DISALLOW_RECORD_AUDIO, false, userId); + } else if (action.equals(Intent.ACTION_SHUTDOWN)) { + AudioSystem.setParameters("dev_shutdown=true"); } } } // end class AudioServiceBroadcastReceiver diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 7d1da01b8ca6a..58c76ec7674a9 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -27,6 +27,7 @@ import android.net.ProxyInfo; import android.net.Uri; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -39,10 +40,10 @@ import com.android.net.IProxyCallback; import com.android.net.IProxyPortListener; import com.android.net.IProxyService; -import com.android.server.IoThread; import libcore.io.Streams; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.net.URLConnection; @@ -66,6 +67,7 @@ public class PacManager { private static final int DELAY_1 = 0; private static final int DELAY_4 = 3; private static final int DELAY_LONG = 4; + private static final long MAX_PAC_SIZE = 20 * 1000 * 1000; /** Keep these values up-to-date with ProxyService.java */ public static final String KEY_PROXY = "keyProxy"; @@ -123,15 +125,21 @@ public void run() { } }; + private final HandlerThread mNetThread = new HandlerThread("android.pacmanager", + android.os.Process.THREAD_PRIORITY_DEFAULT); + private final Handler mNetThreadHandler; + class PacRefreshIntentReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { - IoThread.getHandler().post(mPacDownloader); + mNetThreadHandler.post(mPacDownloader); } } public PacManager(Context context, Handler handler, int proxyMessage) { mContext = context; mLastPort = -1; + mNetThread.start(); + mNetThreadHandler = new Handler(mNetThread.getLooper()); mPacRefreshIntent = PendingIntent.getBroadcast( context, 0, new Intent(ACTION_PAC_REFRESH), 0); @@ -199,7 +207,25 @@ public synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) { private static String get(Uri pacUri) throws IOException { URL url = new URL(pacUri.toString()); URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY); - return new String(Streams.readFully(urlConnection.getInputStream())); + long contentLength = -1; + try { + contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length")); + } catch (NumberFormatException e) { + // Ignore + } + if (contentLength > MAX_PAC_SIZE) { + throw new IOException("PAC too big: " + contentLength + " bytes"); + } + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count; + while ((count = urlConnection.getInputStream().read(buffer)) != -1) { + bytes.write(buffer, 0, count); + if (bytes.size() > MAX_PAC_SIZE) { + throw new IOException("PAC too big"); + } + } + return bytes.toString(); } private int getNextDelay(int currentDelay) { @@ -267,7 +293,7 @@ private void bind() { intent.setClassName(PAC_PACKAGE, PAC_SERVICE); if ((mProxyConnection != null) && (mConnection != null)) { // Already bound no need to bind again, just download the new file. - IoThread.getHandler().post(mPacDownloader); + mNetThreadHandler.post(mPacDownloader); return; } mConnection = new ServiceConnection() { @@ -297,7 +323,7 @@ public void onServiceConnected(ComponentName component, IBinder binder) { } catch (RemoteException e) { Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e); } - IoThread.getHandler().post(mPacDownloader); + mNetThreadHandler.post(mPacDownloader); } } } diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 9ead529b22ea0..60d677208c82b 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -36,8 +36,11 @@ import android.net.NetworkInfo; import android.net.NetworkUtils; import android.net.RouteInfo; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiDevice; +import android.net.wifi.WifiManager; import android.os.Binder; +import android.os.Handler; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; @@ -56,6 +59,7 @@ import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.IoThread; +import com.android.server.NetPluginDelegate; import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; @@ -164,12 +168,16 @@ public class Tethering extends BaseNetworkObserver { private static final int DNSMASQ_POLLING_INTERVAL = 1000; private static final int DNSMASQ_POLLING_MAX_TIMES = 10; + private long mWiFiApInactivityTimeout; + private final Handler mHandler; + public Tethering(Context context, INetworkManagementService nmService, INetworkStatsService statsService, Looper looper) { mContext = context; mNMService = nmService; mStatsService = statsService; mLooper = looper; + mHandler = new Handler(mLooper); mPublicSync = new Object(); @@ -269,6 +277,18 @@ public void interfaceStatusChanged(String iface, boolean up) { sm = new TetherInterfaceSM(iface, mLooper, usb); mIfaces.put(iface, sm); sm.start(); + if (isWifi(iface)) { + // check if the user has specified an inactivity timeout for wifi AP and + // if so schedule the timeout + final WifiManager wm = + (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + final WifiConfiguration apConfig = wm.getWifiApConfiguration(); + mWiFiApInactivityTimeout = + apConfig != null ? apConfig.wifiApInactivityTimeout : 0; + if (mWiFiApInactivityTimeout > 0 && mL2ConnectedDeviceMap.size() == 0) { + scheduleInactivityTimeout(); + } + } } } else { if (isUsb(iface)) { @@ -278,6 +298,9 @@ public void interfaceStatusChanged(String iface, boolean up) { } else if (sm != null) { sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); mIfaces.remove(iface); + if (isWifi(iface)) { + cancelInactivityTimeout(); + } } } } @@ -388,8 +411,6 @@ private void sendTetherConnectStateChangedBroadcast() { Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); - - showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi); } private boolean readDeviceInfoFromDnsmasq(WifiDevice device) { @@ -430,6 +451,29 @@ private boolean readDeviceInfoFromDnsmasq(WifiDevice device) { return result; } + private final Runnable mDisableWifiApRunnable = new Runnable() { + @Override + public void run() { + if (VDBG) Log.d(TAG, "Turning off hotpost due to inactivity"); + final WifiManager wifiManager = + (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + wifiManager.setWifiApEnabled(null, false); + } + }; + + private void scheduleInactivityTimeout() { + if (mWiFiApInactivityTimeout > 0) { + if (VDBG) Log.d(TAG, "scheduleInactivityTimeout: " + mWiFiApInactivityTimeout); + mHandler.removeCallbacks(mDisableWifiApRunnable); + mHandler.postDelayed(mDisableWifiApRunnable, mWiFiApInactivityTimeout); + } + } + + private void cancelInactivityTimeout() { + if (VDBG) Log.d(TAG, "cancelInactivityTimeout"); + mHandler.removeCallbacks(mDisableWifiApRunnable); + } + /* * DnsmasqThread is used to read the Device info from dnsmasq. */ @@ -513,10 +557,15 @@ public void interfaceMessageRecevied(String message) { new DnsmasqThread(this, device, DNSMASQ_POLLING_INTERVAL, DNSMASQ_POLLING_MAX_TIMES).start(); } + cancelInactivityTimeout(); } else if (device.deviceState == WifiDevice.DISCONNECTED) { mL2ConnectedDeviceMap.remove(device.deviceAddress); mConnectedDeviceMap.remove(device.deviceAddress); sendTetherConnectStateChangedBroadcast(); + // schedule inactivity timeout if non-zero and no more devices are connected + if (mWiFiApInactivityTimeout > 0 && mL2ConnectedDeviceMap.size() == 0) { + scheduleInactivityTimeout(); + } } } catch (IllegalArgumentException ex) { Log.e(TAG, "WifiDevice IllegalArgument: " + ex); @@ -650,7 +699,12 @@ private void showTetheredNotification(int icon) { if (mLastNotificationId != 0) { if (mLastNotificationId == icon) { - return; + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_softap_extention) + || icon != com.android.internal.R.drawable.stat_sys_tether_wifi) { + // if softap extension feature is on, allow to update icon else return. + return; + } } notificationManager.cancelAsUser(null, mLastNotificationId, UserHandle.ALL); @@ -666,24 +720,8 @@ private void showTetheredNotification(int icon) { Resources r = Resources.getSystem(); CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); - - CharSequence message; - int size = mConnectedDeviceMap.size(); - - if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_softap_extention) - && icon == com.android.internal.R.drawable.stat_sys_tether_wifi) { - if (size == 0) { - message = r.getText(com.android.internal.R.string.tethered_notification_no_device_message); - } else if (size == 1) { - message = String.format((r.getText(com.android.internal.R.string.tethered_notification_one_device_message)).toString(), - size); - } else { - message = String.format((r.getText(com.android.internal.R.string.tethered_notification_multi_device_message)).toString(), - size); - } - } else { - message = r.getText(com.android.internal.R.string.tethered_notification_message); - } + CharSequence message = r.getText(com.android.internal.R.string. + tethered_notification_message); if (mTetheredNotificationBuilder == null) { mTetheredNotificationBuilder = new Notification.Builder(mContext); @@ -698,18 +736,10 @@ private void showTetheredNotification(int icon) { .setContentTitle(title) .setContentText(message) .setContentIntent(pi); - if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_softap_extention) - && icon == com.android.internal.R.drawable.stat_sys_tether_wifi - && size > 0) { - mTetheredNotificationBuilder.setContentText(message); - } else { - mTetheredNotificationBuilder.setContentTitle(title); - } mLastNotificationId = icon; notificationManager.notifyAsUser(null, mLastNotificationId, mTetheredNotificationBuilder.build(), UserHandle.ALL); - } private void clearTetheredNotification() { @@ -1566,6 +1596,8 @@ protected void chooseUpstreamType(boolean tryCell) { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); } } else { + Network network = getConnectivityManager().getNetworkForType(upType); + NetPluginDelegate.setUpstream(network); LinkProperties linkProperties = getConnectivityManager().getLinkProperties(upType); if (linkProperties != null) { @@ -1600,7 +1632,6 @@ protected void chooseUpstreamType(boolean tryCell) { } } try { - Network network = getConnectivityManager().getNetworkForType(upType); if (network == null) { Log.e(TAG, "No Network for upstream type " + upType + "!"); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index b766894d72b35..f581a7f8c4b7f 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -815,9 +815,13 @@ public List getCurrentSyncsAsUser(int userId) { mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, "no permission to read the sync stats"); + final boolean canAccessAccounts = + mContext.checkCallingOrSelfPermission(Manifest.permission.GET_ACCOUNTS) + == PackageManager.PERMISSION_GRANTED; long identityToken = clearCallingIdentity(); try { - return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); + return getSyncManager().getSyncStorageEngine() + .getCurrentSyncsCopy(userId, canAccessAccounts); } finally { restoreCallingIdentity(identityToken); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 3ec0bee85f679..53c36ff589fc0 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -2435,10 +2435,9 @@ private long scheduleReadyPeriodicSyncs() { final long shiftedLastPollTimeAbsolute = (0 < lastPollTimeAbsolute - mSyncRandomOffsetMillis) ? (lastPollTimeAbsolute - mSyncRandomOffsetMillis) : 0; - long remainingMillis - = periodInMillis - (shiftedNowAbsolute % periodInMillis); long timeSinceLastRunMillis = (nowAbsolute - lastPollTimeAbsolute); + long remainingMillis = periodInMillis - timeSinceLastRunMillis; // Schedule this periodic sync to run early if it's close enough to its next // runtime, and far enough from its last run time. // If we are early, there will still be time remaining in this period. @@ -2604,32 +2603,17 @@ private long maybeStartNextSyncH() { } continue; } - if (!isOperationValidLocked(op)) { - operationIterator.remove(); - mSyncStorageEngine.deleteFromPending(op.pendingOperation); - continue; - } - // If the next run time is in the future, even given the flexible scheduling, - // return the time. - if (op.effectiveRunTime - op.flexTime > now) { - if (nextReadyToRunTime > op.effectiveRunTime) { - nextReadyToRunTime = op.effectiveRunTime; - } - if (isLoggable) { - Log.v(TAG, " Not running sync operation: Sync too far in future." - + "effective: " + op.effectiveRunTime + " flex: " + op.flexTime - + " now: " + now); - } - continue; - } String packageName = getPackageName(op.target); ApplicationInfo ai = null; if (packageName != null) { try { ai = mContext.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES - | PackageManager.GET_DISABLED_COMPONENTS); + | PackageManager.GET_DISABLED_COMPONENTS); } catch (NameNotFoundException e) { + operationIterator.remove(); + mSyncStorageEngine.deleteFromPending(op.pendingOperation); + continue; } } // If app is considered idle, then skip for now and backoff @@ -2644,6 +2628,24 @@ private long maybeStartNextSyncH() { } else { op.appIdle = false; } + if (!isOperationValidLocked(op)) { + operationIterator.remove(); + mSyncStorageEngine.deleteFromPending(op.pendingOperation); + continue; + } + // If the next run time is in the future, even given the flexible scheduling, + // return the time. + if (op.effectiveRunTime - op.flexTime > now) { + if (nextReadyToRunTime > op.effectiveRunTime) { + nextReadyToRunTime = op.effectiveRunTime; + } + if (isLoggable) { + Log.v(TAG, " Not running sync operation: Sync too far in future." + + "effective: " + op.effectiveRunTime + " flex: " + op.flexTime + + " now: " + now); + } + continue; + } // Add this sync to be run. operations.add(op); } diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index cca0c16f805fd..96a7bb47b5e28 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -45,6 +45,7 @@ import android.util.SparseArray; import android.util.ArrayMap; import android.util.Xml; +import android.util.EventLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -1458,15 +1459,23 @@ private List getCurrentSyncs(int userId) { } /** - * @return a copy of the current syncs data structure. Will not return - * null. + * @param userId Id of user to return current sync info. + * @param canAccessAccounts Determines whether to redact Account information from the result. + * @return a copy of the current syncs data structure. Will not return null. */ - public List getCurrentSyncsCopy(int userId) { + public List getCurrentSyncsCopy(int userId, boolean canAccessAccounts) { synchronized (mAuthorities) { final List syncs = getCurrentSyncsLocked(userId); final List syncsCopy = new ArrayList(); for (SyncInfo sync : syncs) { - syncsCopy.add(new SyncInfo(sync)); + SyncInfo copy; + if (!canAccessAccounts) { + copy = SyncInfo.createAccountRedacted( + sync.authorityId, sync.authority, sync.startTime); + } else { + copy = new SyncInfo(sync); + } + syncsCopy.add(copy); } return syncsCopy; } @@ -1892,8 +1901,13 @@ private void readAccountInfoLocked() { if ("authority".equals(tagName)) { authority = parseAuthority(parser, version); periodicSync = null; - if (authority.ident > highestAuthorityId) { - highestAuthorityId = authority.ident; + if (authority != null) { + if (authority.ident > highestAuthorityId) { + highestAuthorityId = authority.ident; + } + } else { + EventLog.writeEvent(0x534e4554, "26513719", -1, + "Malformed authority"); } } else if (XML_TAG_LISTEN_FOR_TICKLES.equals(tagName)) { parseListenForTickles(parser); diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 575701ac9b774..eca6a2e7c1944 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -55,18 +55,16 @@ class AutomaticBrightnessController { // auto-brightness adjustment setting. private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f; - // Period of time in which to consider light samples in milliseconds. - private static final int AMBIENT_LIGHT_HORIZON = 10000; - // Hysteresis constraints for brightening or darkening. // The recent lux must have changed by at least this fraction relative to the // current ambient lux before a change will be considered. private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f; private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f; - // The intercept used for the weighting calculation. This is used in order to keep all possible - // weighting values positive. - private static final int WEIGHTING_INTERCEPT = AMBIENT_LIGHT_HORIZON; + // Threshold (in lux) to select between normal and fast debounce time. + // If the difference between last sample and weighted value is larger than this value, + // fast debounce is used. + private static final float BRIGHTENING_FAST_THRESHOLD = 1000f; // How long the current sensor reading is assumed to be valid beyond the current time. // This provides a bit of prediction, as well as ensures that the weight for the last sample is @@ -126,6 +124,7 @@ class AutomaticBrightnessController { // when adapting to brighter or darker environments. This parameter controls how quickly // brightness changes occur in response to an observed change in light level that exceeds the // hysteresis threshold. + private final long mBrighteningLightFastDebounceConfig; private final long mBrighteningLightDebounceConfig; private final long mDarkeningLightDebounceConfig; @@ -195,8 +194,12 @@ class AutomaticBrightnessController { private int mBrightnessAdjustmentSampleOldBrightness; private float mBrightnessAdjustmentSampleOldGamma; - // Night mode color temperature adjustments - private final LiveDisplayController mLiveDisplay; + // Period of time in which to consider light samples in milliseconds. + private int mAmbientLightHorizon; + + // The intercept used for the weighting calculation. This is used in order to keep all possible + // weighting values positive. + private int mWeightingIntercept; private final Context mContext; @@ -204,8 +207,9 @@ public AutomaticBrightnessController(Context context, Callbacks callbacks, Loope SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor, int lightSensorRate, long brighteningLightDebounceConfig, - long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, - LiveDisplayController ldc) { + long brighteningLightFastDebounceConfig, long darkeningLightDebounceConfig, + boolean resetAmbientLuxAfterWarmUpConfig, + int ambientLightHorizon) { mContext = context; mCallbacks = callbacks; mTwilight = LocalServices.getService(TwilightManager.class); @@ -217,12 +221,14 @@ public AutomaticBrightnessController(Context context, Callbacks callbacks, Loope mDozeScaleFactor = dozeScaleFactor; mLightSensorRate = lightSensorRate; mBrighteningLightDebounceConfig = brighteningLightDebounceConfig; + mBrighteningLightFastDebounceConfig = brighteningLightFastDebounceConfig; mDarkeningLightDebounceConfig = darkeningLightDebounceConfig; mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig; - mLiveDisplay = ldc; + mAmbientLightHorizon = ambientLightHorizon; + mWeightingIntercept = ambientLightHorizon; mHandler = new AutomaticBrightnessHandler(looper); - mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate); + mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon); if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) { mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); @@ -266,6 +272,7 @@ public void dump(PrintWriter pw) { pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum); pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig); pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig); + pw.println(" mBrighteningLightFastDebounceConfig=" + mBrighteningLightFastDebounceConfig); pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig); pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig); @@ -313,13 +320,14 @@ private boolean setLightSensorEnabled(boolean enable) { private void handleLightSensorEvent(long time, float lux) { mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); + if (DEBUG) Slog.d(TAG, "handleLightSensorEvent: time=" + time + ", lux=" + lux); applyLightSensorMeasurement(time, lux); updateAmbientLux(time); } private void applyLightSensorMeasurement(long time, float lux) { mRecentLightSamples++; - mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON); + mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); mAmbientLightRingBuffer.push(time, lux); // Remember this sample value. @@ -370,17 +378,17 @@ private float calculateAmbientLux(long now) { return sum / totalWeight; } - private static float calculateWeight(long startDelta, long endDelta) { + private float calculateWeight(long startDelta, long endDelta) { return weightIntegral(endDelta) - weightIntegral(startDelta); } - // Evaluates the integral of y = x + WEIGHTING_INTERCEPT. This is always positive for the + // Evaluates the integral of y = x + mWeightIntercept. This is always positive for the // horizon we're looking at and provides a non-linear weighting for light samples. - private static float weightIntegral(long x) { - return x * (x * 0.5f + WEIGHTING_INTERCEPT); + private float weightIntegral(long x) { + return x * (x * 0.5f + mWeightingIntercept); } - private long nextAmbientLightBrighteningTransition(long time) { + private long nextAmbientLightBrighteningTransition(long time, float ambientLux) { final int N = mAmbientLightRingBuffer.size(); long earliestValidTime = time; for (int i = N - 1; i >= 0; i--) { @@ -389,10 +397,13 @@ private long nextAmbientLightBrighteningTransition(long time) { } earliestValidTime = mAmbientLightRingBuffer.getTime(i); } - return earliestValidTime + mBrighteningLightDebounceConfig; + + long debounceDelay = mLastObservedLux - ambientLux > BRIGHTENING_FAST_THRESHOLD + ? mBrighteningLightFastDebounceConfig : mBrighteningLightDebounceConfig; + return earliestValidTime + debounceDelay; } - private long nextAmbientLightDarkeningTransition(long time) { + private long nextAmbientLightDarkeningTransition(long time, float ambientLux) { final int N = mAmbientLightRingBuffer.size(); long earliestValidTime = time; for (int i = N - 1; i >= 0; i--) { @@ -406,7 +417,7 @@ private long nextAmbientLightDarkeningTransition(long time) { private void updateAmbientLux() { long time = SystemClock.uptimeMillis(); - mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON); + mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon); updateAmbientLux(time); } @@ -436,13 +447,12 @@ private void updateAmbientLux(long time) { updateAutoBrightness(true); } - long nextBrightenTransition = nextAmbientLightBrighteningTransition(time); - long nextDarkenTransition = nextAmbientLightDarkeningTransition(time); float ambientLux = calculateAmbientLux(time); + long nextBrightenTransition = nextAmbientLightBrighteningTransition(time, ambientLux); + long nextDarkenTransition = nextAmbientLightDarkeningTransition(time, ambientLux); if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) { - setAmbientLux(ambientLux); if (DEBUG) { Slog.d(TAG, "updateAmbientLux: " + ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " @@ -450,9 +460,10 @@ private void updateAmbientLux(long time) { + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", mAmbientLux=" + mAmbientLux); } + setAmbientLux(ambientLux); updateAutoBrightness(true); - nextBrightenTransition = nextAmbientLightBrighteningTransition(time); - nextDarkenTransition = nextAmbientLightDarkeningTransition(time); + nextBrightenTransition = nextAmbientLightBrighteningTransition(time, ambientLux); + nextDarkenTransition = nextAmbientLightDarkeningTransition(time, ambientLux); } long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition); // If one of the transitions is ready to occur, but the total weighted ambient lux doesn't @@ -488,9 +499,6 @@ private void updateAutoBrightness(boolean sendUpdate) { } } - // Update LiveDisplay with the current lux - mLiveDisplay.updateLiveDisplay(mAmbientLux); - if (USE_TWILIGHT_ADJUSTMENT) { TwilightState state = mTwilight.getCurrentState(); if (state != null && state.isNight()) { @@ -666,8 +674,8 @@ private static final class AmbientLightRingBuffer{ private int mEnd; private int mCount; - public AmbientLightRingBuffer(long lightSensorRate) { - mCapacity = (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate); + public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) { + mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate); mRingLux = new float[mCapacity]; mRingTime = new long[mCapacity]; } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index e8a857bb07505..6a6570b97205c 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -287,8 +287,6 @@ public void systemReady(boolean safeMode, boolean onlyCore) { mOnlyCore = onlyCore; } - mDisplayPowerController.systemReady(); - mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 38c418043835e..25e59d55341ca 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -251,9 +251,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The controller for the automatic brightness level. private AutomaticBrightnessController mAutomaticBrightnessController; - // The controller for LiveDisplay - private final LiveDisplayController mLiveDisplayController; - // Animators. private ObjectAnimator mColorFadeOnAnimator; private ObjectAnimator mColorFadeOffAnimator; @@ -275,8 +272,6 @@ public DisplayPowerController(Context context, mBlanker = blanker; mContext = context; - mLiveDisplayController = new LiveDisplayController(context, handler.getLooper()); - final Resources resources = context.getResources(); final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger( com.android.internal.R.integer.config_screenBrightnessSettingMinimum)); @@ -317,10 +312,14 @@ public DisplayPowerController(Context context, com.android.internal.R.integer.config_autoBrightnessLightSensorRate); long brighteningLightDebounce = resources.getInteger( com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); + long brighteningLightFastDebounce = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessBrighteningLightFastDebounce); long darkeningLightDebounce = resources.getInteger( com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce); boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean( com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp); + int ambientLightHorizon = resources.getInteger( + com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon); if (mUseSoftwareAutoBrightnessConfig) { int[] lux = resources.getIntArray( @@ -357,8 +356,9 @@ public DisplayPowerController(Context context, handler.getLooper(), sensorManager, screenAutoBrightnessSpline, lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate, - brighteningLightDebounce, darkeningLightDebounce, - autoBrightnessResetAmbientLuxAfterWarmUp, mLiveDisplayController); + brighteningLightDebounce, brighteningLightFastDebounce, + darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, + ambientLightHorizon); } } @@ -711,9 +711,6 @@ private void updatePowerState() { } } - // Update LiveDisplay now - mLiveDisplayController.updateLiveDisplay(); - // Determine whether the display is ready for use in the newly requested state. // Note that we do not wait for the brightness ramp animation to complete before // reporting the display is ready because we only need to ensure the screen is in the @@ -1152,8 +1149,6 @@ private void dumpLocal(PrintWriter pw) { if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.dump(pw); } - - mLiveDisplayController.dump(pw); } private static String proximityToString(int state) { @@ -1215,10 +1210,6 @@ private static int clampAbsoluteBrightness(int value) { return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); } - void systemReady() { - mLiveDisplayController.systemReady(); - } - private final class DisplayControllerHandler extends Handler { public DisplayControllerHandler(Looper looper) { super(looper, null, true /*async*/); diff --git a/services/core/java/com/android/server/display/LiveDisplayController.java b/services/core/java/com/android/server/display/LiveDisplayController.java deleted file mode 100644 index 9e6da2ddd1cde..0000000000000 --- a/services/core/java/com/android/server/display/LiveDisplayController.java +++ /dev/null @@ -1,834 +0,0 @@ -/* - * Copyright (C) 2015 The CyanogenMod 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.display; - -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.PowerManagerInternal; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.MathUtils; -import android.util.Slog; - -import com.android.server.LocalServices; -import com.android.server.accessibility.DisplayAdjustmentUtils; -import com.android.server.twilight.TwilightListener; -import com.android.server.twilight.TwilightManager; -import com.android.server.twilight.TwilightState; - -import cyanogenmod.hardware.CMHardwareManager; -import cyanogenmod.providers.CMSettings; - -import java.io.PrintWriter; - -public class LiveDisplayController { - - private static final String TAG = "LiveDisplay"; - - private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 1; - - private static final int OFF_TEMPERATURE = 6500; - - public static final int MODE_OFF = 0; - public static final int MODE_NIGHT = 1; - public static final int MODE_AUTO = 2; - public static final int MODE_OUTDOOR = 3; - public static final int MODE_DAY = 4; - - private int mColorTemperature = OFF_TEMPERATURE; - private float mCurrentLux = 0.0f; - - private int mHintCounter; - private int mMode; - - private boolean mOutdoorMode; - private boolean mColorEnhancement; - private boolean mLowPower; - - private final Context mContext; - private final Handler mHandler; - - private CMHardwareManager mHardware; - - private int mDayTemperature; - private int mNightTemperature; - - private boolean mUseOutdoorMode; - private boolean mUseColorEnhancement; - private boolean mUseLowPower; - - private boolean mOutdoorModeIsSelfManaged; - - private final float[] mColorAdjustment = new float[] { 1.0f, 1.0f, 1.0f }; - private final float[] mRGB = new float[] { 0.0f, 0.0f, 0.0f }; - - private TwilightManager mTwilightManager; - private boolean mSunset = false; - - private SettingsObserver mObserver; - - private ValueAnimator mAnimator; - - private int mDefaultDayTemperature; - private int mDefaultNightTemperature; - private int mDefaultOutdoorLux; - - private boolean mInitialized = false; - - private static final int MSG_UPDATE_LIVE_DISPLAY = 1; - - // Display postprocessing can have power impact. Disable it if powersave mode is on. - private boolean mLowPerformance = false; - private PowerManagerInternal.LowPowerModeListener mLowPowerModeListener = - new PowerManagerInternal.LowPowerModeListener() { - @Override - public void onLowPowerModeChanged(boolean enabled) { - mLowPerformance = enabled; - updateLiveDisplay(mCurrentLux); - } - }; - - LiveDisplayController(Context context, Looper looper) { - mContext = context; - mHandler = new LiveDisplayHandler(looper); - } - - void systemReady() { - mHardware = CMHardwareManager.getInstance(mContext); - - mDefaultDayTemperature = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_dayColorTemperature); - mDefaultNightTemperature = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_nightColorTemperature); - mDefaultOutdoorLux = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_outdoorAmbientLux); - - // Counter used to determine when we should tell the user about this feature. - // If it's not used after 3 sunsets, we'll show the hint once. - mHintCounter = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.LIVE_DISPLAY_HINTED, - -3, - UserHandle.USER_CURRENT); - - mUseOutdoorMode = - mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT); - mOutdoorModeIsSelfManaged = mUseOutdoorMode ? - mHardware.isSunlightEnhancementSelfManaged() : false; - - mUseLowPower = - mHardware.isSupported(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT); - if (mUseLowPower) { - mLowPower = mHardware.get(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT); - } - - mUseColorEnhancement = - mHardware.isSupported(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT); - if (mUseColorEnhancement) { - mColorEnhancement = - mHardware.get(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT); - } - - updateSettings(); - - mObserver = new SettingsObserver(); - mObserver.register(true); - - PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class); - pmi.registerLowPowerModeObserver(mLowPowerModeListener); - mLowPerformance = pmi.getLowPowerModeEnabled(); - - mTwilightManager = LocalServices.getService(TwilightManager.class); - mTwilightManager.registerListener(mTwilightListener, mHandler); - - mInitialized = true; - } - - private void updateSettings() { - mDayTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_DAY, - mDefaultDayTemperature, - UserHandle.USER_CURRENT); - mNightTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_NIGHT, - mDefaultNightTemperature, - UserHandle.USER_CURRENT); - mMode = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_MODE, - MODE_OFF, - UserHandle.USER_CURRENT); - - // Clear the hint forever - if (mMode != MODE_OFF) { - saveUserHint(1); - } - - // Manual color adjustment will be set as a space separated string of float values - String colorAdjustmentTemp = CMSettings.System.getStringForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_COLOR_ADJUSTMENT, - UserHandle.USER_CURRENT); - String[] colorAdjustment = colorAdjustmentTemp == null ? - null : colorAdjustmentTemp.split(" "); - if (colorAdjustment == null || colorAdjustment.length != 3) { - colorAdjustment = new String[] { "1.0", "1.0", "1.0" }; - } - try { - mColorAdjustment[0] = Float.parseFloat(colorAdjustment[0]); - mColorAdjustment[1] = Float.parseFloat(colorAdjustment[1]); - mColorAdjustment[2] = Float.parseFloat(colorAdjustment[2]); - } catch (NumberFormatException e) { - Slog.e(TAG, e.getMessage(), e); - mColorAdjustment[0] = 1.0f; - mColorAdjustment[1] = 1.0f; - mColorAdjustment[2] = 1.0f; - } - - updateLiveDisplay(mCurrentLux); - } - - private final class SettingsObserver extends ContentObserver { - private final Uri DISPLAY_TEMPERATURE_DAY_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY); - private final Uri DISPLAY_TEMPERATURE_NIGHT_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT); - private final Uri DISPLAY_TEMPERATURE_MODE_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_MODE); - private final Uri DISPLAY_AUTO_OUTDOOR_MODE_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE); - private final Uri DISPLAY_LOW_POWER_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_LOW_POWER); - private final Uri DISPLAY_COLOR_ENHANCE_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_COLOR_ENHANCE); - private final Uri DISPLAY_COLOR_ADJUSTMENT_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT); - public SettingsObserver() { - super(mHandler); - } - - public void register(boolean register) { - final ContentResolver cr = mContext.getContentResolver(); - if (register) { - cr.registerContentObserver(DISPLAY_TEMPERATURE_DAY_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_TEMPERATURE_NIGHT_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_TEMPERATURE_MODE_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_AUTO_OUTDOOR_MODE_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_LOW_POWER_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_COLOR_ENHANCE_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_COLOR_ADJUSTMENT_URI, false, this, UserHandle.USER_ALL); - } else { - cr.unregisterContentObserver(this); - } - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - updateSettings(); - } - } - - public void updateLiveDisplay() { - updateLiveDisplay(mCurrentLux); - } - - synchronized void updateLiveDisplay(float lux) { - mCurrentLux = lux; - mHandler.removeMessages(MSG_UPDATE_LIVE_DISPLAY); - mHandler.sendEmptyMessage(MSG_UPDATE_LIVE_DISPLAY); - } - - private synchronized void updateColorTemperature(TwilightState twilight) { - int temperature = mDayTemperature; - if (mMode == MODE_OFF || mLowPerformance) { - temperature = OFF_TEMPERATURE; - } else if (mMode == MODE_NIGHT) { - temperature = mNightTemperature; - } else if (mMode == MODE_AUTO) { - temperature = getTwilightK(twilight); - } - - if (mAnimator != null) { - mAnimator.cancel(); - } - mAnimator = ValueAnimator.ofInt(mColorTemperature, temperature); - mAnimator.setDuration(Math.abs(mColorTemperature - temperature) / 2); - mAnimator.addUpdateListener(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - setDisplayTemperature((Integer)animation.getAnimatedValue()); - } - }); - mAnimator.start(); - } - - private synchronized void setDisplayTemperature(int temperature) { - mColorTemperature = temperature; - - final float[] rgb = temperatureToRGB(temperature); - - if (!mLowPerformance) { - rgb[0] *= mColorAdjustment[0]; - rgb[1] *= mColorAdjustment[1]; - rgb[2] *= mColorAdjustment[2]; - } - - if (rgb[0] == mRGB[0] && rgb[1] == mRGB[1] && rgb[2] == mRGB[2]) { - // no changes - return; - } - - System.arraycopy(rgb, 0, mRGB, 0, 3); - - Slog.d(TAG, "Adjust display temperature to " + temperature + - "K [r=" + rgb[0] + " g=" + rgb[1] + " b=" + rgb[2] + "]"); - - if (mHardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION)) { - // Clear this out in case of an upgrade - CMSettings.Secure.putStringForUser(mContext.getContentResolver(), - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, - null, - UserHandle.USER_CURRENT); - - int max = mHardware.getDisplayColorCalibrationMax(); - mHardware.setDisplayColorCalibration(new int[] { - (int) Math.ceil(rgb[0] * max), - (int) Math.ceil(rgb[1] * max), - (int) Math.ceil(rgb[2] * max) - }); - screenRefresh(); - } else { - String colorMatrixStr = null; - if (rgb[0] != 1.0f || rgb[1] != 1.0f || rgb[2] != 1.0f) { - final Float[] colorMatrix = new Float[] { - rgb[0], 0.0f, 0.0f, 0.0f, - 0.0f, rgb[1], 0.0f, 0.0f, - 0.0f, 0.0f, rgb[2], 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f }; - colorMatrixStr = TextUtils.join(" ", colorMatrix); - } - - // For GPU color transform, go thru DisplayAdjustmentUtils in - // order to coexist with accessibility settings - CMSettings.Secure.putStringForUser(mContext.getContentResolver(), - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, - colorMatrixStr, - UserHandle.USER_CURRENT); - - DisplayAdjustmentUtils.applyAdjustments(mContext, UserHandle.USER_CURRENT); - } - } - - /** - * Outdoor mode is optionally enabled when ambient lux > 10000 and it's daytime - * Melt faces! - * - * TODO: Use the camera or RGB sensor to determine if it's really sunlight - */ - private synchronized void updateOutdoorMode(TwilightState twilight) { - if (!mUseOutdoorMode) { - return; - } - - boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, - 1, - UserHandle.USER_CURRENT) == 1; - - boolean enabled; - if (mOutdoorModeIsSelfManaged) { - enabled = value; - } else { - enabled = !mLowPerformance && - ((mMode == MODE_OUTDOOR) || - (value && mMode == MODE_AUTO && - twilight != null && !twilight.isNight() && - mCurrentLux > mDefaultOutdoorLux)); - } - - if (enabled == mOutdoorMode) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, enabled); - mOutdoorMode = enabled; - } - - /** - * Color enhancement is optional, but can look bad with night mode - */ - private synchronized void updateColorEnhancement(TwilightState twilight) { - if (!mUseColorEnhancement) { - return; - } - - boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_COLOR_ENHANCE, - 1, - UserHandle.USER_CURRENT) == 1; - - boolean enabled = !mLowPerformance && value && - !(mMode == MODE_NIGHT || - (mMode == MODE_AUTO && twilight != null && twilight.isNight())); - - if (enabled == mColorEnhancement) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT, enabled); - mColorEnhancement = enabled; - } - - /** - * Adaptive backlight / low power mode. Turn it off when under very bright light. - */ - private synchronized void updateLowPowerMode() { - if (!mUseLowPower) { - return; - } - - boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_LOW_POWER, - 1, - UserHandle.USER_CURRENT) == 1; - - boolean enabled = value && (mCurrentLux < mDefaultOutdoorLux); - - if (enabled == mLowPower) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT, enabled); - mLowPower = enabled; - } - - /** - * Convert a color temperature value (in Kelvin) to a RGB units as floats. - * This can be used in a transform matrix or hardware gamma control. - * - * @param tempK - * @return - */ - private static float[] temperatureToRGB(int degreesK) { - int k = MathUtils.constrain(degreesK, 1000, 20000); - float a = (k % 100) / 100.0f; - int i = ((k - 1000)/ 100) * 3; - - return new float[] { interp(i, a), interp(i+1, a), interp(i+2, a) }; - } - - private static float interp(int i, float a) { - return MathUtils.lerp((float)sColorTable[i], (float)sColorTable[i+3], a); - } - - /** - * Where is the sun anyway? This calculation determines day or night, and scales - * the value around sunset/sunrise for a smooth transition. - * - * @param now - * @param sunset - * @param sunrise - * @return float between 0 and 1 - */ - private static float adj(long now, long sunset, long sunrise) { - if (sunset < 0 || sunrise < 0 - || now < sunset || now > sunrise) { - return 1.0f; - } - - if (now < sunset + TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, 0.0f, - (float)(now - sunset) / TWILIGHT_ADJUSTMENT_TIME); - } - - if (now > sunrise - TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, 0.0f, - (float)(sunrise - now) / TWILIGHT_ADJUSTMENT_TIME); - } - - return 0.0f; - } - - /** - * Determine the color temperature we should use for the display based on - * the position of the sun. - * - * @param state - * @return color temperature in Kelvin - */ - private int getTwilightK(TwilightState state) { - float adjustment = 1.0f; - - if (state != null) { - final long now = System.currentTimeMillis(); - adjustment = adj(now, state.getYesterdaySunset(), state.getTodaySunrise()) * - adj(now, state.getTodaySunset(), state.getTomorrowSunrise()); - } - - return (int)MathUtils.lerp(mNightTemperature, mDayTemperature, adjustment); - } - - /** - * Tell SurfaceFlinger to repaint the screen. This is called after updating - * hardware registers for display calibration to have an immediate effect. - */ - private static void screenRefresh() { - try { - final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); - if (flinger != null) { - final Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - flinger.transact(1004, data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(TAG, "Failed to refresh screen", ex); - } - } - - private void saveUserHint(int value) { - if (mHintCounter == value) { - return; - } - CMSettings.System.putIntForUser(mContext.getContentResolver(), - CMSettings.System.LIVE_DISPLAY_HINTED, - value, - UserHandle.USER_CURRENT); - mHintCounter = value; - } - - /** - * Show a friendly notification to the user about the potential benefits of decreasing - * blue light at night. Do this only once if the feature has not been used after - * three sunsets. It would be great to enable this by default, but we don't want - * the change of screen color to be considered a "bug" by a user who doesn't - * understand what's happening. - * - * @param state - */ - private void updateUserHint(TwilightState state) { - // check if we should send the hint only once after sunset - if (state == null || mHintCounter == 1) { - return; - } - boolean transition = state.isNight() && !mSunset; - mSunset = state.isNight(); - if (!transition) { - return; - } - - if (mHintCounter <= 0) { - mHintCounter++; - saveUserHint(mHintCounter); - } - if (mHintCounter == 0) { - //show the notification and don't come back here - final Intent intent = new Intent("android.settings.LIVEDISPLAY_SETTINGS"); - PendingIntent result = PendingIntent.getActivity( - mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - Notification.Builder builder = new Notification.Builder(mContext) - .setContentTitle(mContext.getResources().getString( - org.cyanogenmod.platform.internal.R.string.live_display_title)) - .setContentText(mContext.getResources().getString( - org.cyanogenmod.platform.internal.R.string.live_display_hint)) - .setSmallIcon(org.cyanogenmod.platform.internal.R.drawable.ic_livedisplay_notif) - .setStyle(new Notification.BigTextStyle().bigText(mContext.getResources() - .getString( - org.cyanogenmod.platform.internal.R.string.live_display_hint))) - .setContentIntent(result); - - NotificationManager nm = - (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); - nm.notifyAsUser(null, 1, builder.build(), UserHandle.CURRENT); - - saveUserHint(1); - } - } - - private final TwilightListener mTwilightListener = new TwilightListener() { - @Override - public void onTwilightStateChanged() { - updateLiveDisplay(mCurrentLux); - } - }; - - private final class LiveDisplayHandler extends Handler { - public LiveDisplayHandler(Looper looper) { - super(looper, null, true /*async*/); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_LIVE_DISPLAY: - if (!mInitialized) { - break; - } - TwilightState twilight = mTwilightManager.getCurrentState(); - - updateColorTemperature(twilight); - updateOutdoorMode(twilight); - updateColorEnhancement(twilight); - updateLowPowerMode(); - updateUserHint(twilight); - - boolean transition = mMode == MODE_AUTO && - mColorTemperature != mDayTemperature && - mColorTemperature != mNightTemperature; - if (transition) { - // fire again in a minute - sendEmptyMessageDelayed(MSG_UPDATE_LIVE_DISPLAY, - DateUtils.MINUTE_IN_MILLIS); - } - break; - } - } - } - - public void dump(PrintWriter pw) { - pw.println(); - pw.println("LiveDisplay Controller Configuration:"); - pw.println(" mDayTemperature=" + mDayTemperature); - pw.println(" mNightTemperature=" + mNightTemperature); - pw.println(); - pw.println("LiveDisplay Controller State:"); - pw.println(" mMode=" + (mLowPerformance ? "disabled in powersave mode" : mMode)); - pw.println(" mSunset=" + mSunset); - pw.println(" mColorTemperature=" + mColorTemperature); - pw.println(" mColorAdjustment=[r: " + mColorAdjustment[0] + " g:" + mColorAdjustment[1] + - " b:" + mColorAdjustment[2] + "]"); - pw.println(" mRGB=[r:" + mRGB[0] + " g:" + mRGB[1] + " b:" + mRGB[2] + "]"); - pw.println(" mOutdoorMode=" + (mUseOutdoorMode ? mOutdoorMode : "N/A")); - pw.println(" mColorEnhancement=" + (mUseColorEnhancement ? mColorEnhancement : "N/A")); - pw.println(" mLowPower=" + (mUseLowPower ? mLowPower : "N/A")); - } - - /** - * This table is a modified version of the original blackbody chart, found here: - * http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html - * - * Created by Ingo Thiel. - */ - private static final double[] sColorTable = new double[] { - 1.00000000, 0.18172716, 0.00000000, - 1.00000000, 0.25503671, 0.00000000, - 1.00000000, 0.30942099, 0.00000000, - 1.00000000, 0.35357379, 0.00000000, - 1.00000000, 0.39091524, 0.00000000, - 1.00000000, 0.42322816, 0.00000000, - 1.00000000, 0.45159884, 0.00000000, - 1.00000000, 0.47675916, 0.00000000, - 1.00000000, 0.49923747, 0.00000000, - 1.00000000, 0.51943421, 0.00000000, - 1.00000000, 0.54360078, 0.08679949, - 1.00000000, 0.56618736, 0.14065513, - 1.00000000, 0.58734976, 0.18362641, - 1.00000000, 0.60724493, 0.22137978, - 1.00000000, 0.62600248, 0.25591950, - 1.00000000, 0.64373109, 0.28819679, - 1.00000000, 0.66052319, 0.31873863, - 1.00000000, 0.67645822, 0.34786758, - 1.00000000, 0.69160518, 0.37579588, - 1.00000000, 0.70602449, 0.40267128, - 1.00000000, 0.71976951, 0.42860152, - 1.00000000, 0.73288760, 0.45366838, - 1.00000000, 0.74542112, 0.47793608, - 1.00000000, 0.75740814, 0.50145662, - 1.00000000, 0.76888303, 0.52427322, - 1.00000000, 0.77987699, 0.54642268, - 1.00000000, 0.79041843, 0.56793692, - 1.00000000, 0.80053332, 0.58884417, - 1.00000000, 0.81024551, 0.60916971, - 1.00000000, 0.81957693, 0.62893653, - 1.00000000, 0.82854786, 0.64816570, - 1.00000000, 0.83717703, 0.66687674, - 1.00000000, 0.84548188, 0.68508786, - 1.00000000, 0.85347859, 0.70281616, - 1.00000000, 0.86118227, 0.72007777, - 1.00000000, 0.86860704, 0.73688797, - 1.00000000, 0.87576611, 0.75326132, - 1.00000000, 0.88267187, 0.76921169, - 1.00000000, 0.88933596, 0.78475236, - 1.00000000, 0.89576933, 0.79989606, - 1.00000000, 0.90198230, 0.81465502, - 1.00000000, 0.90963069, 0.82838210, - 1.00000000, 0.91710889, 0.84190889, - 1.00000000, 0.92441842, 0.85523742, - 1.00000000, 0.93156127, 0.86836903, - 1.00000000, 0.93853986, 0.88130458, - 1.00000000, 0.94535695, 0.89404470, - 1.00000000, 0.95201559, 0.90658983, - 1.00000000, 0.95851906, 0.91894041, - 1.00000000, 0.96487079, 0.93109690, - 1.00000000, 0.97107439, 0.94305985, - 1.00000000, 0.97713351, 0.95482993, - 1.00000000, 0.98305189, 0.96640795, - 1.00000000, 0.98883326, 0.97779486, - 1.00000000, 0.99448139, 0.98899179, - 1.00000000, 1.00000000, 1.00000000, - 0.98947904, 0.99348723, 1.00000000, - 0.97940448, 0.98722715, 1.00000000, - 0.96975025, 0.98120637, 1.00000000, - 0.96049223, 0.97541240, 1.00000000, - 0.95160805, 0.96983355, 1.00000000, - 0.94303638, 0.96443333, 1.00000000, - 0.93480451, 0.95923080, 1.00000000, - 0.92689056, 0.95421394, 1.00000000, - 0.91927697, 0.94937330, 1.00000000, - 0.91194747, 0.94470005, 1.00000000, - 0.90488690, 0.94018594, 1.00000000, - 0.89808115, 0.93582323, 1.00000000, - 0.89151710, 0.93160469, 1.00000000, - 0.88518247, 0.92752354, 1.00000000, - 0.87906581, 0.92357340, 1.00000000, - 0.87315640, 0.91974827, 1.00000000, - 0.86744421, 0.91604254, 1.00000000, - 0.86191983, 0.91245088, 1.00000000, - 0.85657444, 0.90896831, 1.00000000, - 0.85139976, 0.90559011, 1.00000000, - 0.84638799, 0.90231183, 1.00000000, - 0.84153180, 0.89912926, 1.00000000, - 0.83682430, 0.89603843, 1.00000000, - 0.83225897, 0.89303558, 1.00000000, - 0.82782969, 0.89011714, 1.00000000, - 0.82353066, 0.88727974, 1.00000000, - 0.81935641, 0.88452017, 1.00000000, - 0.81530175, 0.88183541, 1.00000000, - 0.81136180, 0.87922257, 1.00000000, - 0.80753191, 0.87667891, 1.00000000, - 0.80380769, 0.87420182, 1.00000000, - 0.80018497, 0.87178882, 1.00000000, - 0.79665980, 0.86943756, 1.00000000, - 0.79322843, 0.86714579, 1.00000000, - 0.78988728, 0.86491137, 1.00000000, - 0.78663296, 0.86273225, 1.00000000, - 0.78346225, 0.86060650, 1.00000000, - 0.78037207, 0.85853224, 1.00000000, - 0.77735950, 0.85650771, 1.00000000, - 0.77442176, 0.85453121, 1.00000000, - 0.77155617, 0.85260112, 1.00000000, - 0.76876022, 0.85071588, 1.00000000, - 0.76603147, 0.84887402, 1.00000000, - 0.76336762, 0.84707411, 1.00000000, - 0.76076645, 0.84531479, 1.00000000, - 0.75822586, 0.84359476, 1.00000000, - 0.75574383, 0.84191277, 1.00000000, - 0.75331843, 0.84026762, 1.00000000, - 0.75094780, 0.83865816, 1.00000000, - 0.74863017, 0.83708329, 1.00000000, - 0.74636386, 0.83554194, 1.00000000, - 0.74414722, 0.83403311, 1.00000000, - 0.74197871, 0.83255582, 1.00000000, - 0.73985682, 0.83110912, 1.00000000, - 0.73778012, 0.82969211, 1.00000000, - 0.73574723, 0.82830393, 1.00000000, - 0.73375683, 0.82694373, 1.00000000, - 0.73180765, 0.82561071, 1.00000000, - 0.72989845, 0.82430410, 1.00000000, - 0.72802807, 0.82302316, 1.00000000, - 0.72619537, 0.82176715, 1.00000000, - 0.72439927, 0.82053539, 1.00000000, - 0.72263872, 0.81932722, 1.00000000, - 0.72091270, 0.81814197, 1.00000000, - 0.71922025, 0.81697905, 1.00000000, - 0.71756043, 0.81583783, 1.00000000, - 0.71593234, 0.81471775, 1.00000000, - 0.71433510, 0.81361825, 1.00000000, - 0.71276788, 0.81253878, 1.00000000, - 0.71122987, 0.81147883, 1.00000000, - 0.70972029, 0.81043789, 1.00000000, - 0.70823838, 0.80941546, 1.00000000, - 0.70678342, 0.80841109, 1.00000000, - 0.70535469, 0.80742432, 1.00000000, - 0.70395153, 0.80645469, 1.00000000, - 0.70257327, 0.80550180, 1.00000000, - 0.70121928, 0.80456522, 1.00000000, - 0.69988894, 0.80364455, 1.00000000, - 0.69858167, 0.80273941, 1.00000000, - 0.69729688, 0.80184943, 1.00000000, - 0.69603402, 0.80097423, 1.00000000, - 0.69479255, 0.80011347, 1.00000000, - 0.69357196, 0.79926681, 1.00000000, - 0.69237173, 0.79843391, 1.00000000, - 0.69119138, 0.79761446, 1.00000000, - 0.69003044, 0.79680814, 1.00000000, - 0.68888844, 0.79601466, 1.00000000, - 0.68776494, 0.79523371, 1.00000000, - 0.68665951, 0.79446502, 1.00000000, - 0.68557173, 0.79370830, 1.00000000, - 0.68450119, 0.79296330, 1.00000000, - 0.68344751, 0.79222975, 1.00000000, - 0.68241029, 0.79150740, 1.00000000, - 0.68138918, 0.79079600, 1.00000000, - 0.68038380, 0.79009531, 1.00000000, - 0.67939381, 0.78940511, 1.00000000, - 0.67841888, 0.78872517, 1.00000000, - 0.67745866, 0.78805526, 1.00000000, - 0.67651284, 0.78739518, 1.00000000, - 0.67558112, 0.78674472, 1.00000000, - 0.67466317, 0.78610368, 1.00000000, - 0.67375872, 0.78547186, 1.00000000, - 0.67286748, 0.78484907, 1.00000000, - 0.67198916, 0.78423512, 1.00000000, - 0.67112350, 0.78362984, 1.00000000, - 0.67027024, 0.78303305, 1.00000000, - 0.66942911, 0.78244457, 1.00000000, - 0.66859988, 0.78186425, 1.00000000, - 0.66778228, 0.78129191, 1.00000000, - 0.66697610, 0.78072740, 1.00000000, - 0.66618110, 0.78017057, 1.00000000, - 0.66539706, 0.77962127, 1.00000000, - 0.66462376, 0.77907934, 1.00000000, - 0.66386098, 0.77854465, 1.00000000, - 0.66310852, 0.77801705, 1.00000000, - 0.66236618, 0.77749642, 1.00000000, - 0.66163375, 0.77698261, 1.00000000, - 0.66091106, 0.77647551, 1.00000000, - 0.66019791, 0.77597498, 1.00000000, - 0.65949412, 0.77548090, 1.00000000, - 0.65879952, 0.77499315, 1.00000000, - 0.65811392, 0.77451161, 1.00000000, - 0.65743716, 0.77403618, 1.00000000, - 0.65676908, 0.77356673, 1.00000000, - 0.65610952, 0.77310316, 1.00000000, - 0.65545831, 0.77264537, 1.00000000, - 0.65481530, 0.77219324, 1.00000000, - 0.65418036, 0.77174669, 1.00000000, - 0.65355332, 0.77130560, 1.00000000, - 0.65293404, 0.77086988, 1.00000000, - 0.65232240, 0.77043944, 1.00000000, - 0.65171824, 0.77001419, 1.00000000, - 0.65112144, 0.76959404, 1.00000000, - 0.65053187, 0.76917889, 1.00000000, - 0.64994941, 0.76876866, 1.00000000, - 0.64937392, 0.76836326, 1.00000000 - }; -} diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index b2207f315eb76..7a28f481c990f 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -192,6 +192,9 @@ public boolean updatePhysicalDisplayInfoLocked( for (int j = 0; j < colorTransforms.size(); j++) { if (colorTransforms.get(j).getColorTransform() == info.colorTransform) { existingMode = true; + if (i == activeDisplayInfo) { + activeColorTransform = colorTransforms.get(j); + } break; } } diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index 239f8cd25cc40..eaeca01f1df6a 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -78,6 +78,9 @@ final class WifiDisplayController implements DumpUtils.Dump { private static final int RTSP_TIMEOUT_SECONDS = 30; private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120; + // time given for RTSP teardown sequence to complete. + private static final int RTSP_TEARDOWN_TIMEOUT = 3; + // We repeatedly issue calls to discover peers every so often for a few reasons. // 1. The initial request may fail and need to retried. // 2. Discovery will self-abort after any group is initiated, which may not necessarily @@ -151,6 +154,12 @@ final class WifiDisplayController implements DumpUtils.Dump { // True if RTSP has connected. private boolean mRemoteDisplayConnected; + // Waiting for displayDisconnected from ERD. + private boolean mRemoteDisplayTearingDown; + + // Timed out waiting for RTSP teardown to complete. + private boolean mRemoteDisplayRtspTeardownTimedOut; + // The information we have most recently told WifiDisplayAdapter about. private WifiDisplay mAdvertisedDisplay; private Surface mAdvertisedDisplaySurface; @@ -363,7 +372,15 @@ private int computeFeatureState() { } private void updateScanState() { - if (mScanRequested && mWfdEnabled && mDesiredDevice == null) { + + if (true == mRemoteDisplayTearingDown) { + // when rtsp teardown sequence is completed or timed out, this + // function will be called again. + Slog.i(TAG, "updateScanState no-op as rtsp teardown sequence is in progress"); + return; + } + + if (mScanRequested && mWfdEnabled && (mDesiredDevice == null)) { if (!mDiscoverPeersInProgress) { Slog.i(TAG, "Starting Wifi display scan."); mDiscoverPeersInProgress = true; @@ -570,7 +587,7 @@ private void updateConnection() { // Step 1. Before we try to connect to a new device, tell the system we // have disconnected from the old one. if ((mRemoteDisplay != null || mExtRemoteDisplay != null) && - mConnectedDevice != mDesiredDevice) { + mConnectedDevice != mDesiredDevice && false == mRemoteDisplayTearingDown) { Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface + " from Wifi display: " + mConnectedDevice.deviceName); @@ -581,16 +598,25 @@ private void updateConnection() { ExtendedRemoteDisplayHelper.dispose(mExtRemoteDisplay); } - mExtRemoteDisplay = null; - mRemoteDisplay = null; - mRemoteDisplayInterface = null; - mRemoteDisplayConnected = false; mHandler.removeCallbacks(mRtspTimeout); + mRemoteDisplayTearingDown = true; - mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); - unadvertiseDisplay(); + // Use extended timeout value for certification, as some tests require user inputs + int rtspTimeout = mWifiDisplayCertMode ? + RTSP_TIMEOUT_SECONDS_CERT_MODE : RTSP_TIMEOUT_SECONDS; + + Slog.i(TAG, "Starting wait for rtsp teardown sequence for " + + rtspTimeout + " secs"); - // continue to next step + mHandler.postDelayed(mRtspTimeout, rtspTimeout * 1000); + + return; + } + + if (true == mRemoteDisplayTearingDown && false == mRemoteDisplayRtspTeardownTimedOut) { + // Need to wait for ERD to notify that p2p connection is no longer needed. + Slog.i(TAG, "updateConnection - return as rtsp teardown sequence in progress"); + return; } // Step 2. Before we try to connect to a new device, disconnect from the old one. @@ -630,6 +656,11 @@ private void next() { return; // wait for asynchronous callback } + if (true == mRemoteDisplayTearingDown) { + Slog.i(TAG, "rtsp teardown sequence in progress"); + return; + } + // Step 3. Before we try to connect to a new device, stop trying to connect // to the old one. if (mCancelingDevice != null) { @@ -771,10 +802,11 @@ public void onDisplayConnected(Surface surface, @Override public void onDisplayDisconnected() { + Slog.i(TAG, "onDisplayDisconnected called"); if (mConnectedDevice == oldDevice) { Slog.i(TAG, "Closed RTSP connection with Wifi display: " + mConnectedDevice.deviceName); - mHandler.removeCallbacks(mRtspTimeout); + FinishRtspTeardown(); disconnect(); } } @@ -907,6 +939,21 @@ public void onGroupInfoAvailable(WifiP2pGroup info) { } } + private void FinishRtspTeardown() + { + Slog.i(TAG, "Wait for rtsp teardown sequence completed"); + mRemoteDisplayTearingDown = false; + + mExtRemoteDisplay = null; // callbacks no longer needed + mRemoteDisplay = null; + mRemoteDisplayInterface = null; + mRemoteDisplayConnected = false; + mHandler.removeCallbacks(mRtspTimeout); + + mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); + unadvertiseDisplay(); + } + private final Runnable mDiscoverPeers = new Runnable() { @Override public void run() { @@ -929,13 +976,31 @@ public void run() { private final Runnable mRtspTimeout = new Runnable() { @Override public void run() { + Slog.i(TAG, "mRtspTimeout triggerred"); if (mConnectedDevice != null - && (mRemoteDisplay != null || mExtRemoteDisplay != null) - && !mRemoteDisplayConnected) { - Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " - + RTSP_TIMEOUT_SECONDS + " seconds: " - + mConnectedDevice.deviceName); - handleConnectionFailure(true); + && (mRemoteDisplay != null || mExtRemoteDisplay != null)) { + if (true == mRemoteDisplayTearingDown) { + // rtsp teardown sequence timed out + Slog.i(TAG, "Timed out waiting for RTSP teardown sequence after " + + RTSP_TEARDOWN_TIMEOUT + " seconds: " + + mConnectedDevice.deviceName); + mRemoteDisplayRtspTeardownTimedOut = true; + + // this should close P2P + disconnect(); + + FinishRtspTeardown(); + + // Ok to resume wifi-scans + updateConnection(); + } else if (!mRemoteDisplayConnected) { + Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " + + RTSP_TIMEOUT_SECONDS + " seconds: " + + mConnectedDevice.deviceName); + handleConnectionFailure(true); + } else { + Slog.i(TAG, "Timed out. no-op"); + } } } }; diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 7d1dbe1e54f1d..c986e74de3f87 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -247,6 +247,9 @@ private int getLidStateInternal() { private void setLidStateInternal(int state) { synchronized (mLock) { + if (mLidState == state) { + return; + } mLidState = state; } switch (state) { diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index ec7c1c437d92d..e5ab37f0ffe68 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -19,7 +19,6 @@ import android.Manifest; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; -import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManagerNative; import android.app.AlarmManager; import android.app.AppOpsManager; @@ -30,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback; @@ -127,6 +127,7 @@ public void handleMessage(android.os.Message msg) { private IFingerprintDaemon mDaemon; private final PowerManager mPowerManager; private final AlarmManager mAlarmManager; + private int mCurrentUserId = UserHandle.USER_NULL; private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() { @Override @@ -143,12 +144,15 @@ public void run() { resetFailedAttempts(); } }; + private boolean mFingerprintManagerRestrictedToSystemAndOwner; public FingerprintService(Context context) { super(context); mContext = context; mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString( com.android.internal.R.string.config_keyguardComponent)).getPackageName(); + mFingerprintManagerRestrictedToSystemAndOwner = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_fingerprintRestrictedToSystemAndOwner); mAppOps = context.getSystemService(AppOpsManager.class); mPowerManager = mContext.getSystemService(PowerManager.class); mAlarmManager = mContext.getSystemService(AlarmManager.class); @@ -337,7 +341,8 @@ void startEnrollment(IBinder token, byte[] cryptoToken, int groupId, return; } stopPendingOperations(true); - mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted, token.toString()); + mEnrollClient = new ClientMonitor(token, receiver, mCurrentUserId, groupId, restricted, + token.toString()); final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); try { final int result = daemon.enroll(cryptoToken, groupId, timeout); @@ -425,7 +430,8 @@ void startAuthentication(IBinder token, long opId, int groupId, return; } stopPendingOperations(true); - mAuthClient = new ClientMonitor(token, receiver, groupId, restricted, opPackageName); + mAuthClient = new ClientMonitor(token, receiver, mCurrentUserId, groupId, restricted, + opPackageName); if (inLockoutMode()) { Slog.v(TAG, "In lockout mode; disallowing authentication"); if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { @@ -482,7 +488,8 @@ void startRemove(IBinder token, int fingerId, int userId, } stopPendingOperations(true); - mRemoveClient = new ClientMonitor(token, receiver, userId, restricted, token.toString()); + mRemoveClient = new ClientMonitor(token, receiver, mCurrentUserId, userId, restricted, + token.toString()); // The fingerprint template ids will be removed when we get confirmation from the HAL try { final int result = daemon.remove(fingerId, userId); @@ -582,6 +589,21 @@ private boolean canUseFingerprint(String opPackageName, boolean foregroundOnly) Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground"); return false; } + if (mFingerprintManagerRestrictedToSystemAndOwner) { + try { + ApplicationInfo ai = mContext.getPackageManager() + .getApplicationInfo(opPackageName, PackageManager.GET_META_DATA); + if (ai != null && ai.isSystemApp() && Binder.getCallingUserHandle().isOwner()) { + return true; + } + Slog.w(TAG, "Rejecting " + opPackageName + + "(uid: " + uid + ") ; fingerprint restricted to system apps."); + } catch (PackageManager.NameNotFoundException e) { + Slog.e(TAG, opPackageName + " package not found, not allowing fingerprint access."); + return false; + } + return false; + } return true; } @@ -605,15 +627,17 @@ private void notifyLockoutResetMonitors() { private class ClientMonitor implements IBinder.DeathRecipient { IBinder token; IFingerprintServiceReceiver receiver; - int userId; + int userId; // userId of the caller + int currentUserId; // current user id when this was created boolean restricted; // True if client does not have MANAGE_FINGERPRINT permission String owner; - public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId, - boolean restricted, String owner) { + public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, + int currentUserId, int userId, boolean restricted, String owner) { this.token = token; this.receiver = receiver; this.userId = userId; + this.currentUserId = currentUserId; this.restricted = restricted; this.owner = owner; // name of the client that owns this - for debugging try { @@ -702,9 +726,9 @@ private boolean sendAuthenticated(int fpId, int groupId) { Slog.v(TAG, "onAuthenticated(owner=" + mAuthClient.owner + ", id=" + fpId + ", gp=" + groupId + ")"); } - Fingerprint fp = !restricted ? - new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null; - receiver.onAuthenticationSucceeded(mHalDeviceId, fp); + Fingerprint fp = !restricted ? new Fingerprint("" /* TODO */, groupId, fpId, + mHalDeviceId) : null; + receiver.onAuthenticationSucceeded(mHalDeviceId, fp, currentUserId); } } catch (RemoteException e) { Slog.w(TAG, "Failed to notify Authenticated:", e); @@ -1129,6 +1153,7 @@ private void updateActiveGroup(int userId) { Slog.e(TAG, "Failed to setActiveGroup():", e); } } + mCurrentUserId = userId; } private void listenForUserSwitches() { @@ -1139,6 +1164,12 @@ private void listenForUserSwitches() { public void onUserSwitching(int newUserId, IRemoteCallback reply) { mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) .sendToTarget(); + if (reply != null) { + try { + reply.sendResult(null); + } catch (RemoteException e) { + } + } } @Override public void onUserSwitchComplete(int newUserId) throws RemoteException { diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java index 16dde26f19cfd..d4762bd8ec189 100644 --- a/services/core/java/com/android/server/lights/LightsService.java +++ b/services/core/java/com/android/server/lights/LightsService.java @@ -113,9 +113,10 @@ private void stopFlashing() { private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) { if (mModesUpdate || color != mColor || mode != mMode || onMS != mOnMS || - offMS != mOffMS) { + offMS != mOffMS || mReset) { if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#" + Integer.toHexString(color)); + mReset = false; mColor = color; mMode = mode; mOnMS = onMS; @@ -141,6 +142,7 @@ private void setLightLocked(int color, int mode, int onMS, int offMS, int bright private boolean mFlashing; private boolean mModesUpdate; private boolean mMultipleLeds; + private boolean mReset = true; } public LightsService(Context context) { diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 42b8783a55224..833c3404ac0e2 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -88,6 +88,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; +import java.util.HashSet; import java.util.Map.Entry; import java.util.Properties; @@ -359,6 +360,7 @@ public GpsRequest(ProviderRequest request, WorkSource source) { private String mC2KServerHost; private int mC2KServerPort; private boolean mSuplEsEnabled = false; + private HashSet mLastKnownMccMnc; private final Context mContext; private final NtpTrustedTime mNtpTime; @@ -482,18 +484,14 @@ public void onSubscriptionsChanged() { }; private void subscriptionOrSimChanged(Context context) { - Log.d(TAG, "received SIM related action: "); - TelephonyManager phone = (TelephonyManager) - mContext.getSystemService(Context.TELEPHONY_SERVICE); - String mccMnc = phone.getSimOperator(); - if (!TextUtils.isEmpty(mccMnc)) { - Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc); - synchronized (mLock) { + HashSet mccMnc = getKnownMccMnc(context); + Log.d(TAG, "received SIM change, new known MCC/MNC: " + mccMnc); + synchronized (mLock) { + if (!mccMnc.isEmpty() && !mccMnc.equals(mLastKnownMccMnc)) { reloadGpsProperties(context, mProperties); mNIHandler.setSuplEsEnabled(mSuplEsEnabled); } - } else { - Log.d(TAG, "SIM MCC/MNC is still not available"); + mLastKnownMccMnc = mccMnc; } } @@ -585,6 +583,20 @@ private void reloadGpsProperties(Context context, Properties properties) { } } + private HashSet getKnownMccMnc(Context context) { + final TelephonyManager phone = (TelephonyManager) + context.getSystemService(Context.TELEPHONY_SERVICE); + final HashSet mccMnc = new HashSet(); + final int phoneCnt = phone.getPhoneCount(); + for (int i = 0;i < phoneCnt; ++i) { + String operator = phone.getNetworkOperatorForPhone(i); + if (!TextUtils.isEmpty(operator)) { + mccMnc.add(operator); + } + } + return mccMnc; + } + private void loadPropertiesFromResource(Context context, Properties properties) { String[] configValues = context.getResources().getStringArray( @@ -650,6 +662,8 @@ public GpsLocationProvider(Context context, ILocationManager ilocationManager, // Construct internal handler mHandler = new ProviderHandler(looper); + mLastKnownMccMnc = getKnownMccMnc(mContext); + // Load GPS configuration and register listeners in the background: // some operations, such as opening files and registering broadcast receivers, can take a // relative long time, so the ctor() is kept to create objects needed by this instance, @@ -767,6 +781,10 @@ private void handleUpdateNetworkState(int state, NetworkInfo info) { && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) { if (mNetworkAvailable) { String apnName = info.getExtraInfo(); + // APN wasn't found in the intent, try to get it from the content provider. + if (apnName == null) { + apnName = getSelectedApn(); + } if (apnName == null) { /* Assign a dummy value in the case of C2K as otherwise we will have a runtime exception in the following call to native_agps_data_conn_open*/ @@ -1100,7 +1118,7 @@ private void updateRequirements() { } if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest); - if (mProviderRequest.reportLocation && !mDisableGps) { + if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) { // update client uids updateClientUids(mWorkSource); diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java index 3585049fab231..6310361573fc4 100644 --- a/services/core/java/com/android/server/location/GpsXtraDownloader.java +++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java @@ -21,8 +21,11 @@ import java.net.HttpURLConnection; import java.net.URL; -import libcore.io.Streams; +import libcore.io.IoUtils; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.io.IOException; import java.util.Properties; import java.util.Random; @@ -36,6 +39,7 @@ public class GpsXtraDownloader { private static final String TAG = "GpsXtraDownloader"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final long MAXIMUM_CONTENT_LENGTH_BYTES = 1000000; // 1MB. private static final String DEFAULT_USER_AGENT = "Android"; private final String[] mXtraServers; @@ -121,7 +125,19 @@ protected byte[] doDownload(String url) { return null; } - return Streams.readFully(connection.getInputStream()); + try (InputStream in = connection.getInputStream()) { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count; + while ((count = in.read(buffer)) != -1) { + bytes.write(buffer, 0, count); + if (bytes.size() > MAXIMUM_CONTENT_LENGTH_BYTES) { + if (DEBUG) Log.d(TAG, "XTRA file too large"); + return null; + } + } + return bytes.toByteArray(); + } } catch (IOException ioe) { if (DEBUG) Log.d(TAG, "Error downloading gps XTRA: ", ioe); } finally { @@ -133,3 +149,4 @@ protected byte[] doDownload(String url) { } } + diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 7028fa6695f66..22f9f72be3de5 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -47,6 +47,7 @@ import android.os.IBinder; import android.os.Message; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -760,6 +761,13 @@ public void dispatchMediaKeyEvent(KeyEvent keyEvent, boolean needWakeLock) { + "setup is in progress."); return; } + if (isGlobalPriorityActive() && uid != Process.SYSTEM_UID) { + // Prevent dispatching key event through reflection while the global priority + // session is active. + Slog.i(TAG, "Only the system can dispatch media key event " + + "to the global priority session."); + return; + } synchronized (mLock) { // If we don't have a media button receiver to fall back on diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index bf7560ed982fa..4c847a2bcc02d 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -45,6 +45,9 @@ import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_DATA; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN_BACKGROUND; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; @@ -105,6 +108,7 @@ import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.LinkProperties; +import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkPolicy; @@ -159,6 +163,7 @@ import com.android.server.DeviceIdleController; import com.android.server.EventLogTags; import com.android.server.LocalServices; +import com.android.server.NetPluginDelegate; import com.google.android.collect.Lists; import org.xmlpull.v1.XmlPullParser; @@ -202,6 +207,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int VERSION_SWITCH_UID = 10; private static final int VERSION_LATEST = VERSION_SWITCH_UID; + @VisibleForTesting + public static final int TYPE_NONE = 0; @VisibleForTesting public static final int TYPE_WARNING = 0x1; @VisibleForTesting @@ -247,6 +254,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6; private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7; private static final int MSG_SCREEN_ON_CHANGED = 8; + private static final int MSG_PROCESS_LOW_POWER_CHANGED = 9; private final Context mContext; private final IActivityManager mActivityManager; @@ -262,6 +270,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private PowerManagerInternal mPowerManagerInternal; private IDeviceIdleController mDeviceIdleController; + private final ComponentName mNotificationComponent; + private int mNotificationSequenceNumber; + final Object mRulesLock = new Object(); volatile boolean mSystemReady; @@ -363,6 +374,11 @@ public NetworkPolicyManagerService(Context context, IActivityManager activityMan mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); mAppOps = context.getSystemService(AppOpsManager.class); + + final String notificationComponent = context.getString( + R.string.config_networkPolicyNotificationComponent); + mNotificationComponent = notificationComponent != null + ? ComponentName.unflattenFromString(notificationComponent) : null; } public void bindConnectivityManager(IConnectivityManager connManager) { @@ -437,13 +453,10 @@ public void systemReady() { mPowerManagerInternal.registerLowPowerModeObserver( new PowerManagerInternal.LowPowerModeListener() { @Override - public void onLowPowerModeChanged(boolean enabled) { - synchronized (mRulesLock) { - if (mRestrictPower != enabled) { - mRestrictPower = enabled; - updateRulesForGlobalChangeLocked(true); - } - } + public void onLowPowerModeChanged(final boolean enabled) { + mHandler.removeMessages(MSG_PROCESS_LOW_POWER_CHANGED); + Message msg = Message.obtain(mHandler, MSG_PROCESS_LOW_POWER_CHANGED, enabled); + mHandler.sendMessage(msg); } }); mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled(); @@ -778,6 +791,11 @@ void updateNotificationsLocked() { final ArraySet beforeNotifs = new ArraySet(mActiveNotifs); mActiveNotifs.clear(); + // increment the sequence number so custom components know + // this update is new + mNotificationSequenceNumber++; + boolean hasNotifications = false; + // TODO: when switching to kernel notifications, compute next future // cycle boundary to recompute notifications. @@ -794,6 +812,7 @@ void updateNotificationsLocked() { final long totalBytes = getTotalBytes(policy.template, start, end); if (policy.isOverLimit(totalBytes)) { + hasNotifications = true; if (policy.lastLimitSnooze >= start) { enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); } else { @@ -807,10 +826,18 @@ void updateNotificationsLocked() { if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start && policy.limitBytes != LIMIT_DISABLED) { enqueueNotification(policy, TYPE_WARNING, totalBytes); + hasNotifications = true; } } } + // right now we don't care about restricted background notifications + // in the custom notification component, so trigger an update now + // if we didn't update anything this pass + if (!hasNotifications) { + sendNotificationToCustomComponent(null, TYPE_NONE, 0); + } + // ongoing notification when restricting background data if (mRestrictBackground) { enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); @@ -857,6 +884,12 @@ private boolean isTemplateRelevant(NetworkTemplate template) { * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. */ private void notifyOverLimitLocked(NetworkTemplate template) { + if (mNotificationComponent != null) { + // It is the job of the notification component to handle UI, + // so we do nothing here + return; + } + if (!mOverLimitNotified.contains(template)) { mContext.startActivity(buildNetworkOverLimitIntent(template)); mOverLimitNotified.add(template); @@ -875,11 +908,55 @@ private String buildNotificationTag(NetworkPolicy policy, int type) { return TAG + ":" + policy.template.hashCode() + ":" + type; } + private boolean sendNotificationToCustomComponent( + NetworkPolicy policy, + int type, + long totalBytes) { + if (mNotificationComponent == null) { + return false; + } + + Intent intent = new Intent(); + intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.setComponent(mNotificationComponent); + + int notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_NONE; + switch (type) { + case TYPE_WARNING: + notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_WARNING; + break; + case TYPE_LIMIT: + notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_REACHED_LIMIT; + break; + case TYPE_LIMIT_SNOOZED: + notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_EXCEEDED_LIMIT; + break; + } + + intent.setAction(NetworkPolicyManager.ACTION_SHOW_NETWORK_POLICY_NOTIFICATION); + intent.putExtra(NetworkPolicyManager.EXTRA_NOTIFICATION_TYPE, notificationType); + intent.putExtra( + NetworkPolicyManager.EXTRA_NOTIFICATION_SEQUENCE_NUMBER, + mNotificationSequenceNumber); + + if (notificationType != NetworkPolicyManager.NOTIFICATION_TYPE_NONE) { + intent.putExtra(NetworkPolicyManager.EXTRA_NETWORK_POLICY, policy); + intent.putExtra(NetworkPolicyManager.EXTRA_BYTES_USED, totalBytes); + } + + mContext.sendBroadcast(intent); + return true; + } + /** * Show notification for combined {@link NetworkPolicy} and specific type, * like {@link #TYPE_LIMIT}. Okay to call multiple times. */ private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { + if (sendNotificationToCustomComponent(policy, type, totalBytes)) { + return; + } + final String tag = buildNotificationTag(policy, type); final Notification.Builder builder = new Notification.Builder(mContext); builder.setOnlyAlertOnce(true); @@ -1133,7 +1210,11 @@ void updateNetworkRulesLocked() { final ArrayList> connIdents = new ArrayList<>(states.length); final ArraySet connIfaces = new ArraySet(states.length); for (NetworkState state : states) { - if (state.networkInfo.isConnected()) { + if (state.networkInfo.isConnected() && (state.networkCapabilities == null + || !state.networkCapabilities.hasTransport( + NetworkCapabilities.TRANSPORT_CELLULAR) + || state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET))) { final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); final String baseIface = state.linkProperties.getInterfaceName(); @@ -1739,6 +1820,19 @@ public void snoozeLimit(NetworkTemplate template) { } } + @Override + public void snoozeWarning(NetworkTemplate template) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + final long token = Binder.clearCallingIdentity(); + try { + // TODO: this seems like a race condition? (along with snoozeLimit above) + performSnooze(template, TYPE_WARNING); + } finally { + Binder.restoreCallingIdentity(token); + } + } + void performSnooze(NetworkTemplate template, int type) { maybeRefreshTrustedTime(); final long currentTime = currentTimeMillis(); @@ -2137,12 +2231,23 @@ void updateRulesForAppIdleLocked() { uidRules.clear(); // Fully update the app idle firewall chain. + final IPackageManager ipm = AppGlobals.getPackageManager(); final List users = mUserManager.getUsers(); for (int ui = users.size() - 1; ui >= 0; ui--) { UserInfo user = users.get(ui); int[] idleUids = mUsageStats.getIdleUidsForUser(user.id); for (int uid : idleUids) { if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) { + // quick check: if this uid doesn't have INTERNET permission, it + // doesn't have network access anyway, so it is a waste to mess + // with it here. + try { + if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid) + != PackageManager.PERMISSION_GRANTED) { + continue; + } + } catch (RemoteException e) { + } uidRules.put(uid, FIREWALL_RULE_DENY); } } @@ -2227,11 +2332,13 @@ private static boolean isUidValidForRules(int uid) { private boolean isUidIdle(int uid) { final String[] packages = mContext.getPackageManager().getPackagesForUid(uid); - final int userId = UserHandle.getUserId(uid); - for (String packageName : packages) { - if (!mUsageStats.isAppIdle(packageName, uid, userId)) { - return false; + if (packages != null) { + final int userId = UserHandle.getUserId(uid); + for (String packageName : packages) { + if (!mUsageStats.isAppIdle(packageName, uid, userId)) { + return false; + } } } return true; @@ -2299,6 +2406,14 @@ void updateRulesForUidLocked(int uid) { uidRules = RULE_REJECT_ALL; } + try { + mNetworkManager.restrictAppOnWlan(uid, (uidPolicy & POLICY_REJECT_ON_WLAN) != 0 || + (((uidPolicy & POLICY_REJECT_ON_WLAN_BACKGROUND) != 0) && !uidForeground)); + mNetworkManager.restrictAppOnData(uid, (uidPolicy & POLICY_REJECT_ON_DATA) != 0); + } catch (RemoteException e) { + // ignored; service lives in system_server + } + final int oldRules = mUidRules.get(uid); if (uidRules == RULE_ALLOW_ALL) { mUidRules.delete(uid); @@ -2430,6 +2545,16 @@ public boolean handleMessage(Message msg) { updateScreenOn(); return true; } + case MSG_PROCESS_LOW_POWER_CHANGED: { + boolean enabled = (Boolean) msg.obj; + synchronized (mRulesLock) { + if (mRestrictPower != enabled) { + mRestrictPower = enabled; + updateRulesForGlobalChangeLocked(true); + } + } + return true; + } default: { return false; } diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 15b68c7399459..0176ec435a014 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -491,6 +491,21 @@ public void removeUids(int[] uids) { } } + /** + * Replace data usage history for each matching identity in the template with empty values + */ + public void resetDataUsage(NetworkTemplate template) { + final ArrayList knownKeys = Lists.newArrayList(); + knownKeys.addAll(mStats.keySet()); + + for (Key key : knownKeys) { + if (templateMatches(template, key.ident)) { + mStats.put(key, new NetworkStatsHistory(mBucketDuration, 10)); + mDirty = true; + } + } + } + private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) { if (startMillis < mStartMillis) mStartMillis = startMillis; if (endMillis > mEndMillis) mEndMillis = endMillis; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 649086575c338..3201981a2966d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -289,6 +289,31 @@ public void removeUidsLocked(int[] uids) { } } + /** + * Reset data usage for all matching identities in {@link FileRotator} history, + */ + public void resetDataUsageLocked(NetworkTemplate template) { + try { + // Reset all persisted data to empty values + mRotator.rewriteAll(new ResetDataUsageRewriter(mBucketDuration, template)); + } catch (IOException e) { + Log.wtf(TAG, "problem resetting data stats " + e); + recoverFromWtf(); + } catch (OutOfMemoryError e) { + Log.wtf(TAG, "problem resetting data stats " + e); + recoverFromWtf(); + } + + // Reset any pending stats + mPending.resetDataUsage(template); + mSinceBoot.resetDataUsage(template); + + final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; + if (complete != null) { + complete.resetDataUsage(template); + } + } + /** * Rewriter that will combine current {@link NetworkStatsCollection} values * with anything read from disk, and write combined set to disk. Clears the @@ -359,6 +384,42 @@ public void write(OutputStream out) throws IOException { } } + /** + * Rewriter that will remove any {@link NetworkStatsHistory} attributed to + * identities in input template, replacing it with empty values. + */ + public static class ResetDataUsageRewriter implements FileRotator.Rewriter { + private final NetworkStatsCollection mTemp; + private NetworkTemplate mTemplate; + + public ResetDataUsageRewriter(long bucketDuration, NetworkTemplate template) { + mTemp = new NetworkStatsCollection(bucketDuration); + mTemplate = template; + } + + @Override + public void reset() { + mTemp.reset(); + } + + @Override + public void read(InputStream in) throws IOException { + mTemp.read(in); + mTemp.clearDirty(); + mTemp.resetDataUsage(mTemplate); + } + + @Override + public boolean shouldWrite() { + return mTemp.isDirty(); + } + + @Override + public void write(OutputStream out) throws IOException { + mTemp.write(new DataOutputStream(out)); + } + } + public void importLegacyNetworkLocked(File file) throws IOException { // legacy file still exists; start empty to avoid double importing mRotator.deleteAll(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index acd05f7b3040f..baaf055114a32 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -81,6 +81,7 @@ import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.LinkProperties; +import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkState; @@ -123,6 +124,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.server.EventLogTags; import com.android.server.LocalServices; +import com.android.server.NetPluginDelegate; import com.android.server.connectivity.Tethering; import java.io.File; @@ -628,6 +630,26 @@ private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate templat return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); } + /** + * Reset entire data usage history for all the uids in the template and update global + * data stats + */ + @Override + public void resetDataUsageHistoryForAllUid(NetworkTemplate template) { + mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + + synchronized (mStatsLock) { + mWakeLock.acquire(); + try { + resetDataUsageLocked(template); + } catch (Exception e) { + // ignored; service lives in system_server + } finally { + mWakeLock.release(); + } + } + } + @Override public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); @@ -920,7 +942,11 @@ private void updateIfacesLocked() { final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { - if (state.networkInfo.isConnected()) { + if (state.networkInfo.isConnected() && (state.networkCapabilities == null + || !state.networkCapabilities.hasTransport( + NetworkCapabilities.TRANSPORT_CELLULAR) + || state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET))) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); @@ -1148,6 +1174,18 @@ private void removeUserLocked(int userId) { removeUidsLocked(uids); } + /** + * Reset data usage history for all uids, uid tags, and global transfer data for the input template + */ + private void resetDataUsageLocked(NetworkTemplate template) { + // Perform one last poll before removing + performPollLocked(FLAG_PERSIST_ALL); + + mUidRecorder.resetDataUsageLocked(template); + mUidTagRecorder.resetDataUsageLocked(template); + mXtRecorder.resetDataUsageLocked(template); + } + @Override protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java old mode 100755 new mode 100644 index cb1cf47c339c9..422aee2e91138 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -24,7 +24,6 @@ import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; -import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppGlobals; @@ -58,14 +57,12 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; +import android.graphics.drawable.Drawable; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioManagerInternal; import android.media.AudioSystem; import android.media.IRingtonePlayer; -import android.media.session.MediaController; -import android.media.session.MediaSessionManager; -import android.media.session.PlaybackState; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -79,6 +76,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -103,6 +101,7 @@ import android.util.LruCache; import android.util.Slog; import android.util.SparseIntArray; +import android.util.TimeUtils; import android.util.Xml; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -123,7 +122,10 @@ import com.android.server.notification.ManagedServices.UserProfiles; import com.android.server.statusbar.StatusBarManagerInternal; +import cyanogenmod.media.AudioSessionInfo; +import cyanogenmod.media.CMAudioManager; import cyanogenmod.providers.CMSettings; +import cyanogenmod.util.ColorUtils; import libcore.io.IoUtils; @@ -248,6 +250,8 @@ public class NotificationManagerService extends SystemService { private boolean mMultipleNotificationLeds; private boolean mMultipleLedsEnabledSetting = false; + private boolean mAutoGenerateNotificationColor = true; + private boolean mScreenOnEnabled = false; private boolean mScreenOnDefault = false; @@ -287,6 +291,8 @@ public class NotificationManagerService extends SystemService { private boolean mNotificationPulseEnabled; private HashMap mNotificationPulseCustomLedValues; private Map mPackageNameMappings; + private final Map mGeneratedPackageLedColors = + new HashMap(); // for checking lockscreen status private KeyguardManager mKeyguardManager; @@ -298,6 +304,7 @@ public class NotificationManagerService extends SystemService { new ArrayMap(); final ArrayList mToastQueue = new ArrayList(); final ArrayMap mSummaryByGroupKey = new ArrayMap<>(); + final ArrayMap mLastSoundTimestamps = new ArrayMap<>(); final PolicyAccess mPolicyAccess = new PolicyAccess(); // The last key in this list owns the hardware. @@ -333,6 +340,8 @@ public class NotificationManagerService extends SystemService { private boolean mDisableDuckingWhileMedia; private boolean mActiveMedia; + private boolean mMultiColorNotificationLed; + private static final int MY_UID = Process.myUid(); private static final int MY_PID = Process.myPid(); private static final int REASON_DELEGATE_CLICK = 1; @@ -702,8 +711,9 @@ public void onNotificationError(int callingUid, int callingPid, String pkg, Stri "Bad notification posted from package " + pkg + ": " + message); } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); } - Binder.restoreCallingIdentity(ident); } @Override @@ -1000,6 +1010,9 @@ void observe() { resolver.registerContentObserver(CMSettings.Global.getUriFor( CMSettings.Global.ZEN_DISABLE_DUCKING_DURING_MEDIA_PLAYBACK), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO), false, + this, UserHandle.USER_ALL); if (mAdjustableNotificationLedBrightness) { resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL), @@ -1024,6 +1037,11 @@ public void update(Uri uri) { mNotificationPulseEnabled = Settings.System.getIntForUser(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0; + // Automatically pick a color for LED if not set + mAutoGenerateNotificationColor = CMSettings.System.getIntForUser(resolver, + CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO, + 1, UserHandle.USER_CURRENT) != 0; + // LED default color mDefaultNotificationColor = CMSettings.System.getIntForUser(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, @@ -1039,6 +1057,9 @@ public void update(Uri uri) { CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF, mDefaultNotificationLedOff, UserHandle.USER_CURRENT); + // LED generated notification colors + mGeneratedPackageLedColors.clear(); + // LED custom notification colors mNotificationPulseCustomLedValues.clear(); if (CMSettings.System.getIntForUser(resolver, @@ -1076,15 +1097,39 @@ public void update(Uri uri) { } } + private BroadcastReceiver mMediaSessionReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateForActiveSessions(); + } + }; + + private void updateForActiveSessions() { + CMAudioManager manager = CMAudioManager.getInstance(getContext()); + List sessions = manager.listAudioSessions(AudioManager.STREAM_MUSIC); + mActiveMedia = false; + for (AudioSessionInfo sessionInfo : sessions) { + if (sessionInfo.getSessionId() > 0) { + mActiveMedia = true; + break; + } + } + } + private void updateDisableDucking() { if (!mSystemReady) { return; } - final MediaSessionManager mediaSessionManager = (MediaSessionManager) getContext() - .getSystemService(Context.MEDIA_SESSION_SERVICE); - mediaSessionManager.removeOnActiveSessionsChangedListener(mSessionListener); + try { + getContext().unregisterReceiver(mMediaSessionReceiver); + } catch (IllegalArgumentException e) { + // Never registered + } if (mDisableDuckingWhileMedia) { - mediaSessionManager.addOnActiveSessionsChangedListener(mSessionListener, null); + updateForActiveSessions(); + IntentFilter intentFilter = new IntentFilter(CMAudioManager + .ACTION_AUDIO_SESSIONS_CHANGED); + getContext().registerReceiver(mMediaSessionReceiver, intentFilter); } } @@ -1182,6 +1227,8 @@ void onPolicyChanged() { mDefaultNotificationLedOff = resources.getInteger( R.integer.config_defaultNotificationLedOff); + mMultiColorNotificationLed = deviceLightsCan(NotificationManager.LIGHTS_RGB_NOTIFICATION); + mNotificationPulseCustomLedValues = new HashMap(); mPackageNameMappings = new HashMap(); @@ -1202,10 +1249,10 @@ void onPolicyChanged() { VIBRATE_PATTERN_MAXLEN, DEFAULT_VIBRATE_PATTERN); - mAdjustableNotificationLedBrightness = resources.getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness); - mMultipleNotificationLeds = resources.getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds); + mAdjustableNotificationLedBrightness = deviceLightsCan( + NotificationManager.LIGHTS_ADJUSTABLE_NOTIFICATION_BRIGHTNESS); + mMultipleNotificationLeds = deviceLightsCan( + NotificationManager.LIGHTS_MULTIPLE_LED); mUseAttentionLight = resources.getBoolean(R.bool.config_useAttentionLight); @@ -1218,6 +1265,8 @@ void onPolicyChanged() { mDisableNotificationEffects = true; } mZenModeHelper.initZenMode(); + mZenModeHelper.readAllowLightsFromSettings(); + mZenModeHelper.readVibrationModeFromSettings(); mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter(); mUserProfiles.updateCache(getContext()); @@ -1346,6 +1395,47 @@ private void updateInterruptionFilterLocked() { scheduleInterruptionFilterChanged(interruptionFilter); } + private int deviceLightsCapabilities() { + Resources resources = getContext().getResources(); + int capabilities = SystemProperties.getInt("sys.lights.capabilities", 0); + + if (capabilities == 0) { + int[] deviceCaps = resources.getIntArray( + com.android.internal.R.array.config_deviceLightCapabilities); + for (int cap : deviceCaps) { + capabilities |= 1< getAppActiveNotifications(String Binder.getCallingUid(), incomingUserId, true, false, "getAppActiveNotifications", pkg); - final int N = mNotificationList.size(); - final ArrayList list = new ArrayList(N); + final ArrayList list + = new ArrayList(mNotificationList.size()); synchronized (mNotificationList) { + final int N = mNotificationList.size(); for (int i = 0; i < N; i++) { final StatusBarNotification sbn = mNotificationList.get(i).sbn; if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId) { @@ -1930,6 +2048,7 @@ private void enforceSystemOrSystemUI(String message) { } private void enforcePolicyAccess(String pkg, String method) { + checkCallerIsSameApp(pkg); if (!checkPolicyAccess(pkg)) { Slog.w(TAG, "Notification policy access denied calling " + method); throw new SecurityException("Notification policy access denied"); @@ -1969,7 +2088,7 @@ public ComponentName getEffectsSuppressor() { } @Override - public boolean matchesCallFilter(Bundle extras) { + public boolean[] matchesCallFilter(Bundle extras) { enforceSystemOrSystemUI("INotificationManager.matchesCallFilter"); return mZenModeHelper.matchesCallFilter( UserHandle.getCallingUserHandle(), @@ -2082,16 +2201,23 @@ public void setNotificationPolicy(String pkg, Policy policy) { Binder.restoreCallingIdentity(identity); } } + + public boolean deviceLightsCan(int lightCapability) { + return ( (deviceLightsCapabilities() & 1< entry: mLastSoundTimestamps.entrySet()) { + pw.print(" " + entry.getKey() + " -> "); + TimeUtils.formatDuration(entry.getValue(), now, pw); + pw.println(" ago"); + } } } @@ -2603,21 +2737,6 @@ private boolean removeUnusedGroupedNotificationLocked(NotificationRecord r, return false; } - private MediaSessionManager.OnActiveSessionsChangedListener mSessionListener = - new MediaSessionManager.OnActiveSessionsChangedListener() { - @Override - public void onActiveSessionsChanged(@Nullable List controllers) { - for (MediaController activeSession : controllers) { - PlaybackState playbackState = activeSession.getPlaybackState(); - if (playbackState != null && playbackState.getState() == PlaybackState.STATE_PLAYING) { - mActiveMedia = true; - return; - } - } - mActiveMedia = false; - } - }; - private void buzzBeepBlinkLocked(NotificationRecord record) { boolean buzz = false; boolean beep = false; @@ -2647,23 +2766,30 @@ private void buzzBeepBlinkLocked(NotificationRecord record) { if (disableEffects != null) { ZenLog.traceDisableEffects(record, disableEffects); } - boolean smsRingtone = getContext().getResources().getBoolean( - com.android.internal.R.bool.config_sms_ringtone_incall); - if ((disableEffects == null || (smsRingtone && mInCall)) + + boolean readyForBeepOrBuzz = disableEffects == null && (!(record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) && (record.getUserId() == UserHandle.USER_ALL || record.getUserId() == currentUser || mUserProfiles.isCurrentProfile(record.getUserId())) - && canInterrupt + && !isInSoundTimeoutPeriod(record) && mSystemReady - && mAudioManager != null) { + && mAudioManager != null; + + boolean canBeep = readyForBeepOrBuzz && canInterrupt; + boolean canBuzz = readyForBeepOrBuzz && + (canInterrupt || (aboveThreshold && mZenModeHelper.allowVibrationForNotifications())); + boolean hasValidSound = false; + + if (canBeep || canBuzz) { if (DBG) Slog.v(TAG, "Interrupting!"); sendAccessibilityEvent(notification, record.sbn.getPackageName()); + } - // sound - + // sound + if (canBeep) { // should we use the default notification sound? (indicated either by // DEFAULT_SOUND or because notification.sound is pointing at // Settings.System.NOTIFICATION_SOUND) @@ -2673,7 +2799,6 @@ private void buzzBeepBlinkLocked(NotificationRecord record) { .equals(notification.sound); Uri soundUri = null; - boolean hasValidSound = false; if (useDefaultSound) { soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; @@ -2714,15 +2839,17 @@ private void buzzBeepBlinkLocked(NotificationRecord record) { } } } + } + - // vibrate + // vibrate + if (canBuzz) { // Does the notification want to specify its own vibration? final boolean hasCustomVibrate = notification.vibrate != null; // new in 4.2: if there was supposed to be a sound and we're in vibrate // mode, and no other vibration is specified, we fall back to vibration - final boolean convertSoundToVibration = - !hasCustomVibrate + final boolean convertSoundToVibration = !hasCustomVibrate && hasValidSound && (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE); @@ -2765,8 +2892,9 @@ private void buzzBeepBlinkLocked(NotificationRecord record) { // light // release the light boolean wasShowLights = mLights.remove(record.getKey()); - final boolean aboveThresholdWithLight = aboveThreshold || isLedNotificationForcedOn(record); - if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThresholdWithLight) { + final boolean canInterruptWithLight = canInterrupt || isLedNotificationForcedOn(record) + || (!canInterrupt && mZenModeHelper.getAllowLights()); + if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && canInterruptWithLight) { mLights.add(record.getKey()); updateLightsLocked(); if (mUseAttentionLight) { @@ -2776,6 +2904,10 @@ private void buzzBeepBlinkLocked(NotificationRecord record) { } else if (wasShowLights) { updateLightsLocked(); } + if (buzz || beep) { + mLastSoundTimestamps.put(generateLastSoundTimeoutKey(record), + SystemClock.elapsedRealtime()); + } if (buzz || beep || blink) { EventLogTags.writeNotificationAlert(record.getKey(), buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0); @@ -2783,6 +2915,24 @@ private void buzzBeepBlinkLocked(NotificationRecord record) { } } + private boolean isInSoundTimeoutPeriod(NotificationRecord record) { + long timeoutMillis = mRankingHelper.getPackageNotificationSoundTimeout( + record.sbn.getPackageName(), record.sbn.getUid()); + if (timeoutMillis == 0) { + return false; + } + + Long value = mLastSoundTimestamps.get(generateLastSoundTimeoutKey(record)); + if (value == null) { + return false; + } + return SystemClock.elapsedRealtime() - value < timeoutMillis; + } + + private String generateLastSoundTimeoutKey(NotificationRecord record) { + return record.sbn.getPackageName() + "|" + record.sbn.getUid(); + } + private static AudioAttributes audioAttributesForNotification(Notification n) { if (n.audioAttributes != null && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) { @@ -3430,7 +3580,7 @@ void updateLightsLocked() ledOnMS = ledValues.onMS >= 0 ? ledValues.onMS : mDefaultNotificationLedOn; ledOffMS = ledValues.offMS >= 0 ? ledValues.offMS : mDefaultNotificationLedOff; } else if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) { - ledARGB = mDefaultNotificationColor; + ledARGB = generateLedColorForNotification(ledNotification); ledOnMS = mDefaultNotificationLedOn; ledOffMS = mDefaultNotificationLedOff; } else { @@ -3491,6 +3641,36 @@ private NotificationLedValues getLedValuesForNotification(NotificationRecord led return mNotificationPulseCustomLedValues.get(mapPackage(packageName)); } + private int generateLedColorForNotification(NotificationRecord ledNotification) { + if (!mAutoGenerateNotificationColor) { + return mDefaultNotificationColor; + } + if (!mMultiColorNotificationLed) { + return mDefaultNotificationColor; + } + final String packageName = ledNotification.sbn.getPackageName(); + final String mapping = mapPackage(packageName); + int color = mDefaultNotificationColor; + + if (mGeneratedPackageLedColors.containsKey(mapping)) { + return mGeneratedPackageLedColors.get(mapping); + } + + PackageManager pm = getContext().getPackageManager(); + Drawable icon; + try { + icon = pm.getApplicationIcon(mapping); + } catch (NameNotFoundException e) { + Slog.e(TAG, e.getMessage(), e); + return color; + } + + color = ColorUtils.generateAlertColorFromDrawable(icon); + mGeneratedPackageLedColors.put(mapping, color); + + return color; + } + private String mapPackage(String pkg) { if (!mPackageNameMappings.containsKey(pkg)) { return pkg; @@ -3550,6 +3730,10 @@ private static void checkCallerIsSystemOrSameApp(String pkg) { if (isCallerSystem()) { return; } + checkCallerIsSameApp(pkg); + } + + private static void checkCallerIsSameApp(String pkg) { final int uid = Binder.getCallingUid(); try { ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo( diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index 803db10cd03f6..320cf758600e3 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -27,4 +27,9 @@ public interface RankingConfig { int getPackageVisibilityOverride(String packageName, int uid); void setPackageVisibilityOverride(String packageName, int uid, int visibility); + + void setShowNotificationForPackageOnKeyguard(String packageName, int uid, int status); + + int getShowNotificationForPackageOnKeyguard(String packageName, int uid); + } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index a089518c53b8c..233eb0a4bd88d 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -51,6 +51,8 @@ public class RankingHelper implements RankingConfig { private static final String ATT_PRIORITY = "priority"; private static final String ATT_PEEKABLE = "peekable"; private static final String ATT_VISIBILITY = "visibility"; + private static final String ATT_KEYGUARD = "keyguard"; + private static final String ATT_SOUND_TIMEOUT = "sound-timeout"; private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT; private static final boolean DEFAULT_PEEKABLE = true; @@ -143,6 +145,9 @@ public void readXml(XmlPullParser parser, boolean forRestore) int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); boolean peekable = safeBool(parser, ATT_PEEKABLE, DEFAULT_PEEKABLE); int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); + int keyguard = safeInt(parser, ATT_KEYGUARD, + Notification.SHOW_ALL_NOTI_ON_KEYGUARD); + long soundTimeout = safeInt(parser, ATT_SOUND_TIMEOUT, 0); String name = parser.getAttributeValue(null, ATT_NAME); if (!TextUtils.isEmpty(name)) { @@ -172,6 +177,12 @@ public void readXml(XmlPullParser parser, boolean forRestore) if (vis != DEFAULT_VISIBILITY) { r.visibility = vis; } + if (keyguard != Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { + r.keyguard = keyguard; + } + if (soundTimeout != 0) { + r.notificationSoundTimeout = soundTimeout; + } } } } @@ -200,8 +211,10 @@ private void removeDefaultRecords() { for (int i = N - 1; i >= 0; i--) { final Record r = mRecords.valueAt(i); if (r.priority == DEFAULT_PRIORITY && r.peekable == DEFAULT_PEEKABLE - && r.visibility == DEFAULT_VISIBILITY) { - mRecords.remove(i); + && r.visibility == DEFAULT_VISIBILITY + && r.keyguard == Notification.SHOW_ALL_NOTI_ON_KEYGUARD + && r.notificationSoundTimeout == 0) { + mRecords.removeAt(i); } } } @@ -227,6 +240,12 @@ public void writeXml(XmlSerializer out, boolean forBackup) throws IOException { if (r.visibility != DEFAULT_VISIBILITY) { out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); } + if (r.keyguard != Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { + out.attribute(null, ATT_KEYGUARD, Integer.toBinaryString(r.keyguard)); + } + if (r.notificationSoundTimeout != 0) { + out.attribute(null, ATT_SOUND_TIMEOUT, Long.toString(r.notificationSoundTimeout)); + } if (!forBackup) { out.attribute(null, ATT_UID, Integer.toString(r.uid)); } @@ -377,6 +396,36 @@ public void setPackageVisibilityOverride(String packageName, int uid, int visibi updateConfig(); } + @Override + public int getShowNotificationForPackageOnKeyguard(String packageName, int uid) { + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.keyguard : Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + } + + @Override + public void setShowNotificationForPackageOnKeyguard( + String packageName, int uid, int keyguard) { + if (keyguard == getShowNotificationForPackageOnKeyguard(packageName, uid)) { + return; + } + getOrCreateRecord(packageName, uid).keyguard = keyguard; + removeDefaultRecords(); + updateConfig(); + } + + public long getPackageNotificationSoundTimeout(String packageName, int uid) { + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.notificationSoundTimeout : 0; + } + + public void setPackageNotificationSoundTimeout(String packageName, int uid, long timeout) { + if (timeout == getPackageNotificationSoundTimeout(packageName, uid)) { + return; + } + getOrCreateRecord(packageName, uid).notificationSoundTimeout = timeout; + removeDefaultRecords(); + } + public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; @@ -459,6 +508,8 @@ private static class Record { int priority = DEFAULT_PRIORITY; boolean peekable = DEFAULT_PEEKABLE; int visibility = DEFAULT_VISIBILITY; + int keyguard = Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + long notificationSoundTimeout = 0; } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 461c3a26ddd7e..54eac0622d536 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -53,6 +53,7 @@ import com.android.internal.R; import com.android.internal.logging.MetricsLogger; import com.android.server.LocalServices; +import cyanogenmod.providers.CMSettings; import libcore.io.IoUtils; @@ -89,6 +90,8 @@ public class ZenModeHelper { private ZenModeConfig mConfig; private AudioManagerInternal mAudioManager; private boolean mEffectsSuppressed; + private boolean mAllowLights; + private int mVibrationMode; public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { mContext = context; @@ -115,10 +118,12 @@ public String toString() { return TAG; } - public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, + public boolean[] matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) { - return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle, extras, - validator, contactsTimeoutMs, timeoutAffinity); + boolean matches = ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, + userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity); + boolean matchesForVibration = matches || allowVibrationForCalls(); + return new boolean[] { matches, matchesForVibration }; } public boolean isCall(NotificationRecord record) { @@ -236,6 +241,8 @@ public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mUser="); pw.println(mUser); dump(pw, prefix, "mConfig", mConfig); pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed); + pw.print(prefix); pw.print("mAllowLights="); pw.println(mAllowLights); + pw.print(prefix); pw.print("mVibrationMode="); pw.println(mVibrationMode); mFiltering.dump(pw, prefix); mConditions.dump(pw, prefix); } @@ -378,6 +385,8 @@ private boolean evaluateZenMode(String reason, boolean setRingerMode) { ZenLog.traceSetZenMode(zen, reason); mZenMode = zen; updateRingerModeAffectedStreams(); + readAllowLightsFromSettings(); + readVibrationModeFromSettings(); setZenModeSetting(mZenMode); if (setRingerMode) { applyZenToRingerMode(); @@ -407,6 +416,39 @@ private int computeZenMode(ArraySet automaticRulesOut) { return zen; } + public boolean getAllowLights() { + return mAllowLights; + } + + public void readAllowLightsFromSettings() { + switch (mZenMode) { + case Global.ZEN_MODE_NO_INTERRUPTIONS: + case Global.ZEN_MODE_ALARMS: + mAllowLights = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.ZEN_ALLOW_LIGHTS, 1) == 1; + break; + case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: + mAllowLights = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS, 1) == 1; + break; + } + } + + public boolean allowVibrationForCalls() { + return mVibrationMode > 0; + } + + public boolean allowVibrationForNotifications() { + return mVibrationMode > 1; + } + + public void readVibrationModeFromSettings() { + final ContentResolver cr = mContext.getContentResolver(); + mVibrationMode = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS + ? CMSettings.System.getInt(cr, CMSettings.System.ZEN_PRIORITY_VIBRATION_MODE, 0) + : 0; + } + private void applyRestrictions() { final boolean zen = mZenMode != Global.ZEN_MODE_OFF; @@ -415,13 +457,14 @@ private void applyRestrictions() { applyRestrictions(muteNotifications, USAGE_NOTIFICATION); // call restrictions - final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers - || mEffectsSuppressed; + final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers; applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE); // alarm restrictions final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; applyRestrictions(muteAlarms, USAGE_ALARM); + + readAllowLightsFromSettings(); } private void applyRestrictions(boolean mute, int usage) { @@ -692,6 +735,12 @@ public int getRingerModeAffectedStreams(int streams) { private final class SettingsObserver extends ContentObserver { private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); + private final Uri ZEN_ALLOW_LIGHTS = CMSettings.System.getUriFor( + CMSettings.System.ZEN_ALLOW_LIGHTS); + private final Uri ZEN_PRIORITY_ALLOW_LIGHTS = CMSettings.System.getUriFor( + CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS); + private final Uri ZEN_PRIORITY_VIBRATION_MODE = CMSettings.System.getUriFor( + CMSettings.System.ZEN_PRIORITY_VIBRATION_MODE); public SettingsObserver(Handler handler) { super(handler); @@ -700,6 +749,12 @@ public SettingsObserver(Handler handler) { public void observe() { final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); + resolver.registerContentObserver( + ZEN_ALLOW_LIGHTS, false /*notifyForDescendents*/, this); + resolver.registerContentObserver( + ZEN_PRIORITY_ALLOW_LIGHTS, false /*notifyForDescendents*/, this); + resolver.registerContentObserver( + ZEN_PRIORITY_VIBRATION_MODE, false /*notifyForDescendents*/, this); update(null); } @@ -714,6 +769,10 @@ public void update(Uri uri) { if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); setZenModeSetting(mZenMode); } + } else if (ZEN_ALLOW_LIGHTS.equals(uri) || ZEN_PRIORITY_ALLOW_LIGHTS.equals(uri)) { + readAllowLightsFromSettings(); + } else if (ZEN_PRIORITY_VIBRATION_MODE.equals(uri)) { + readVibrationModeFromSettings(); } } } diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index df023fd8be5d3..29e9fa6cc756c 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -572,6 +572,26 @@ && doesPackageSupportRuntimePermissions(musicPackage)) { grantRuntimePermissionsLPw(musicPackage, STORAGE_PERMISSIONS, userId); } + // Android Wear Home + if (mService.hasSystemFeature(PackageManager.FEATURE_WATCH)) { + Intent homeIntent = new Intent(Intent.ACTION_MAIN); + homeIntent.addCategory(Intent.CATEGORY_HOME_MAIN); + + PackageParser.Package wearHomePackage = getDefaultSystemHandlerActivityPackageLPr( + homeIntent, userId); + + if (wearHomePackage != null + && doesPackageSupportRuntimePermissions(wearHomePackage)) { + grantRuntimePermissionsLPw(wearHomePackage, CONTACTS_PERMISSIONS, false, + userId); + grantRuntimePermissionsLPw(wearHomePackage, PHONE_PERMISSIONS, true, userId); + grantRuntimePermissionsLPw(wearHomePackage, MICROPHONE_PERMISSIONS, false, + userId); + grantRuntimePermissionsLPw(wearHomePackage, LOCATION_PERMISSIONS, false, + userId); + } + } + mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId); } } @@ -579,7 +599,10 @@ && doesPackageSupportRuntimePermissions(musicPackage)) { private void grantDefaultPermissionsToDefaultSystemDialerAppLPr( PackageParser.Package dialerPackage, int userId) { if (doesPackageSupportRuntimePermissions(dialerPackage)) { - grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, userId); + boolean isPhonePermFixed = + mService.hasSystemFeature(PackageManager.FEATURE_WATCH); + grantRuntimePermissionsLPw( + dialerPackage, PHONE_PERMISSIONS, isPhonePermFixed, userId); grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId); grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId); grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId); diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 5f183a2456724..4be7e2585327a 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -129,7 +129,7 @@ public int idmap(String targetApkPath, String overlayApkPath, String cachePath, } public int aapt(String themeApkPath, String internalPath, String resTablePath, int uid, - int pkgId, int minSdkVersion, String commonResourcesPath) { + int pkgId, int minSdkVersion, String appResourcesPath, String commonResourcesPath) { StringBuilder builder = new StringBuilder(); if (TextUtils.isEmpty(commonResourcesPath)) { @@ -149,6 +149,8 @@ public int aapt(String themeApkPath, String internalPath, String resTablePath, i builder.append(pkgId); builder.append(' '); builder.append(minSdkVersion); + builder.append(' '); + builder.append(appResourcesPath); if (!TextUtils.isEmpty(commonResourcesPath)) { builder.append(' '); diff --git a/services/core/java/com/android/server/pm/MultiTaskDealer.java b/services/core/java/com/android/server/pm/MultiTaskDealer.java new file mode 100644 index 0000000000000..9b8d46ecc556d --- /dev/null +++ b/services/core/java/com/android/server/pm/MultiTaskDealer.java @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.android.server.pm; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantLock; + +import android.util.Log; + +public class MultiTaskDealer { + + public static final String TAG = "MultiTaskDealer"; + public static final String PACKAGEMANAGER_SCANER = "packagescan"; + private static final boolean DEBUG_TASK = false; + + private static HashMap> map = new HashMap>(); + + public static MultiTaskDealer getDealer(String name) { + WeakReference ref = map.get(name); + MultiTaskDealer dealer = ref!=null?ref.get():null; + return dealer; + } + + public static MultiTaskDealer startDealer(String name,int taskCount) { + MultiTaskDealer dealer = getDealer(name); + if(dealer==null) { + dealer = new MultiTaskDealer(name,taskCount); + WeakReference ref = new WeakReference(dealer); + map.put(name,ref); + } + return dealer; + } + + public void startLock() { + mLock.lock(); + } + + public void endLock() { + mLock.unlock(); + } + + private ThreadPoolExecutor mExecutor; + private int mTaskCount = 0; + private boolean mNeedNotifyEnd = false; + private Object mObjWaitAll = new Object(); + private ReentrantLock mLock = new ReentrantLock(); + + public MultiTaskDealer(String name,int taskCount) { + final String taskName = name; + ThreadFactory factory = new ThreadFactory() + { + private final AtomicInteger mCount = new AtomicInteger(1); + + public Thread newThread(final Runnable r) { + if (DEBUG_TASK) Log.d(TAG, "create a new thread:" + taskName); + return new Thread(r, taskName + "-" + mCount.getAndIncrement()); + } + }; + mExecutor = new ThreadPoolExecutor(taskCount, taskCount, 5, TimeUnit.SECONDS, + new LinkedBlockingQueue(), factory){ + protected void afterExecute(Runnable r, Throwable t) { + if(t!=null) { + t.printStackTrace(); + } + MultiTaskDealer.this.TaskCompleteNotify(r); + if (DEBUG_TASK) Log.d(TAG, "end task"); + super.afterExecute(r,t); + } + protected void beforeExecute(Thread t, Runnable r) { + if (DEBUG_TASK) Log.d(TAG, "start task"); + super.beforeExecute(t,r); + } + }; + } + + public void addTask(Runnable task) { + synchronized (mObjWaitAll) { + mTaskCount+=1; + } + mExecutor.execute(task); + if (DEBUG_TASK) Log.d(TAG, "addTask"); + } + + private void TaskCompleteNotify(Runnable task) { + synchronized (mObjWaitAll) { + mTaskCount-=1; + if(mTaskCount<=0 && mNeedNotifyEnd) { + if (DEBUG_TASK) Log.d(TAG, "complete notify"); + mObjWaitAll.notify(); + } + } + } + + public void waitAll() { + if (DEBUG_TASK) Log.d(TAG, "start wait all"); + synchronized (mObjWaitAll) { + if(mTaskCount>0) { + mNeedNotifyEnd = true; + try { + mObjWaitAll.wait(); + } catch (Exception e) { + } + mNeedNotifyEnd = false; + } + if (DEBUG_TASK) Log.d(TAG, "wait finish"); + return; + } + } +} diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index f73cb0a1fa641..fa11ff8464dbd 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -57,6 +57,8 @@ final class PackageDexOptimizer { private final PowerManager.WakeLock mDexoptWakeLock; private volatile boolean mSystemReady; + private Object mDeferredDexOptSync = new Object(); + PackageDexOptimizer(PackageManagerService packageManagerService) { this.mPackageManagerService = packageManagerService; PowerManager powerManager = (PowerManager)packageManagerService.mContext.getSystemService( @@ -150,7 +152,9 @@ private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructio // We're deciding to defer a needed dexopt. Don't bother dexopting for other // paths and instruction sets. We'll deal with them all together when we process // our list of deferred dexopts. - addPackageForDeferredDexopt(pkg); + synchronized (mDeferredDexOptSync) { + addPackageForDeferredDexopt(pkg); + } return DEX_OPT_DEFERRED; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 358b7739b3127..920a8500beadc 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2006 The Android Open Source Project * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. * @@ -17,7 +20,6 @@ package com.android.server.pm; -import static android.Manifest.permission.ACCESS_THEME_MANAGER; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_MEDIA_STORAGE; @@ -92,6 +94,7 @@ import android.Manifest; +import cyanogenmod.app.CMContextConstants; import cyanogenmod.app.suggest.AppSuggestManager; import android.app.ActivityManager; @@ -156,14 +159,12 @@ import android.content.pm.Signature; import android.content.pm.UserInfo; import android.content.pm.ManifestDigest; -import android.content.pm.ThemeUtils; import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.res.Resources; import android.content.res.AssetManager; import android.content.res.ThemeConfig; -import android.content.res.ThemeManager; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Debug; @@ -222,6 +223,8 @@ import android.view.Display; import cyanogenmod.providers.CMSettings; +import cyanogenmod.themes.IThemeService; + import dalvik.system.DexFile; import dalvik.system.VMRuntime; @@ -248,12 +251,14 @@ import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemConfig; +import com.android.server.SystemConfig.AppLink; import com.android.server.Watchdog; import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; import com.android.server.pm.Settings.VersionInfo; import com.android.server.storage.DeviceStorageMonitorInternal; +import org.cyanogenmod.internal.util.ThemeUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -303,8 +308,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * Keep track of all those .apks everywhere. @@ -334,8 +337,10 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DEBUG_PACKAGE_SCANNING = false; private static final boolean DEBUG_VERIFY = false; private static final boolean DEBUG_DEXOPT = false; + private static final boolean DEBUG_FILTERS = false; private static final boolean DEBUG_ABI_SELECTION = false; private static final boolean DEBUG_PREBUNDLED_SCAN = false; + private static final boolean DEBUG_PROTECTED = false; static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false; @@ -462,6 +467,9 @@ public class PackageManagerService extends IPackageManager.Stub { private static final long COMMON_RESOURCE_EXPIRATION = 3*60*1000; // 3 minutes + private static final String PROTECTED_APPS_TARGET_VALIDATION_COMPONENT = + "com.android.settings/com.android.settings.applications.ProtectedAppsActivity"; + /** * The offset in bytes to the beginning of the hashes in an idmap */ @@ -613,7 +621,7 @@ public static final class SharedLibraryEntry { final ArraySet mTransferedPackages = new ArraySet(); // Broadcast actions that are only available to the system. - final ArraySet mProtectedBroadcasts = new ArraySet(); + final ArrayMap mProtectedBroadcasts = new ArrayMap<>(); /** List of packages waiting for verification. */ final SparseArray mPendingVerification @@ -1461,7 +1469,8 @@ void doHandleMessage(Message msg) { } String category = null; if(res.pkg.mIsThemeApk) { - category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; + category = cyanogenmod.content.Intent + .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, null, extras, null, null, updateUsers); @@ -1487,6 +1496,17 @@ void doHandleMessage(Message msg) { // if this was a theme, send it off to the theme service for processing if(res.pkg.mIsThemeApk || res.pkg.mIsLegacyIconPackApk) { processThemeResourcesInThemeService(res.pkg.packageName); + } else if (mOverlays.containsKey(res.pkg.packageName)) { + + // if this was an app and is themed send themes that theme it + // for processing + ArrayMap themes = + mOverlays.get(res.pkg.packageName); + + for (PackageParser.Package themePkg : themes.values()) { + processThemeResourcesInThemeService(themePkg.packageName); + } + } if (res.removedInfo.args != null) { // Remove the replaced package's older resources safely now @@ -1895,7 +1915,9 @@ public PackageManagerService(Context context, Installer installer, mContext = context; mFactoryTest = factoryTest; mOnlyCore = onlyCore; - mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type")); + mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type")) || + ("userdebug".equals(SystemProperties.get("ro.build.type")) && + SystemProperties.getBoolean("persist.sys.lazy.dexopt", false)); mMetrics = new DisplayMetrics(); mSettings = new Settings(mPackages); mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID, @@ -1956,9 +1978,9 @@ public PackageManagerService(Context context, Installer installer, mAvailableFeatures = systemConfig.getAvailableFeatures(); mSignatureAllowances = systemConfig.getSignatureAllowances(); - synchronized (mInstallLock) { +// synchronized (mInstallLock) { // writer - synchronized (mPackages) { +// synchronized (mPackages) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); @@ -2482,8 +2504,8 @@ public PackageManagerService(Context context, Installer installer, mIntentFilterVerifier = new IntentVerifierProxy(mContext, mIntentFilterVerifierComponent); - } // synchronized (mPackages) - } // synchronized (mInstallLock) + //} // synchronized (mPackages) + //} // synchronized (mInstallLock) // Now after opening every single application zip, make sure they // are all flushed. Not really needed, but keeps things nice and @@ -2620,10 +2642,11 @@ private void primeDomainVerificationsLPw(int userId) { } SystemConfig systemConfig = SystemConfig.getInstance(); - ArraySet packages = systemConfig.getLinkedApps(); + ArraySet links = systemConfig.getLinkedApps(); ArraySet domains = new ArraySet(); - for (String packageName : packages) { + for (AppLink link : links) { + String packageName = link.pkgname; PackageParser.Package pkg = mPackages.get(packageName); if (pkg != null) { if (!pkg.isSystemApp()) { @@ -2648,11 +2671,11 @@ private void primeDomainVerificationsLPw(int userId) { // state w.r.t. the formal app-linkage "no verification attempted" state; // and then 'always' in the per-user state actually used for intent resolution. final IntentFilterVerificationInfo ivi; - ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName, - new ArrayList(domains)); + ivi = mSettings.createIntentFilterVerificationIfNeededLPw( + packageName, new ArrayList(domains)); ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED); - mSettings.updateIntentFilterVerificationStatusLPw(packageName, - INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, userId); + mSettings.updateIntentFilterVerificationStatusLPw( + packageName, link.state, userId); } else { Slog.w(TAG, "Sysconfig package '" + packageName + "' does not handle web links"); @@ -4022,7 +4045,19 @@ public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener liste @Override public boolean isProtectedBroadcast(String actionName) { synchronized (mPackages) { - return mProtectedBroadcasts.contains(actionName); + return mProtectedBroadcasts.containsKey(actionName); + } + } + + @Override + public boolean isProtectedBroadcastAllowed(String actionName, int callingUid) { + synchronized (mPackages) { + if (mProtectedBroadcasts.containsKey(actionName)) { + final int result = checkUidPermission(mProtectedBroadcasts.get(actionName), + callingUid); + return result == PackageManager.PERMISSION_GRANTED; + } + return false; } } @@ -4695,10 +4730,14 @@ private List getMatchingCrossProfileIntentFilters(Inte } private boolean shouldIncludeResolveActivity(Intent intent) { - synchronized(mPackages) { - AppSuggestManager suggest = AppSuggestManager.getInstance(mContext); - return mResolverReplaced && (suggest != null) ? suggest.handles(intent) : false; + // Don't call into AppSuggestManager before it comes up later in the SystemServer init! + if (!mSystemReady || mOnlyCore) { + return false; } + + AppSuggestManager suggest = AppSuggestManager.getInstance(mContext); + return mResolverReplaced && (suggest.getService() != null) ? + suggest.handles(intent) : false; } @Override @@ -5791,7 +5830,7 @@ private boolean createIdmapForPackagePairLI(PackageParser.Package pkg, } private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime, - UserHandle user) { + final UserHandle user) { final File[] files = dir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + dir); @@ -5803,8 +5842,8 @@ private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime + " flags=0x" + Integer.toHexString(parseFlags)); } - int prebundledUserId = user == null ? UserHandle.USER_OWNER : user.getIdentifier(); - boolean isPrebundled = (parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0; + final int prebundledUserId = user == null ? UserHandle.USER_OWNER : user.getIdentifier(); + final boolean isPrebundled = (parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0; if (isPrebundled) { synchronized (mPackages) { if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, "Reading prebundled packages for user " @@ -5813,6 +5852,13 @@ private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime } } + Log.d(TAG, "start scanDirLI:"+dir); + // use multi thread to speed up scanning + int iMultitaskNum = SystemProperties.getInt("persist.pm.multitask", 6); + Log.d(TAG, "max thread:" + iMultitaskNum); + final MultiTaskDealer dealer = (iMultitaskNum > 1) ? MultiTaskDealer.startDealer( + MultiTaskDealer.PACKAGEMANAGER_SCANER, iMultitaskNum) : null; + for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); @@ -5820,43 +5866,64 @@ private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime // Ignore entries which are not packages continue; } - try { - scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, - scanFlags, currentTime, user); - if (isPrebundled) { - final PackageParser.Package pkg; + + final File ref_file = file; + final int ref_parseFlags = parseFlags; + final int ref_scanFlags = scanFlags; + final long ref_currentTime = currentTime; + + Runnable scanTask = new Runnable() { + public void run() { + try { - pkg = new PackageParser().parsePackage(file, parseFlags); - } catch (PackageParserException e) { - throw PackageManagerException.from(e); - } - synchronized (mPackages) { - if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, - "Marking prebundled packages for user " + prebundledUserId); - mSettings.markPrebundledPackageInstalledLPr(prebundledUserId, - pkg.packageName); - // do this for every other user - for (UserInfo userInfo : sUserManager.getUsers(true)) { - if (userInfo.id == prebundledUserId) continue; - mSettings.markPrebundledPackageInstalledLPr(userInfo.id, + scanPackageLI(ref_file, ref_parseFlags | PackageParser.PARSE_MUST_BE_APK, + ref_scanFlags, ref_currentTime, user); + if (isPrebundled) { + final PackageParser.Package pkg; + try { + pkg = new PackageParser().parsePackage(ref_file, ref_parseFlags); + } catch (PackageParserException e) { + throw PackageManagerException.from(e); + } + if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, + "Marking prebundled package " + pkg.packageName + + " for user " + prebundledUserId); + mSettings.markPrebundledPackageInstalledLPr(prebundledUserId, pkg.packageName); + // do this for every other user + for (UserInfo userInfo : sUserManager.getUsers(true)) { + if (userInfo.id == prebundledUserId) continue; + if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, + "Marking for secondary user " + userInfo.id); + mSettings.markPrebundledPackageInstalledLPr(userInfo.id, + pkg.packageName); + } + } + } catch (PackageManagerException e) { + Slog.w(TAG, "Failed to parse " + ref_file + ": " + e.getMessage()); + + // Delete invalid userdata apps + if ((ref_parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && + e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { + logCriticalInfo(Log.WARN, "Deleting invalid package at " + ref_file); + if (ref_file.isDirectory()) { + mInstaller.rmPackageDir(ref_file.getAbsolutePath()); + } else { + ref_file.delete(); + } } } } - } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); + }; - // Delete invalid userdata apps - if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && - e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { - logCriticalInfo(Log.WARN, "Deleting invalid package at " + file); - if (file.isDirectory()) { - mInstaller.rmPackageDir(file.getAbsolutePath()); - } else { - file.delete(); - } - } - } + if (dealer != null) + dealer.addTask(scanTask); + else + scanTask.run(); + } + + if (dealer != null) { + dealer.waitAll(); } if (isPrebundled) { @@ -5866,6 +5933,8 @@ private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime mSettings.writePrebundledPackagesLPr(prebundledUserId); } } + + Log.d(TAG, "end scanDirLI:"+dir); } private static File getSettingsProblemFile() { @@ -5879,7 +5948,7 @@ static void reportSettingsProblem(int priority, String msg) { logCriticalInfo(priority, msg); } - static void logCriticalInfo(int priority, String msg) { + static synchronized void logCriticalInfo(int priority, String msg) { Slog.println(priority, TAG, msg); EventLogTags.writePmCriticalInfo(msg); try { @@ -5969,15 +6038,17 @@ private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int s if ((parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0) { synchronized (mPackages) { PackageSetting existingSettings = mSettings.peekPackageLPr(pkg.packageName); - if (mSettings.wasPrebundledPackageInstalledLPr(user.getIdentifier() - , pkg.packageName) && existingSettings == null) { - // The prebundled app was installed at some point in time, but now it is - // gone. Assume that the user uninstalled it intentionally: do not reinstall. + + if (!mSettings.shouldPrebundledPackageBeInstalledForUserLPr(existingSettings, + user.getIdentifier(), pkg.packageName)) { + // The prebundled app was installed at some point for the owner and isn't + // currently installed for the owner, dont install it for a new user + // OR the prebundled app was installed for the user at some point and isn't + // current installed for the user, so skip reinstalling it throw new PackageManagerException(INSTALL_FAILED_UNINSTALLED_PREBUNDLE, "skip reinstall for " + pkg.packageName); - } else if (existingSettings == null && - !mSettings.shouldPrebundledPackageBeInstalled(mContext.getResources(), - pkg.packageName, mCustomResources)) { + } else if (!mSettings.shouldPrebundledPackageBeInstalledForRegion( + mContext.getResources(), pkg.packageName, mCustomResources)) { // The prebundled app is not needed for the default mobile country code, // skip installing it throw new PackageManagerException(INSTALL_FAILED_REGION_LOCKED_PREBUNDLE, @@ -6293,9 +6364,8 @@ public void performBootDexOpt() { if (doTrim) { if (!isFirstBoot()) { try { - ActivityManagerNative.getDefault().showBootMessage( - mContext.getResources().getString( - R.string.android_upgrading_fstrim), true); + ActivityManagerNative.getDefault().updateBootProgress( + IActivityManager.BOOT_STAGE_FSTRIM, null, 0, 0, true); } catch (RemoteException e) { } } @@ -6422,9 +6492,9 @@ private void performBootDexOpt(PackageParser.Package pkg, int curr, int total) { Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName); } try { - ActivityManagerNative.getDefault().showBootMessage( - mContext.getResources().getString(R.string.android_upgrading_apk, - curr, total), true); + ActivityManagerNative.getDefault().updateBootProgress( + IActivityManager.BOOT_STAGE_PREPARING_APPS, + pkg.applicationInfo, curr, total, true); } catch (RemoteException e) { } PackageParser.Package p = pkg; @@ -7452,6 +7522,25 @@ private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int KeySetManagerService ksms = mSettings.mKeySetManagerService; ksms.assertScannedPackageValid(pkg); + // Get the current theme config. We do this outside the lock + // since ActivityManager might be waiting on us already + // and a deadlock would result. + final boolean isBootScan = (scanFlags & SCAN_BOOTING) != 0; + ThemeConfig config = mBootThemeConfig; + if (!isBootScan) { + final IActivityManager am = ActivityManagerNative.getDefault(); + try { + if (am != null) { + config = am.getConfiguration().themeConfig; + } else { + Log.w(TAG, "ActivityManager getDefault() " + + "returned null, cannot compile app's theme"); + } + } catch(RemoteException e) { + Log.w(TAG, "Failed to get the theme config from ActivityManager"); + } + } + // writer synchronized (mPackages) { // We don't expect installation to fail beyond this point @@ -7793,32 +7882,36 @@ private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int if (pkg.protectedBroadcasts != null) { N = pkg.protectedBroadcasts.size(); for (i=0; i themes = mOverlays.get(pkg.packageName); - for(PackageParser.Package themePkg : themes.values()) { - if (!isBootScan || (mBootThemeConfig != null && - (themePkg.packageName.equals(mBootThemeConfig.getOverlayPkgName()) || + + if (config != null) { + for(PackageParser.Package themePkg : themes.values()) { + if (themePkg.packageName.equals(config.getOverlayPkgName()) || themePkg.packageName.equals( - mBootThemeConfig.getOverlayPkgNameForApp(pkg.packageName))))) { - try { - compileResourcesAndIdmapIfNeeded(pkg, themePkg); - } catch (Exception e) { - // Do not stop a pkg installation just because of one bad theme - // Also we don't break here because we should try to compile other - // themes - Slog.w(TAG, "Unable to compile " + themePkg.packageName - + " for target " + pkg.packageName, e); - themePkg.mOverlayTargets.remove(pkg.packageName); + config.getOverlayPkgNameForApp(pkg.packageName))) { + try { + compileResourcesAndIdmapIfNeeded(pkg, themePkg); + } catch (Exception e) { + // Do not stop a pkg installation just because of one bad theme + // Also we don't break here because we should try to compile other + // themes + Slog.w(TAG, "Unable to compile " + themePkg.packageName + + " for target " + pkg.packageName, e); + themePkg.mOverlayTargets.remove(pkg.packageName); + } } } } @@ -7852,10 +7945,22 @@ private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int } if (failedException != null) { - Slog.w(TAG, "Unable to process theme " + pkgName + " for " + target, - failedException); - // remove target from mOverlayTargets - iterator.remove(); + if (failedException instanceof AaptException && + ((AaptException) failedException).isCommon) { + Slog.e(TAG, "Unable to process common resources for " + pkgName + + ", uninstalling theme.", failedException); + uninstallThemeForAllApps(pkg); + deletePackageLI(pkg.packageName, null, true, null, null, 0, null, + false); + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_THEME_AAPT_ERROR, + "Unable to process theme " + pkgName, failedException); + } else { + Slog.w(TAG, "Unable to process theme " + pkgName + " for " + target, + failedException); + // remove target from mOverlayTargets + iterator.remove(); + } } } } @@ -8228,8 +8333,15 @@ private void generateIdmap(String target, PackageParser.Package opkg) throws Idm } public class AaptException extends Exception { + boolean isCommon; + public AaptException(String message) { + this(message, false); + } + + public AaptException(String message, boolean isCommon) { super(message); + this.isCommon = isCommon; } } @@ -8255,21 +8367,29 @@ private void compileResourcesWithAapt(String target, PackageParser.Package pkg) String internalPath = APK_PATH_TO_OVERLAY + target + File.separator; String resPath = ThemeUtils.getTargetCacheDir(target, pkg); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + final boolean isCommonResources = COMMON_OVERLAY.equals(target); int pkgId; if ("android".equals(target)) { pkgId = Resources.THEME_FRAMEWORK_PKG_ID; - } else if (COMMON_OVERLAY.equals(target)) { + } else if ("cyanogenmod.platform".equals(target)) { + pkgId = Resources.THEME_CM_PKG_ID; + } else if (isCommonResources) { pkgId = Resources.THEME_COMMON_PKG_ID; } else { pkgId = Resources.THEME_APP_PKG_ID; } - boolean hasCommonResources = (hasCommonResources(pkg) && !COMMON_OVERLAY.equals(target)); + boolean hasCommonResources = (hasCommonResources(pkg) && !isCommonResources); + PackageParser.Package targetPkg = mPackages.get(target); + String appPath = targetPkg != null ? targetPkg.baseCodePath : + Environment.getRootDirectory() + "/framework/framework-res.apk"; + if (mInstaller.aapt(pkg.baseCodePath, internalPath, resPath, sharedGid, pkgId, pkg.applicationInfo.targetSdkVersion, + appPath, hasCommonResources ? ThemeUtils.getTargetCacheDir(COMMON_OVERLAY, pkg) + File.separator + "resources.apk" : "") != 0) { - throw new AaptException("Failed to run aapt"); + throw new AaptException("Failed to run aapt", isCommonResources); } } @@ -8280,7 +8400,7 @@ private void compileIconsWithAapt(Package pkg) throws Exception { if (mInstaller.aapt(pkg.baseCodePath, APK_PATH_TO_ICONS, resPath, sharedGid, Resources.THEME_ICON_PKG_ID, pkg.applicationInfo.targetSdkVersion, - "") != 0) { + "", "") != 0) { throw new AaptException("Failed to run aapt"); } } @@ -8418,25 +8538,34 @@ private int[] getIdmapHashes(File idmap) throws IOException { private void setUpCustomResolverActivity(PackageParser.Package pkg) { synchronized (mPackages) { - mResolverReplaced = true; - // Set up information for custom user intent resolution activity. - mResolveActivity.applicationInfo = pkg.applicationInfo; - mResolveActivity.name = mCustomResolverComponentName.getClassName(); - mResolveActivity.packageName = pkg.applicationInfo.packageName; - mResolveActivity.processName = pkg.applicationInfo.packageName; - mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; - mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | - ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; - mResolveActivity.theme = 0; - mResolveActivity.exported = true; - mResolveActivity.enabled = true; - mResolveInfo.activityInfo = mResolveActivity; - mResolveInfo.priority = 0; - mResolveInfo.preferredOrder = 0; - mResolveInfo.match = 0; - mResolveComponentName = mCustomResolverComponentName; - Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " + - mResolveComponentName); + for (Activity a : pkg.activities) { + if (a.getComponentName().getClassName() + .equals(mCustomResolverComponentName.getClassName())) { + mResolverReplaced = true; + // Set up information for custom user intent resolution activity. + mResolveActivity.applicationInfo = pkg.applicationInfo; + mResolveActivity.name = mCustomResolverComponentName.getClassName(); + mResolveActivity.packageName = pkg.applicationInfo.packageName; + mResolveActivity.processName = pkg.applicationInfo.packageName; + mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; + mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | + ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; + mResolveActivity.theme = a.info.theme; + mResolveActivity.exported = true; + mResolveActivity.enabled = true; + mResolveInfo.activityInfo = mResolveActivity; + mResolveInfo.priority = 0; + mResolveInfo.preferredOrder = 0; + mResolveInfo.match = 0; + mResolveComponentName = mCustomResolverComponentName; + Slog.i(TAG, "Replacing default ResolverActivity with custom activity: " + + mResolveComponentName); + break; + } + } + if (mResolveActivity.theme == 0) { + mResolveActivity.theme = R.style.Theme_DeviceDefault_Resolver; + } } } @@ -9364,12 +9493,15 @@ public List queryIntent(Intent intent, String resolvedType, int fla mFlags = flags; List list = super.queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId); - // Remove protected Application components + // Remove protected Application components if they're explicitly queried for. + // Implicit intent queries will be gated when the returned component is acted upon. int callingUid = Binder.getCallingUid(); String[] pkgs = getPackagesForUid(callingUid); List packages = (pkgs != null) ? Arrays.asList(pkgs) : Collections.EMPTY_LIST; - if (callingUid != Process.SYSTEM_UID && - (getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) == 0) { + final boolean isNotSystem = callingUid != Process.SYSTEM_UID && + (getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) == 0; + + if (isNotSystem && intent.getComponent() != null) { Iterator itr = list.iterator(); while (itr.hasNext()) { ActivityInfo activityInfo = itr.next().activityInfo; @@ -9407,6 +9539,255 @@ public List queryIntentForPackage(Intent intent, String resolvedTyp return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); } + /** + * Finds a privileged activity that matches the specified activity names. + */ + private PackageParser.Activity findMatchingActivity( + List activityList, ActivityInfo activityInfo) { + for (PackageParser.Activity sysActivity : activityList) { + if (sysActivity.info.name.equals(activityInfo.name)) { + return sysActivity; + } + if (sysActivity.info.name.equals(activityInfo.targetActivity)) { + return sysActivity; + } + if (sysActivity.info.targetActivity != null) { + if (sysActivity.info.targetActivity.equals(activityInfo.name)) { + return sysActivity; + } + if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) { + return sysActivity; + } + } + } + return null; + } + + public class IterGenerator { + public Iterator generate(ActivityIntentInfo info) { + return null; + } + } + + public class ActionIterGenerator extends IterGenerator { + @Override + public Iterator generate(ActivityIntentInfo info) { + return info.actionsIterator(); + } + } + + public class CategoriesIterGenerator extends IterGenerator { + @Override + public Iterator generate(ActivityIntentInfo info) { + return info.categoriesIterator(); + } + } + + public class SchemesIterGenerator extends IterGenerator { + @Override + public Iterator generate(ActivityIntentInfo info) { + return info.schemesIterator(); + } + } + + public class AuthoritiesIterGenerator extends IterGenerator { + @Override + public Iterator generate(ActivityIntentInfo info) { + return info.authoritiesIterator(); + } + } + + /** + * WARNING for performance reasons, the passed in intentList WILL BE + * MODIFIED. Do not pass in a list that should not be changed. + */ + private void getIntentListSubset(List intentList, + IterGenerator generator, Iterator searchIterator) { + // loop through the set of actions; every one must be found in the intent filter + while (searchIterator.hasNext()) { + // we must have at least one filter in the list to consider a match + if (intentList.size() == 0) { + break; + } + + final T searchAction = searchIterator.next(); + + // loop through the set of intent filters + final Iterator intentIter = intentList.iterator(); + while (intentIter.hasNext()) { + final ActivityIntentInfo intentInfo = intentIter.next(); + boolean selectionFound = false; + + // loop through the intent filter's selection criteria; at least one + // of them must match the searched criteria + final Iterator intentSelectionIter = generator.generate(intentInfo); + while (intentSelectionIter != null && intentSelectionIter.hasNext()) { + final T intentSelection = intentSelectionIter.next(); + if (intentSelection != null && intentSelection.equals(searchAction)) { + selectionFound = true; + break; + } + } + + // the selection criteria wasn't found in this filter's set; this filter + // is not a potential match + if (!selectionFound) { + intentIter.remove(); + } + } + } + } + + /** + * Adjusts the priority of the given intent filter according to policy. + *

+ *

    + *
  • The priority for unbundled updates to system applications is capped to the + * priority defined on the system partition
  • + *
+ */ + private void adjustPriority( + List systemActivities, ActivityIntentInfo intent) { + // nothing to do; priority is fine as-is + if (intent.getPriority() <= 0) { + return; + } + + final ActivityInfo activityInfo = intent.activity.info; + final ApplicationInfo applicationInfo = activityInfo.applicationInfo; + + final boolean systemApp = applicationInfo.isSystemApp(); + if (!systemApp) { + // non-system applications can never define a priority >0 + Slog.w(TAG, "Non-system app; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + intent.setPriority(0); + return; + } + + if (systemActivities == null) { + // the system package is not disabled; we're parsing the system partition + // apps on the system image get whatever priority they request + return; + } + + // system app unbundled update ... try to find the same activity + final PackageParser.Activity foundActivity = + findMatchingActivity(systemActivities, activityInfo); + if (foundActivity == null) { + // this is a new activity; it cannot obtain >0 priority + if (DEBUG_FILTERS) { + Slog.i(TAG, "New activity; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + + // found activity, now check for filter equivalence + + // a shallow copy is enough; we modify the list, not its contents + final List intentListCopy = + new ArrayList<>(foundActivity.intents); + final List foundFilters = findFilters(intent); + + // find matching action subsets + final Iterator actionsIterator = intent.actionsIterator(); + if (actionsIterator != null) { + getIntentListSubset( + intentListCopy, new ActionIterGenerator(), actionsIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched action; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // find matching category subsets + final Iterator categoriesIterator = intent.categoriesIterator(); + if (categoriesIterator != null) { + getIntentListSubset(intentListCopy, new CategoriesIterGenerator(), + categoriesIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched category; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // find matching schemes subsets + final Iterator schemesIterator = intent.schemesIterator(); + if (schemesIterator != null) { + getIntentListSubset(intentListCopy, new SchemesIterGenerator(), + schemesIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched scheme; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // find matching authorities subsets + final Iterator + authoritiesIterator = intent.authoritiesIterator(); + if (authoritiesIterator != null) { + getIntentListSubset(intentListCopy, + new AuthoritiesIterGenerator(), + authoritiesIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched authority; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // we found matching filter(s); app gets the max priority of all intents + int cappedPriority = 0; + for (int i = intentListCopy.size() - 1; i >= 0; --i) { + cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority()); + } + if (intent.getPriority() > cappedPriority) { + if (DEBUG_FILTERS) { + Slog.i(TAG, "Found matching filter(s);" + + " cap priority to " + cappedPriority + ";" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(cappedPriority); + return; + } + // all this for nothing; the requested priority was <= what was on the system + } + public final void addActivity(PackageParser.Activity a, String type) { final boolean systemApp = a.info.applicationInfo.isSystemApp(); mActivities.put(a.getComponentName(), a); @@ -9419,10 +9800,12 @@ public final void addActivity(PackageParser.Activity a, String type) { final int NI = a.intents.size(); for (int j=0; j 0 && "activity".equals(type)) { - intent.setPriority(0); - Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity " - + a.className + " with priority > 0, forcing to 0"); + if ("activity".equals(type)) { + final PackageSetting ps = + mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName); + final List systemActivities = + ps != null && ps.pkg != null ? ps.pkg.activities : null; + adjustPriority(systemActivities, intent); } if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); @@ -9576,18 +9959,6 @@ protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int out.println(); } -// List filterEnabled(List resolveInfoList) { -// final Iterator i = resolveInfoList.iterator(); -// final List retList = Lists.newArrayList(); -// while (i.hasNext()) { -// final ResolveInfo resolveInfo = i.next(); -// if (isEnabledLP(resolveInfo.activityInfo)) { -// retList.add(resolveInfo); -// } -// } -// return retList; -// } - // Keys are String (activity class name), values are Activity. private final ArrayMap mActivities = new ArrayMap(); @@ -10155,10 +10526,10 @@ void schedulePackageCleaning(String packageName, int userId, boolean andCode) { void startCleaningPackages() { // reader + if (!isExternalMediaAvailable()) { + return; + } synchronized (mPackages) { - if (!isExternalMediaAvailable()) { - return; - } if (mSettings.mPackagesToBeCleaned.isEmpty()) { return; } @@ -10266,8 +10637,8 @@ private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetti Bundle extras = new Bundle(1); extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId)); - sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, null, - packageName, extras, null, null, new int[] {userId}); + sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, + null, extras, null, null, new int[] {userId}); try { IActivityManager am = ActivityManagerNative.getDefault(); final boolean isSystem = @@ -11134,7 +11505,7 @@ class InstallParams extends HandlerParams { final IPackageInstallObserver2 observer; int installFlags; final String installerPackageName; - final String volumeUuid; + String volumeUuid; final VerificationParams verificationParams; private InstallArgs mArgs; private int mRet; @@ -11339,6 +11710,28 @@ public void handleStartCopy() throws RemoteException { } } + // Check whether we're replacing an existing package that's + // installed on adopted storage. If yes, override the new + // package location to match. + if (move == null && (installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(pkgLite.packageName); + if (pkg != null && isExternalAdopted(pkg)) { + // Check whether anything will actually change + // so that we log only when a fixup was needed + if (!((installFlags & PackageManager.INSTALL_INTERNAL) != 0 + && (installFlags & PackageManager.INSTALL_EXTERNAL) == 0 + && Objects.equals(volumeUuid, pkg.volumeUuid))) { + installFlags |= PackageManager.INSTALL_INTERNAL; + installFlags &= ~PackageManager.INSTALL_EXTERNAL; + volumeUuid = pkg.volumeUuid; + Slog.w(TAG, "Replacing package on adopted storage, updating " + +"new package destination to volumeUuid "+volumeUuid); + } + } + } + } + final InstallArgs args = createInstallArgs(this); mArgs = args; @@ -11647,8 +12040,6 @@ int doPreCopy() { * Called after the source arguments are copied. This is used mostly for * MoveParams when it needs to read the source file to put it in the * destination. - * - * @return */ int doPostCopy(int uid) { return PackageManager.INSTALL_SUCCEEDED; @@ -13292,6 +13683,14 @@ private static boolean isExternal(ApplicationInfo info) { return (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } + // Package is assumed to be on adopted storage if: + // FLAG_EXTERNAL_STORAGE is set + // volumeUuid is neither private internal (null) nor primary physical + private static boolean isExternalAdopted(PackageParser.Package pkg) { + return isExternal(pkg) && !TextUtils.isEmpty(pkg.volumeUuid) + && !Objects.equals(pkg.volumeUuid, StorageManager.UUID_PRIMARY_PHYSICAL); + } + private static boolean isSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } @@ -13522,7 +13921,8 @@ private int deletePackageX(String packageName, int userId, int flags) { String category = null; if (info.isThemeApk) { - category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; + category = cyanogenmod.content.Intent + .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, category, @@ -13567,7 +13967,8 @@ void sendBroadcast(boolean fullRemove, boolean replacing, boolean removedForAllU if (removedPackage != null) { String category = null; if (isThemeApk) { - category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; + category = cyanogenmod.content.Intent + .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; } sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, category, extras, null, null, removedUsers); @@ -15370,6 +15771,9 @@ public void systemReady() { int[] grantPermissionsUserIds = EMPTY_INT_ARRAY; synchronized (mPackages) { + // process applied themes so their resources are up to date and ready use + processAppliedThemes(); + // Verify that all of the preferred activity components actually // exist. It is possible for applications to be updated and at // that point remove a previously declared activity component that @@ -17179,6 +17583,70 @@ public void setComponentProtectedSetting(ComponentName componentName, boolean ne } } + @Override + public boolean isComponentProtected(String callingPackage, int callingUid, + ComponentName componentName, int userId) { + if (DEBUG_PROTECTED) Log.d(TAG, "Checking if component is protected " + + componentName.flattenToShortString() + " from calling package " + callingPackage + + " and callinguid " + callingUid); + + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "set protected"); + + //Allow managers full access + List protectedComponentManagers = + CMSettings.Secure.getDelimitedStringAsList(mContext.getContentResolver(), + CMSettings.Secure.PROTECTED_COMPONENT_MANAGERS, "|"); + if (protectedComponentManagers.contains(callingPackage)) { + if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is a protected manager, allow"); + return false; + } + + String packageName = componentName.getPackageName(); + String className = componentName.getClassName(); + + //If this component is launched from the same package, allow it. + if (TextUtils.equals(packageName, callingPackage)) { + if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is same as target, allow"); + return false; + } + + //If this component is launched from a validation component, allow it. + if (TextUtils.equals(PROTECTED_APPS_TARGET_VALIDATION_COMPONENT, + componentName.flattenToString()) && callingUid == Process.SYSTEM_UID) { + return false; + } + + //If this component is launched from the system or a uid of a protected component, allow it. + boolean fromProtectedComponentUid = false; + for (String protectedComponentManager : protectedComponentManagers) { + int packageUid = getPackageUid(protectedComponentManager, userId); + if (packageUid != -1 && callingUid == packageUid) { + fromProtectedComponentUid = true; + } + } + + if (TextUtils.equals(callingPackage, "android") && callingUid == Process.SYSTEM_UID + || callingPackage == null && fromProtectedComponentUid) { + if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is android or manager, allow"); + return false; + } + + PackageSetting pkgSetting; + ArraySet components; + + synchronized (mPackages) { + pkgSetting = mSettings.mPackages.get(packageName); + + if (pkgSetting == null || className == null) { + return false; + } + // Get all the protected components + components = pkgSetting.getProtectedComponents(userId); + if (DEBUG_PROTECTED) Log.d(TAG, "Got " + components.size() + " protected components"); + return components.size() > 0; + } + } + @Override public boolean isStorageLow() { final long token = Binder.clearCallingIdentity(); @@ -17632,8 +18100,11 @@ public ComposedIconInfo getComposedIconInfo() { @Override public int processThemeResources(String themePkgName) { mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - PackageParser.Package pkg = mPackages.get(themePkgName); + cyanogenmod.platform.Manifest.permission.ACCESS_THEME_MANAGER, null); + PackageParser.Package pkg; + synchronized (mPackages) { + pkg = mPackages.get(themePkgName); + } if (pkg == null) { Log.w(TAG, "Unable to get pkg for processing " + themePkgName); return 0; @@ -17654,11 +18125,15 @@ public int processThemeResources(String themePkgName) { // Generate Idmaps and res tables if pkg is a theme Iterator iterator = pkg.mOverlayTargets.iterator(); - while(iterator.hasNext()) { + while (iterator.hasNext()) { String target = iterator.next(); Exception failedException = null; + PackageParser.Package targetPkg; + synchronized (mPackages) { + targetPkg = mPackages.get(target); + } try { - compileResourcesAndIdmapIfNeeded(mPackages.get(target), pkg); + compileResourcesAndIdmapIfNeeded(targetPkg, pkg); } catch (IdmapException e) { failedException = e; } catch (AaptException e) { @@ -17668,10 +18143,20 @@ public int processThemeResources(String themePkgName) { } if (failedException != null) { - Slog.w(TAG, "Unable to process theme " + pkg.packageName + " for " + target, - failedException); - // remove target from mOverlayTargets - iterator.remove(); + if (failedException instanceof AaptException && + ((AaptException) failedException).isCommon) { + Slog.e(TAG, "Unable to process common resources for " + pkg.packageName + + ", uninstalling theme.", failedException); + uninstallThemeForAllApps(pkg); + deletePackageX(pkg.packageName, getCallingUid(), + PackageManager.DELETE_ALL_USERS); + return PackageManager.INSTALL_FAILED_THEME_AAPT_ERROR; + } else { + Slog.w(TAG, "Unable to process theme " + pkg.packageName + " for " + target, + failedException); + // remove target from mOverlayTargets + iterator.remove(); + } } } @@ -17679,11 +18164,57 @@ public int processThemeResources(String themePkgName) { } private void processThemeResourcesInThemeService(String pkgName) { - ThemeManager tm = - (ThemeManager) mContext.getSystemService(Context.THEME_SERVICE); - if (tm != null) { - tm.processThemeResources(pkgName); + IThemeService ts = IThemeService.Stub.asInterface(ServiceManager.getService( + CMContextConstants.CM_THEME_SERVICE)); + if (ts == null) { + Slog.e(TAG, "Theme service not available"); + return; } + try { + ts.processThemeResources(pkgName); + } catch (RemoteException e) { + /* ignore */ + } + } + + /** + * Makes sure resources and idmaps for themes that are applied are up to date. This should only + * impact boots when something on /system has changed. + */ + private void processAppliedThemes() { + ThemeConfig themeConfig = ThemeConfig.getBootTheme(mContext.getContentResolver()); + if (themeConfig == null) return; + + // gather up all the themes applied and then process them + Set themesToProcess = new ArraySet(); + // process theme set for icons + if (themeConfig.getIconPackPkgName() != null) { + themesToProcess.add(themeConfig.getIconPackPkgName()); + } + // process theme set for non-app specific overlays + if (themeConfig.getOverlayPkgName() != null) { + themesToProcess.add(themeConfig.getOverlayPkgName()); + } + // process theme set for status bar + if (themeConfig.getOverlayForStatusBar() != null) { + themesToProcess.add(themeConfig.getOverlayForStatusBar()); + } + // process theme set for navigation bar + if (themeConfig.getOverlayForNavBar() != null) { + themesToProcess.add(themeConfig.getOverlayForNavBar()); + } + // process themes set for specific apps + Map appThemesMap = themeConfig.getAppThemes(); + for (String themePkgName : appThemesMap.keySet()) { + themesToProcess.add(themePkgName); + } + + // now start the processing + for (String themePkgName : themesToProcess) { + processThemeResources(themePkgName); + } + + updateIconMapping(themeConfig.getIconPackPkgName()); } private void createAndSetCustomResources() { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 7b951060659f2..38478c2e6e270 100755 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -338,7 +338,7 @@ public void forceCurrent() { // Packages that have been uninstalled and still need their external // storage data deleted. final ArrayList mPackagesToBeCleaned = new ArrayList(); - + // Packages that have been renamed since they were first installed. // Keys are the new names of the packages, values are the original // names. The packages appear everwhere else under their original @@ -2459,11 +2459,16 @@ void readPrebundledPackagesLPr(int userId) { private void readPrebundledPackagesForUserFromFileLPr(int userId, File file) { BufferedReader reader = null; try { + HashSet ppkg = mPrebundledPackages.get(userId); + if (ppkg == null) { + Slog.e(PackageManagerService.TAG, "Unable to get packages for user " + userId); + return; + } reader = new BufferedReader(new FileReader(file)); String packageName = reader.readLine(); while (packageName != null) { if (!TextUtils.isEmpty(packageName)) { - mPrebundledPackages.get(userId).add(packageName); + ppkg.add(packageName); } packageName = reader.readLine(); } @@ -2519,7 +2524,7 @@ boolean wasPrebundledPackageInstalledLPr(int userId, String packageName) { return mPrebundledPackages.get(userId).contains(packageName); } - boolean shouldPrebundledPackageBeInstalled(Resources res, String packageName, + boolean shouldPrebundledPackageBeInstalledForRegion(Resources res, String packageName, Resources configuredResources) { // Default fallback on lack of bad package if (TextUtils.isEmpty(packageName)) { @@ -2552,6 +2557,37 @@ boolean shouldPrebundledPackageBeInstalled(Resources res, String packageName, return !ArrayUtils.contains(prebundledArray, packageName); } + boolean shouldPrebundledPackageBeInstalledForUserLPr(PackageSetting existingSettings, + int userIdentifier, String packageName) { + + // Check if package installed for the user + final boolean isInstalledForUser = (existingSettings != null + && existingSettings.getInstalled(userIdentifier)); + + // Check if package installed for the owner + final boolean isInstalledForOwner = (existingSettings != null + && existingSettings.getInstalled(UserHandle.USER_OWNER)); + + // Check if the user is the owner + final boolean isOwner = userIdentifier == UserHandle.USER_OWNER; + + // If the given user is not the owner, and the prebundle was installed for the owner + // but is no longer installed, and isn't currently installed for the user, + // skip installing it. + if (!isOwner && wasPrebundledPackageInstalledLPr(UserHandle.USER_OWNER, packageName) + && !isInstalledForOwner && !isInstalledForUser) { + return false; + } + + // If the given package was installed for the user and isn't currently, skip reinstalling it + if (wasPrebundledPackageInstalledLPr(userIdentifier, packageName) && + !isInstalledForUser) { + return false; + } + + return true; + } + void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg) throws java.io.IOException { serializer.startTag(null, "updated-package"); @@ -3751,7 +3787,7 @@ private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, } String tagName = parser.getName(); - // Legacy + // Legacy if (tagName.equals(TAG_DISABLED_COMPONENTS)) { readDisabledComponentsLPw(packageSetting, parser, 0); } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) { @@ -4029,7 +4065,7 @@ public PackageSetting getDisabledSystemPkgLPr(String name) { private String compToString(ArraySet cmp) { return cmp != null ? Arrays.toString(cmp.toArray()) : "[]"; } - + boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) { if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { return true; diff --git a/services/core/java/com/android/server/pm/UserContentObserver.java b/services/core/java/com/android/server/pm/UserContentObserver.java new file mode 100644 index 0000000000000..6145c3ba370da --- /dev/null +++ b/services/core/java/com/android/server/pm/UserContentObserver.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.server.pm; + +import android.app.ActivityManagerNative; +import android.app.IUserSwitchObserver; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.IRemoteCallback; +import android.os.RemoteException; +import android.util.Log; + +/** + * Simple extension of ContentObserver that also listens for user switch events to call update + */ +public abstract class UserContentObserver extends ContentObserver { + private static final String TAG = "UserContentObserver"; + + private Runnable mUpdateRunnable; + + private IUserSwitchObserver mUserSwitchObserver = new IUserSwitchObserver.Stub() { + @Override + public void onUserSwitching(int newUserId, IRemoteCallback reply) { + } + @Override + public void onUserSwitchComplete(int newUserId) throws RemoteException { + mHandler.post(mUpdateRunnable); + } + @Override + public void onForegroundProfileSwitch(int newProfileId) { + } + }; + + private Handler mHandler; + + /** + * Content observer that tracks user switches + * to allow clients to re-load settings for current user + */ + public UserContentObserver(Handler handler) { + super(handler); + mHandler = handler; + mUpdateRunnable = new Runnable() { + @Override + public void run() { + update(); + } + }; + } + + protected void observe() { + try { + ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchObserver); + } catch (RemoteException e) { + Log.w(TAG, "Unable to register user switch observer!", e); + } + } + + protected void unobserve() { + try { + mHandler.removeCallbacks(mUpdateRunnable); + ActivityManagerNative.getDefault().unregisterUserSwitchObserver(mUserSwitchObserver); + } catch (RemoteException e) { + Log.w(TAG, "Unable to unregister user switch observer!", e); + } + } + + /** + * Called to notify of registered uri changes and user switches. + * Always invoked on the handler passed in at construction + */ + protected abstract void update(); + + @Override + public void onChange(boolean selfChange, Uri uri) { + update(); + } +} diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 06c3682fa988a..583d7649a292d 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -125,6 +125,11 @@ public class UserManagerService extends IUserManager.Stub { private static final String RESTRICTIONS_FILE_PREFIX = "res_"; private static final String XML_SUFFIX = ".xml"; + private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION = + UserInfo.FLAG_MANAGED_PROFILE + | UserInfo.FLAG_RESTRICTED + | UserInfo.FLAG_GUEST; + private static final int MIN_USER_ID = 10; private static final int USER_VERSION = 5; @@ -262,11 +267,22 @@ void systemReady() { Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); } } + UserInfo currentGuestUser = null; + synchronized (mPackagesLock) { + currentGuestUser = findCurrentGuestUserLocked(); + } + if (currentGuestUser != null && !hasUserRestriction( + UserManager.DISALLOW_CONFIG_WIFI, currentGuestUser.id)) { + // If a guest user currently exists, apply the DISALLOW_CONFIG_WIFI option + // to it, in case this guest was created in a previous version where this + // user restriction was not a default guest restriction. + setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id); + } } @Override public List getUsers(boolean excludeDying) { - checkManageUsersPermission("query users"); + checkManageOrCreateUsersPermission("query users"); synchronized (mPackagesLock) { ArrayList users = new ArrayList(mUsers.size()); for (int i = 0; i < mUsers.size(); i++) { @@ -285,7 +301,7 @@ public List getUsers(boolean excludeDying) { @Override public List getProfiles(int userId, boolean enabledOnly) { if (userId != UserHandle.getCallingUserId()) { - checkManageUsersPermission("getting profiles related to user " + userId); + checkManageOrCreateUsersPermission("getting profiles related to user " + userId); } final long ident = Binder.clearCallingIdentity(); try { @@ -377,7 +393,7 @@ public void setUserEnabled(int userId) { @Override public UserInfo getUserInfo(int userId) { - checkManageUsersPermission("query user"); + checkManageOrCreateUsersPermission("query user"); synchronized (mPackagesLock) { return getUserInfoLocked(userId); } @@ -509,6 +525,7 @@ private void initDefaultGuestRestrictions() { if (mGuestRestrictions.isEmpty()) { mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true); mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true); + mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true); } } @@ -664,6 +681,71 @@ private static final void checkManageUsersPermission(String message) { } } + /** + * Enforces that only the system UID or root's UID or apps that have the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} + * can make certain calls to the UserManager. + * + * @param message used as message if SecurityException is thrown + * @throws SecurityException if the caller is not system or root + * @see #hasManageOrCreateUsersPermission() + */ + private static final void checkManageOrCreateUsersPermission(String message) { + if (!hasManageOrCreateUsersPermission()) { + throw new SecurityException( + "You either need MANAGE_USERS or CREATE_USERS permission to: " + message); + } + } + + /** + * Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries + * to create user/profiles other than what is allowed for + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} permission, then it will only + * allow callers with {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} permission. + */ + private static final void checkManageOrCreateUsersPermission(int creationFlags) { + if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) { + if (!hasManageOrCreateUsersPermission()) { + throw new SecurityException("You either need MANAGE_USERS or CREATE_USERS " + + "permission to create an user with flags: " + creationFlags); + } + } else if (!hasManageUsersPermission()) { + throw new SecurityException("You need MANAGE_USERS permission to create an user " + + " with flags: " + creationFlags); + } + } + + /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}. + */ + private static final boolean hasManageUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + + /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}. + */ + private static final boolean hasManageOrCreateUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED + || ActivityManager.checkComponentPermission( + android.Manifest.permission.CREATE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + private static void checkSystemOrRoot(String message) { final int uid = Binder.getCallingUid(); if (uid != Process.SYSTEM_UID && uid != 0) { @@ -1215,7 +1297,7 @@ private void cleanAppRestrictionsForPackage(String pkg, int userId) { @Override public UserInfo createProfileForUser(String name, int flags, int userId) { - checkManageUsersPermission("Only the system can create users"); + checkManageOrCreateUsersPermission(flags); if (userId != UserHandle.USER_OWNER) { Slog.w(LOG_TAG, "Only user owner can have profiles"); return null; @@ -1225,7 +1307,7 @@ public UserInfo createProfileForUser(String name, int flags, int userId) { @Override public UserInfo createUser(String name, int flags) { - checkManageUsersPermission("Only the system can create users"); + checkManageOrCreateUsersPermission(flags); return createUserInternal(name, flags, UserHandle.USER_NULL); } @@ -1390,7 +1472,7 @@ public boolean markGuestForDeletion(int userHandle) { * @param userHandle the user's id */ public boolean removeUser(int userHandle) { - checkManageUsersPermission("Only the system can remove users"); + checkManageOrCreateUsersPermission("Only the system can remove users"); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( UserManager.DISALLOW_REMOVE_USER, false)) { Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); diff --git a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java index fef1e57504cd4..e6ec6a67fe3af 100644 --- a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java +++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java @@ -72,6 +72,9 @@ public class BurnInProtectionHelper implements DisplayManager.DisplayListener, /* 1 means increasing, -1 means decreasing */ private int mYOffsetDirection = 1; + private int mAppliedBurnInXOffset = 0; + private int mAppliedBurnInYOffset = 0; + private final AlarmManager mAlarmManager; private final PendingIntent mBurnInProtectionIntent; private final DisplayManagerInternal mDisplayManagerInternal; @@ -139,6 +142,8 @@ private void updateBurnInProtection() { mFirstUpdate = false; } else { adjustOffsets(); + mAppliedBurnInXOffset = mLastBurnInXOffset; + mAppliedBurnInYOffset = mLastBurnInYOffset; mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), mLastBurnInXOffset, mLastBurnInYOffset); } @@ -258,6 +263,8 @@ public void onAnimationStart(Animator animator) { @Override public void onAnimationEnd(Animator animator) { if (animator == mCenteringAnimator && !mBurnInProtectionActive) { + mAppliedBurnInXOffset = 0; + mAppliedBurnInYOffset = 0; // No matter how the animation finishes, we want to zero the offsets. mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), 0, 0); } @@ -276,7 +283,7 @@ public void onAnimationUpdate(ValueAnimator valueAnimator) { if (!mBurnInProtectionActive) { final float value = (Float) valueAnimator.getAnimatedValue(); mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), - (int) (mLastBurnInXOffset * value), (int) (mLastBurnInYOffset * value)); + (int) (mAppliedBurnInXOffset * value), (int) (mAppliedBurnInYOffset * value)); } } } diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index 8c42917a8bf2c..96e1c70c2dc4e 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -22,12 +22,14 @@ import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.R; +import com.android.internal.util.UserIcons; import com.android.internal.widget.LockPatternUtils; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AlertDialog; import android.app.Dialog; +import android.app.INotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -35,12 +37,18 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ThemeUtils; import android.content.pm.UserInfo; import android.content.ServiceConnection; import android.database.ContentObserver; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.Manifest; import android.media.AudioManager; import android.net.ConnectivityManager; import android.os.Build; @@ -58,10 +66,13 @@ import android.os.UserManager; import android.os.Vibrator; import android.provider.Settings; +import android.provider.Settings.Global; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -84,11 +95,14 @@ import android.widget.ImageView.ScaleType; import android.widget.ListView; import android.widget.TextView; + import cyanogenmod.providers.CMSettings; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; -import java.util.UUID; + +import org.cyanogenmod.internal.util.ThemeUtils; import static com.android.internal.util.cm.PowerMenuConstants.*; @@ -128,6 +142,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac // Power menu customizations String mActions; + private BitSet mAirplaneModeBits; + private final List mPhoneStateListeners = new ArrayList<>(); + /** * @param context everything needs a context :( */ @@ -151,9 +168,15 @@ public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) { mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); // get notified of phone state changes - TelephonyManager telephonyManager = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); + SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener( + new SubscriptionManager.OnSubscriptionsChangedListener() { + @Override + public void onSubscriptionsChanged() { + super.onSubscriptionsChanged(); + setupAirplaneModeListeners(); + } + }); + setupAirplaneModeListeners(); mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, mAirplaneModeObserver); @@ -166,6 +189,58 @@ public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) { updatePowerMenuActions(); } + /** + * Since there are two ways of handling airplane mode (with telephony, we depend on the internal + * device telephony state), and MSIM devices do not report phone state for missing SIMs, we + * need to dynamically setup listeners based on subscription changes. + * + * So if there is _any_ active SIM in the device, we can depend on the phone state, + * otherwise fall back to {@link Settings.Global#AIRPLANE_MODE_ON}. + */ + private void setupAirplaneModeListeners() { + TelephonyManager telephonyManager = + (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + + for (PhoneStateListener listener : mPhoneStateListeners) { + telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE); + } + mPhoneStateListeners.clear(); + + final List subInfoList = SubscriptionManager.from(mContext) + .getActiveSubscriptionInfoList(); + if (subInfoList != null) { + mHasTelephony = true; + mAirplaneModeBits = new BitSet(subInfoList.size()); + for (int i = 0; i < subInfoList.size(); i++) { + final int finalI = i; + PhoneStateListener subListener = new PhoneStateListener(subInfoList.get(finalI) + .getSubscriptionId()) { + @Override + public void onServiceStateChanged(ServiceState serviceState) { + final boolean inAirplaneMode = serviceState.getState() + == ServiceState.STATE_POWER_OFF; + mAirplaneModeBits.set(finalI, inAirplaneMode); + + // we're in airplane mode if _any_ of the subscriptions say we are + mAirplaneState = mAirplaneModeBits.cardinality() > 0 + ? ToggleAction.State.On : ToggleAction.State.Off; + + mAirplaneModeOn.updateState(mAirplaneState); + if (mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + }; + mPhoneStateListeners.add(subListener); + telephonyManager.listen(subListener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + } else { + mHasTelephony = false; + } + // Set the initial status of airplane mode toggle + mAirplaneState = getUpdatedAirplaneToggleState(); + } + /** * Show the global actions dialog (creating if necessary) * @param keyguardShowing True if keyguard is showing @@ -173,14 +248,12 @@ public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) { public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; - if (mDialog != null && mUiContext == null) { + if (mDialog != null) { mDialog.dismiss(); mDialog = null; - mDialog = createDialog(); // Show delayed, so that the dismiss of the previous dialog completes mHandler.sendEmptyMessage(MESSAGE_SHOW); } else { - mDialog = createDialog(); handleShow(); } } @@ -199,6 +272,7 @@ private void awakenIfNecessary() { private void handleShow() { awakenIfNecessary(); + mDialog = createDialog(); prepareDialog(); // If we only have 1 item and it's a simple press action, just do this action. @@ -218,7 +292,7 @@ private void handleShow() { private Context getUiContext() { if (mUiContext == null) { mUiContext = ThemeUtils.createUiContext(mContext); - mUiContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + mUiContext.setTheme(com.android.internal.R.style.Theme_Power_Dialog); } return mUiContext != null ? mUiContext : mContext; } @@ -342,7 +416,8 @@ public boolean showBeforeProvisioning() { params.mOnClickListener = this; params.mForceInverseBackground = true; - GlobalActionsDialog dialog = new GlobalActionsDialog(getUiContext(), params); + GlobalActionsDialog dialog = new GlobalActionsDialog(/** system context **/ mContext, + /** themed context **/ getUiContext(), params); dialog.setCanceledOnTouchOutside(false); // Handled by the custom class. dialog.getListView().setItemsCanFocus(true); @@ -612,16 +687,24 @@ private void addUsersToMenu(ArrayList items) { if (um.isUserSwitcherEnabled()) { List users = um.getUsers(); UserInfo currentUser = getCurrentUser(); + final int avatarSize = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.global_actions_avatar_size); for (final UserInfo user : users) { if (user.supportsSwitchTo()) { boolean isCurrentUser = currentUser == null ? user.id == 0 : (currentUser.id == user.id); - Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath) - : null; + Drawable avatar = null; + Bitmap rawAvatar = um.getUserIcon(user.id); + if (rawAvatar == null) { + rawAvatar = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon( + user.isGuest() ? UserHandle.USER_NULL : user.id, /*light=*/ false)); + } + avatar = new BitmapDrawable(mContext.getResources(), + createCircularClip(rawAvatar, avatarSize, avatarSize)); + SinglePressAction switchToUser = new SinglePressAction( - com.android.internal.R.drawable.ic_lock_user, icon, - (user.name != null ? user.name : "Primary") - + (isCurrentUser ? " \u2714" : "")) { + com.android.internal.R.drawable.ic_lock_user, avatar, + (user.name != null ? user.name : "Primary")) { public void onPress() { try { ActivityManagerNative.getDefault().switchUser(user.id); @@ -638,6 +721,10 @@ public boolean showBeforeProvisioning() { return false; } }; + if (isCurrentUser) { + switchToUser.setStatus(mContext.getString( + R.string.global_action_current_user)); + } items.add(switchToUser); } } @@ -721,7 +808,8 @@ public void handleMessage(Message msg) { @Override public void onServiceDisconnected(ComponentName name) {} }; - if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { + if (mContext.bindServiceAsUser( + intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { mScreenshotConnection = conn; mHandler.postDelayed(mScreenshotTimeout, 10000); } @@ -890,6 +978,7 @@ private static abstract class SinglePressAction implements Action { private final Drawable mIcon; private final int mMessageResId; private final CharSequence mMessage; + private CharSequence mStatusMessage; protected SinglePressAction(int iconResId, int messageResId) { mIconResId = iconResId; @@ -916,8 +1005,12 @@ public boolean isEnabled() { return true; } - public String getStatus() { - return null; + public CharSequence getStatus() { + return mStatusMessage; + } + + public void setStatus(CharSequence status) { + mStatusMessage = status; } abstract public void onPress(); @@ -938,7 +1031,7 @@ public View create( TextView messageView = (TextView) v.findViewById(R.id.message); TextView statusView = (TextView) v.findViewById(R.id.status); - final String status = getStatus(); + final CharSequence status = getStatus(); if (!TextUtils.isEmpty(status)) { statusView.setText(status); } else { @@ -946,7 +1039,7 @@ public View create( } if (mIcon != null) { icon.setImageDrawable(mIcon); - icon.setScaleType(ScaleType.CENTER_CROP); + icon.setScaleType(ScaleType.CENTER); } else if (mIconResId != 0) { icon.setImageDrawable(context.getDrawable(mIconResId)); } @@ -1116,9 +1209,15 @@ public boolean showBeforeProvisioning() { } } - private static class SilentModeTriStateAction implements Action, View.OnClickListener { + private final class SilentModeTriStateAction implements Action, View.OnClickListener { - private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 }; + private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3, R.id.option4 }; + private final int[] ITEM_INDEX_TO_ZEN_MODE = { + Global.ZEN_MODE_NO_INTERRUPTIONS, + Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, + Global.ZEN_MODE_OFF, + Global.ZEN_MODE_OFF + }; private final AudioManager mAudioManager; private final Handler mHandler; @@ -1130,14 +1229,15 @@ private static class SilentModeTriStateAction implements Action, View.OnClickLis mContext = context; } - private int ringerModeToIndex(int ringerMode) { - // They just happen to coincide - return ringerMode; - } - private int indexToRingerMode(int index) { - // They just happen to coincide - return index; + if (index == 2) { + if (mHasVibrator) { + return AudioManager.RINGER_MODE_VIBRATE; + } else { + return AudioManager.RINGER_MODE_NORMAL; + } + } + return AudioManager.RINGER_MODE_NORMAL; } @Override @@ -1149,9 +1249,28 @@ public View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false); - int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode()); - for (int i = 0; i < 3; i++) { + int ringerMode = mAudioManager.getRingerModeInternal(); + int zenMode = Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, + Global.ZEN_MODE_OFF); + int selectedIndex = 0; + if (zenMode != Global.ZEN_MODE_OFF) { + if (zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { + selectedIndex = 0; + } else if (zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { + selectedIndex = 1; + } + } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { + selectedIndex = 2; + } else if (ringerMode == AudioManager.RINGER_MODE_NORMAL) { + selectedIndex = 3; + } + + for (int i = 0; i < ITEM_IDS.length; i++) { View itemView = v.findViewById(ITEM_IDS[i]); + if (!mHasVibrator && i == 2) { + itemView.setVisibility(View.GONE); + continue; + } itemView.setSelected(selectedIndex == i); // Set up click handler itemView.setTag(i); @@ -1182,7 +1301,22 @@ public void onClick(View v) { if (!(v.getTag() instanceof Integer)) return; int index = (Integer) v.getTag(); - mAudioManager.setRingerMode(indexToRingerMode(index)); + int zenMode = ITEM_INDEX_TO_ZEN_MODE[index]; + // ZenModeHelper will revert zen mode back to the previous value if we just + // put the value into the Settings db, so use INotificationManager instead + INotificationManager noMan = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + try { + noMan.setZenMode(zenMode, null, TAG); + } catch (RemoteException e) { + Log.e(TAG, "Unable to set zen mode", e); + } + + if (index == 2 || index == 3) { + int ringerMode = indexToRingerMode(index); + mAudioManager.setRingerModeInternal(ringerMode); + } + mAdapter.notifyDataSetChanged(); mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY); } } @@ -1222,17 +1356,6 @@ public void onReceive(Context context, Intent intent) { } }; - PhoneStateListener mPhoneStateListener = new PhoneStateListener() { - @Override - public void onServiceStateChanged(ServiceState serviceState) { - if (!mHasTelephony) return; - final boolean inAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF; - mAirplaneState = inAirplaneMode ? ToggleAction.State.On : ToggleAction.State.Off; - mAirplaneModeOn.updateState(mAirplaneState); - mAdapter.notifyDataSetChanged(); - } - }; - private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1274,15 +1397,17 @@ public void handleMessage(Message msg) { } }; + private ToggleAction.State getUpdatedAirplaneToggleState() { + return (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1) ? + ToggleAction.State.On : ToggleAction.State.Off; + } + private void onAirplaneModeChanged() { // Let the service state callbacks handle the state. if (mHasTelephony) return; - boolean airplaneModeOn = Settings.Global.getInt( - mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, - 0) == 1; - mAirplaneState = airplaneModeOn ? ToggleAction.State.On : ToggleAction.State.Off; + mAirplaneState = getUpdatedAirplaneToggleState(); mAirplaneModeOn.updateState(mAirplaneState); } @@ -1303,8 +1428,36 @@ private void changeAirplaneModeSystemSetting(boolean on) { } } + /** + * Generate a new bitmap (width x height pixels, ARGB_8888) with the input bitmap scaled + * to fit and clipped to an inscribed circle. + * @param input Bitmap to resize and clip + * @param width Width of output bitmap (and diameter of circle) + * @param height Height of output bitmap + * @return A shiny new bitmap for you to use + */ + private static Bitmap createCircularClip(Bitmap input, int width, int height) { + if (input == null) return null; + + final int inWidth = input.getWidth(); + final int inHeight = input.getHeight(); + final Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + final Paint paint = new Paint(); + paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + paint.setAntiAlias(true); + final RectF srcRect = new RectF(0, 0, inWidth, inHeight); + final RectF dstRect = new RectF(0, 0, width, height); + final Matrix m = new Matrix(); + m.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.CENTER); + canvas.setMatrix(m); + canvas.drawCircle(inWidth / 2, inHeight / 2, inWidth / 2, paint); + return output; + } + private static final class GlobalActionsDialog extends Dialog implements DialogInterface { private final Context mContext; + private Context mSystemContext = null; private final int mWindowTouchSlop; private final AlertController mAlert; private final MyAdapter mAdapter; @@ -1314,7 +1467,7 @@ private static final class GlobalActionsDialog extends Dialog implements DialogI private boolean mIntercepted; private boolean mCancelOnUp; - public GlobalActionsDialog(Context context, AlertParams params) { + private GlobalActionsDialog(Context context, AlertParams params) { super(context, getDialogTheme(context)); mContext = getContext(); mAlert = new AlertController(mContext, this, getWindow()); @@ -1323,6 +1476,19 @@ public GlobalActionsDialog(Context context, AlertParams params) { params.apply(mAlert); } + /** + * Utilized for a working global actions dialog for both accessibility services (which + * require a system context) and + * @param systemContext Base context (should be from system process) + * @param themedContext Themed context (created from system ui) + * @param params + */ + public GlobalActionsDialog(Context systemContext, Context themedContext, + AlertParams params) { + this(themedContext, params); + mSystemContext = systemContext; + } + private static int getDialogTheme(Context context) { TypedValue outValue = new TypedValue(); context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme, @@ -1336,8 +1502,8 @@ protected void onStart() { // of dismissing the dialog on touch outside. This is because the dialog // is dismissed on the first down while the global gesture is a long press // with two fingers anywhere on the screen. - if (EnableAccessibilityController.canEnableAccessibilityViaGesture(mContext)) { - mEnableAccessibilityController = new EnableAccessibilityController(mContext, + if (EnableAccessibilityController.canEnableAccessibilityViaGesture(mSystemContext)) { + mEnableAccessibilityController = new EnableAccessibilityController(mSystemContext, new Runnable() { @Override public void run() { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index dd4d3abe7099c..63390073e3dc2 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -22,7 +22,6 @@ import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.IUiModeManager; -import android.app.ProgressDialog; import android.app.SearchManager; import android.app.StatusBarManager; import android.app.UiModeManager; @@ -36,6 +35,7 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.CompatibilityInfo; @@ -83,10 +83,11 @@ import android.service.dreams.IDreamManager; import android.speech.RecognizerIntent; import android.telecom.TelecomManager; -import android.service.gesture.EdgeGestureManager; import com.android.internal.os.DeviceKeyHandler; import com.android.internal.util.cm.ActionUtils; + +import cyanogenmod.hardware.CMHardwareManager; import cyanogenmod.providers.CMSettings; import dalvik.system.DexClassLoader; import android.util.DisplayMetrics; @@ -129,8 +130,6 @@ import com.android.internal.policy.IKeyguardService; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ScreenShapeHelper; -import com.android.internal.util.gesture.EdgeGesturePosition; -import com.android.internal.util.gesture.EdgeServiceConstants; import com.android.internal.view.RotationPolicy; import com.android.internal.widget.PointerLocationView; import com.android.server.GestureLauncherService; @@ -138,6 +137,8 @@ import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; +import org.cyanogenmod.internal.BootDexoptDialog; + import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -153,6 +154,7 @@ import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; +import static org.cyanogenmod.platform.internal.Manifest.permission.THIRD_PARTY_KEYGUARD; /** * WindowManagerPolicy implementation for the Android phone UI. This @@ -274,6 +276,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // app shows again. If that doesn't happen for 30s we drop the gesture. private static final long PANIC_GESTURE_EXPIRATION = 30000; + private static final String DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION = + "android.permission.THIRD_PARTY_KEYGUARD"; + /** * Keyguard stuff */ @@ -372,6 +377,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { int[] mNavigationBarHeightForRotation = new int[4]; int[] mNavigationBarWidthForRotation = new int[4]; + WindowState mKeyguardPanel; + KeyguardServiceDelegate mKeyguardDelegate; final Runnable mWindowManagerDrawCallback = new Runnable() { @Override @@ -488,7 +495,9 @@ public void onDrawn() { // During wakeup by volume keys, we still need to capture subsequent events // until the key is released. This is required since the beep sound is produced // post keypressed. - boolean mVolumeWakeTriggered; + boolean mVolumeDownWakeTriggered; + boolean mVolumeUpWakeTriggered; + boolean mVolumeMuteWakeTriggered; int mPointerLocationMode = 0; // guarded by mLock @@ -654,6 +663,10 @@ public void onDrawn() { // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) int mIncallPowerBehavior; + // Behavior of HOME button during incomming call ring. + // (See Settings.Secure.RING_HOME_BUTTON_BEHAVIOR.) + int mRingHomeBehavior; + Display mDisplay; private int mDisplayRotation; @@ -743,6 +756,8 @@ public void onDrawn() { private boolean mHasPermanentMenuKey; private boolean mClearedBecauseOfForceShow; private boolean mTopWindowIsKeyguard; + private CMHardwareManager mCMHardware; + private boolean mShowKeyguardOnLeftSwipe; private class PolicyHandler extends Handler { @Override @@ -832,6 +847,9 @@ void observe() { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.Secure.getUriFor( + CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR), false, this, + UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.WAKE_GESTURE_ENABLED), false, this, UserHandle.USER_ALL); @@ -883,15 +901,12 @@ void observe() { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.ACCELEROMETER_ROTATION_ANGLES), false, this, UserHandle.USER_ALL); - resolver.registerContentObserver(CMSettings.Secure.getUriFor( - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR), false, this, + resolver.registerContentObserver(CMSettings.Global.getUriFor( + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.VOLBTN_MUSIC_CONTROLS), false, this, UserHandle.USER_ALL); - resolver.registerContentObserver(CMSettings.System.getUriFor( - CMSettings.System.USE_EDGE_SERVICE_FOR_GESTURES), false, this, - UserHandle.USER_ALL); resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.BACK_WAKE_SCREEN), false, this, UserHandle.USER_ALL); @@ -986,67 +1001,6 @@ public void onProposedRotationChanged(int rotation) { private SystemGesturesPointerEventListener mSystemGestures; - private EdgeGestureManager.EdgeGestureActivationListener mEdgeGestureActivationListener - = new EdgeGestureManager.EdgeGestureActivationListener() { - - @Override - public void onEdgeGestureActivation(int touchX, int touchY, - EdgeGesturePosition position, int flags) { - WindowState target = null; - - if (position == EdgeGesturePosition.TOP) { - target = mStatusBar; - } else if (position == EdgeGesturePosition.BOTTOM && mNavigationBarOnBottom) { - target = mNavigationBar; - } else if (position == EdgeGesturePosition.LEFT - && !mNavigationBarOnBottom && mNavigationBarLeftInLandscape) { - target = mNavigationBar; - } else if (position == EdgeGesturePosition.RIGHT && !mNavigationBarOnBottom) { - target = mNavigationBar; - } - - if (target != null) { - requestTransientBars(target); - dropEventsUntilLift(); - mEdgeListenerActivated = true; - } else { - restoreListenerState(); - } - } - }; - private EdgeGestureManager mEdgeGestureManager = null; - private int mLastEdgePositions = 0; - private boolean mEdgeListenerActivated = false; - private boolean mUsingEdgeGestureServiceForGestures = false; - - private void updateEdgeGestureListenerState() { - int flags = 0; - if (mUsingEdgeGestureServiceForGestures) { - flags = EdgeServiceConstants.LONG_LIVING | EdgeServiceConstants.UNRESTRICTED; - if (mStatusBar != null && !mStatusBar.isVisibleLw()) { - flags |= EdgeGesturePosition.TOP.FLAG; - } - if (mNavigationBar != null && !mNavigationBar.isVisibleLw() && !isStatusBarKeyguard()) { - if (mNavigationBarOnBottom) { - flags |= EdgeGesturePosition.BOTTOM.FLAG; - } else if (mNavigationBarLeftInLandscape) { - flags |= EdgeGesturePosition.LEFT.FLAG; - } else { - flags |= EdgeGesturePosition.RIGHT.FLAG; - } - } - } - if (mEdgeListenerActivated) { - mEdgeGestureActivationListener.restoreListenerState(); - mEdgeListenerActivated = false; - } - if (flags != mLastEdgePositions) { - mEdgeGestureManager.updateEdgeGestureActivationListener(mEdgeGestureActivationListener, - flags); - mLastEdgePositions = flags; - } - } - IStatusBarService getStatusBarService() { synchronized (mServiceAquireLock) { if (mStatusBarService == null) { @@ -1489,8 +1443,8 @@ boolean isDeviceProvisioned() { } boolean isUserSetupComplete() { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; + return CMSettings.Secure.getIntForUser(mContext.getContentResolver(), + CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 0, UserHandle.USER_CURRENT) != 0; } private void handleShortPressOnHome() { @@ -1625,6 +1579,7 @@ public void init(Context context, IWindowManager windowManager, mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); // Init display burn-in protection boolean burnInProtectionEnabled = context.getResources().getBoolean( @@ -1668,7 +1623,6 @@ public void init(Context context, IWindowManager windowManager, mOrientationListener.setCurrentRotation(windowManager.getRotation()); } catch (RemoteException ex) { } mSettingsObserver = new SettingsObserver(mHandler); - mSettingsObserver.observe(); mShortcutManager = new ShortcutManager(context); mUiMode = context.getResources().getInteger( com.android.internal.R.integer.config_defaultUiModeType); @@ -1813,6 +1767,11 @@ public void onSwipeFromLeft() { mNavigationBarLeftInLandscape) { requestTransientBars(mNavigationBar); } + if (mShowKeyguardOnLeftSwipe && isKeyguardShowingOrOccluded() + && mKeyguardDelegate.isKeyguardPanelFocused()) { + // Show keyguard + mKeyguardDelegate.showKeyguard(); + } } @Override public void onFling(int duration) { @@ -2136,6 +2095,10 @@ public void updateSettings() { Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT, UserHandle.USER_CURRENT); + mRingHomeBehavior = CMSettings.Secure.getIntForUser(resolver, + CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR, + CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR_DEFAULT, + UserHandle.USER_CURRENT); mHomeWakeScreen = (CMSettings.System.getIntForUser(resolver, CMSettings.System.HOME_WAKE_SCREEN, 1, UserHandle.USER_CURRENT) == 1) && ((mDeviceHardwareWakeKeys & KEY_MASK_HOME) != 0); @@ -2173,23 +2136,13 @@ public void updateSettings() { updateWakeGestureListenerLp(); } - final boolean useEdgeService = CMSettings.System.getIntForUser(resolver, - CMSettings.System.USE_EDGE_SERVICE_FOR_GESTURES, 1, UserHandle.USER_CURRENT) == 1; - if (useEdgeService ^ mUsingEdgeGestureServiceForGestures && mSystemReady) { - if (!mUsingEdgeGestureServiceForGestures && useEdgeService) { - mUsingEdgeGestureServiceForGestures = true; - mWindowManagerFuncs.unregisterPointerEventListener(mSystemGestures); - } else if (mUsingEdgeGestureServiceForGestures && !useEdgeService) { - mUsingEdgeGestureServiceForGestures = false; - mWindowManagerFuncs.registerPointerEventListener(mSystemGestures); - } - updateEdgeGestureListenerState(); - } - - boolean devForceNavbar = CMSettings.Secure.getIntForUser(resolver, - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; + boolean devForceNavbar = CMSettings.Global.getIntForUser(resolver, + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; if (devForceNavbar != mDevForceNavbar) { mDevForceNavbar = devForceNavbar; + if (mCMHardware.isSupported(CMHardwareManager.FEATURE_KEY_DISABLE)) { + mCMHardware.set(CMHardwareManager.FEATURE_KEY_DISABLE, mDevForceNavbar); + } } mNavigationBarLeftInLandscape = CMSettings.System.getIntForUser(resolver, @@ -2359,6 +2312,9 @@ public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; break; + case TYPE_KEYGUARD_PANEL: + permission = THIRD_PARTY_KEYGUARD; + break; default: permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; } @@ -2392,6 +2348,14 @@ public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) return WindowManagerGlobal.ADD_OKAY; } } + } else if (permission == THIRD_PARTY_KEYGUARD) { + // check if caller has the old permission and if so allow adding window + if (mContext.checkCallingOrSelfPermission( + DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION) + == PackageManager.PERMISSION_GRANTED) { + return WindowManagerGlobal.ADD_OKAY; + } + // fall through to the normal check below } if (mContext.checkCallingOrSelfPermission(permission) @@ -2440,6 +2404,7 @@ public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) { case TYPE_SYSTEM_DIALOG: case TYPE_VOLUME_OVERLAY: case TYPE_PRIVATE_PRESENTATION: + case TYPE_KEYGUARD_PANEL: break; } @@ -2482,6 +2447,12 @@ public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) { attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; } + + if ((attrs.privateFlags & (WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS | + WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY)) != 0) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.PREVENT_SYSTEM_KEYS, + "No permission to prevent system key"); + } } void readLidState() { @@ -2578,6 +2549,7 @@ public int windowTypeToLayerLw(int type) { // the safety window that shows behind keyguard while keyguard is starting return 14; case TYPE_STATUS_BAR_SUB_PANEL: + case TYPE_KEYGUARD_PANEL: return 15; case TYPE_STATUS_BAR: return 16; @@ -2724,6 +2696,11 @@ public WindowState getWinShowWhenLockedLw() { return mWinShowWhenLocked; } + @Override + public WindowState getWinKeyguardPanelLw() { + return mKeyguardPanel; + } + /** {@inheritDoc} */ @Override public View addStartingWindow(IBinder appToken, String packageName, int theme, @@ -2918,6 +2895,19 @@ public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) android.Manifest.permission.STATUS_BAR_SERVICE, "PhoneWindowManager"); break; + case TYPE_KEYGUARD_PANEL: + // check deprecated perm first and if not granted enforce the new permission name + if (mContext.checkCallingOrSelfPermission( + DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION) + != PackageManager.PERMISSION_GRANTED) { + mContext.enforceCallingOrSelfPermission(THIRD_PARTY_KEYGUARD, + "PhoneWindowManager"); + } + if (mKeyguardPanel != null) { + return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; + } + mKeyguardPanel = win; + break; case TYPE_KEYGUARD_SCRIM: if (mKeyguardScrim != null) { return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; @@ -2938,9 +2928,11 @@ public void removeWindowLw(WindowState win) { } else if (mKeyguardScrim == win) { Log.v(TAG, "Removing keyguard scrim"); mKeyguardScrim = null; - } if (mNavigationBar == win) { + } else if (mNavigationBar == win) { mNavigationBar = null; mNavigationBarController.setWindow(null); + } else if (mKeyguardPanel == win) { + mKeyguardPanel = null; } } @@ -3137,19 +3129,6 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p + " canceled=" + canceled); } - // If the boot mode is power off alarm, we should not dispatch the several physical keys - // in power off alarm UI to avoid pausing power off alarm UI. - int isPowerOffAlarmMode = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.POWER_OFF_ALARM_MODE, 0); - if (DEBUG_INPUT) { Log.d(TAG, "intercept Dispatching isPowerOffAlarmMode = " + - isPowerOffAlarmMode); } - - if (isPowerOffAlarmMode == 1 && (keyCode == KeyEvent.KEYCODE_HOME - || keyCode == KeyEvent.KEYCODE_SEARCH - || keyCode == KeyEvent.KEYCODE_MENU)) { - return -1; // ignore the physical key here - } - // If we think we might have a volume down & power key chord on the way // but we're not sure, then tell the dispatcher to wait a little while and // try again later before dispatching. @@ -3187,6 +3166,12 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p // timeout. if (keyCode == KeyEvent.KEYCODE_HOME) { + if (mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS) != 0 + && mScreenOnFully) { + return 0; + } // If we have released the home key, and didn't do anything else // while it was pressed, then it is time to go home! if (!down) { @@ -3210,8 +3195,15 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p // and his ONLY options are to answer or reject the call.) TelecomManager telecomManager = getTelecommService(); if (telecomManager != null && telecomManager.isRinging()) { - Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); - return -1; + if ((mRingHomeBehavior + & CMSettings.Secure.RING_HOME_BUTTON_BEHAVIOR_ANSWER) != 0) { + Log.i(TAG, "Answering with HOME button."); + telecomManager.acceptRingingCall(); + return -1; + } else { + Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); + return -1; + } } // Delay handling home if a double-tap is possible. @@ -3280,6 +3272,13 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p return 0; } + if (mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS) != 0 + && mScreenOnFully) { + return 0; + } + if (down) { if (mPressOnMenuBehavior == KEY_ACTION_APP_SWITCH || mLongPressOnMenuBehavior == KEY_ACTION_APP_SWITCH) { @@ -3345,6 +3344,13 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p } return 0; } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { + if (mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS) != 0 + && mScreenOnFully) { + return 0; + } + if (!keyguardOn) { if (down) { if (mPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH @@ -4005,8 +4011,6 @@ public int adjustSystemUiVisibilityLw(int visibility) { mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0; - updateEdgeGestureListenerState(); - // Reset any bits in mForceClearingStatusBarVisibility that // are now clear. mResettingSystemUiFlags &= visibility; @@ -4462,7 +4466,12 @@ private void applyForceImmersiveMode(int pfl, Rect r) { } } - private void applyStableConstraints(int sysui, int fl, Rect r) { + private void applyStableConstraints(int sysui, int fl, Rect r, Rect d) { + if (mNavigationBarLeftInLandscape) { + d.left = r.left; + r.left = 0; + } + if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { // If app is requesting a stable layout, don't let the // content insets go below the stable values. @@ -4722,7 +4731,7 @@ public void layoutWindowLw(WindowState win, WindowState attached) { cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; } - applyStableConstraints(sysUiFl, fl, cf); + applyStableConstraints(sysUiFl, fl, cf, df); if (adjust != SOFT_INPUT_ADJUST_NOTHING) { vf.left = mCurLeft; vf.top = mCurTop; @@ -4743,7 +4752,8 @@ public void layoutWindowLw(WindowState win, WindowState attached) { // gets everything, period. if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_STATUS_BAR_SUB_PANEL - || attrs.type == TYPE_VOLUME_OVERLAY) { + || attrs.type == TYPE_VOLUME_OVERLAY + || attrs.type == TYPE_KEYGUARD_PANEL) { pf.left = df.left = of.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; @@ -4837,7 +4847,7 @@ public void layoutWindowLw(WindowState win, WindowState attached) { + mRestrictedScreenHeight; } - applyStableConstraints(sysUiFl, fl, cf); + applyStableConstraints(sysUiFl, fl, cf, df); if (adjust != SOFT_INPUT_ADJUST_NOTHING) { vf.left = mCurLeft; @@ -5053,7 +5063,15 @@ public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { mForceStatusBarTransparent = true; } - } + } else if (attrs.type == TYPE_KEYGUARD_PANEL) { + if (mKeyguardDelegate.isKeyguardPanelFocused()) { + attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + attrs.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else { + attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + attrs.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type < FIRST_SYSTEM_WINDOW; @@ -5329,7 +5347,6 @@ public void run() { // update since mAllowLockscreenWhenOn might have changed updateLockScreenTimeout(); - updateEdgeGestureListenerState(); return changes; } @@ -5557,6 +5574,36 @@ public void onServiceDisconnected(ComponentName name) {} } } + private void setVolumeWakeTriggered(final int keyCode, boolean triggered) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + mVolumeDownWakeTriggered = triggered; + break; + case KeyEvent.KEYCODE_VOLUME_UP: + mVolumeUpWakeTriggered = triggered; + break; + case KeyEvent.KEYCODE_VOLUME_MUTE: + mVolumeMuteWakeTriggered = triggered; + break; + default: + Log.w(TAG, "setVolumeWakeTriggered: unexpected keyCode=" + keyCode); + } + } + + private boolean getVolumeWakeTriggered(final int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + return mVolumeDownWakeTriggered; + case KeyEvent.KEYCODE_VOLUME_UP: + return mVolumeUpWakeTriggered; + case KeyEvent.KEYCODE_VOLUME_MUTE: + return mVolumeMuteWakeTriggered; + default: + Log.w(TAG, "getVolumeWakeTriggered: unexpected keyCode=" + keyCode); + return false; + } + } + /** {@inheritDoc} */ @Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { @@ -5618,7 +5665,8 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { if (isValidGlobalKey(keyCode) && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, + "android.policy:KEY", true); } return result; } @@ -5651,11 +5699,11 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { // Eat all down & up keys when using volume wake. // This disables volume control, music control, and "beep" on key up. if (isWakeKey && mVolumeWakeScreen) { - mVolumeWakeTriggered = true; + setVolumeWakeTriggered(keyCode, true); break; - } else if (mVolumeWakeTriggered && !down) { + } else if (getVolumeWakeTriggered(keyCode) && !down) { result &= ~ACTION_PASS_TO_USER; - mVolumeWakeTriggered = false; + setVolumeWakeTriggered(keyCode, false); break; } @@ -5853,7 +5901,8 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { case KeyEvent.KEYCODE_POWER: { if (mTopFullscreenOpaqueWindowState != null && (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0 + & (WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS | + WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY)) != 0 && mScreenOnFully) { return result; } @@ -5881,6 +5930,15 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { break; } + case KeyEvent.KEYCODE_SOFT_SLEEP: { + result &= ~ACTION_PASS_TO_USER; + isWakeKey = false; + if (!down) { + mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); + } + break; + } + case KeyEvent.KEYCODE_WAKEUP: { result &= ~ACTION_PASS_TO_USER; isWakeKey = true; @@ -5956,7 +6014,8 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { } if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY", + event.getKeyCode() == KeyEvent.KEYCODE_WAKEUP /* check prox only on wake key*/); } return result; @@ -6093,11 +6152,9 @@ public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int polic } private boolean shouldDispatchInputWhenNonInteractive() { - if (mDisplay == null || mDisplay.getState() == Display.STATE_OFF) { - return false; - } - // Send events to keyguard while the screen is on and it's showing. - if (isKeyguardShowingAndNotOccluded()) { + // Send events to keyguard while the screen is on. + if (isKeyguardShowingAndNotOccluded() && mDisplay != null + && mDisplay.getState() != Display.STATE_OFF) { return true; } @@ -6400,6 +6457,11 @@ private void wakeUpFromPowerKey(long eventTime) { } private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { + return wakeUp(wakeTime, wakeInTheaterMode, reason, false); + } + + private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason, + boolean withProximityCheck) { final boolean theaterModeEnabled = isTheaterModeEnabled(); if (!wakeInTheaterMode && theaterModeEnabled) { return false; @@ -6410,7 +6472,11 @@ private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) Settings.Global.THEATER_MODE_ON, 0); } - mPowerManager.wakeUp(wakeTime, reason); + if (withProximityCheck) { + mPowerManager.wakeUpWithProximityCheck(wakeTime, reason); + } else { + mPowerManager.wakeUp(wakeTime, reason); + } return true; } @@ -6925,8 +6991,10 @@ public void systemReady() { mKeyguardDelegate = new KeyguardServiceDelegate(mContext); mKeyguardDelegate.onSystemReady(); - mEdgeGestureManager = EdgeGestureManager.getInstance(); - mEdgeGestureManager.setEdgeGestureActivationListener(mEdgeGestureActivationListener); + mCMHardware = CMHardwareManager.getInstance(mContext); + // Ensure observe happens in systemReady() since we need + // CMHardwareService to be up and running + mSettingsObserver.observe(); readCameraLensCoverState(); updateUiMode(); @@ -6982,68 +7050,18 @@ public void systemBooted() { screenTurnedOn(); } - ProgressDialog mBootMsgDialog = null; + BootDexoptDialog mBootMsgDialog = null; /** {@inheritDoc} */ @Override - public void showBootMessage(final CharSequence msg, final boolean always) { + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount) { mHandler.post(new Runnable() { @Override public void run() { if (mBootMsgDialog == null) { - int theme; - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WATCH)) { - theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert; - } else if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_TELEVISION)) { - theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; - } else { - theme = 0; - } - - mBootMsgDialog = new ProgressDialog(mContext, theme) { - // This dialog will consume all events coming in to - // it, to avoid it trying to do things too early in boot. - @Override public boolean dispatchKeyEvent(KeyEvent event) { - return true; - } - @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { - return true; - } - @Override public boolean dispatchTouchEvent(MotionEvent ev) { - return true; - } - @Override public boolean dispatchTrackballEvent(MotionEvent ev) { - return true; - } - @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { - return true; - } - @Override public boolean dispatchPopulateAccessibilityEvent( - AccessibilityEvent event) { - return true; - } - }; - if (mContext.getPackageManager().isUpgrade()) { - mBootMsgDialog.setTitle(R.string.android_upgrading_title); - } else { - mBootMsgDialog.setTitle(R.string.android_start_title); - } - mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); - mBootMsgDialog.setIndeterminate(true); - mBootMsgDialog.getWindow().setType( - WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); - mBootMsgDialog.getWindow().addFlags( - WindowManager.LayoutParams.FLAG_DIM_BEHIND - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); - mBootMsgDialog.getWindow().setDimAmount(1); - WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); - lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; - mBootMsgDialog.getWindow().setAttributes(lp); - mBootMsgDialog.setCancelable(false); - mBootMsgDialog.show(); - } - mBootMsgDialog.setMessage(msg); + mBootMsgDialog = BootDexoptDialog.create(mContext); + } + mBootMsgDialog.setProgress(stage, optimizedApp, currentAppPos, totalAppCount); } }); } @@ -7808,6 +7826,7 @@ public void dump(String prefix, PrintWriter pw, String[] args) { pw.print(prefix); pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); + pw.print(" mRingHomeBehavior="); pw.print(mRingHomeBehavior); pw.print(prefix); pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); @@ -7959,4 +7978,9 @@ public void dump(String prefix, PrintWriter pw, String[] args) { mKeyguardDelegate.dump(prefix, pw); } } + + @Override + public void setLiveLockscreenEdgeDetector(boolean enable) { + mShowKeyguardOnLeftSwipe = enable; + } } diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java index 991622398a481..651ee2249dbfc 100644 --- a/services/core/java/com/android/server/policy/WindowOrientationListener.java +++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java @@ -55,6 +55,7 @@ public abstract class WindowOrientationListener { private boolean mEnabled; private int mRate; private String mSensorType; + private boolean mUseSystemClockforRotationSensor; private Sensor mSensor; private OrientationJudge mOrientationJudge; private int mCurrentRotation = -1; @@ -90,6 +91,9 @@ private WindowOrientationListener(Context context, Handler handler, int rate) { mSensorType = context.getResources().getString( com.android.internal.R.string.config_orientationSensorType); + mUseSystemClockforRotationSensor = context.getResources().getBoolean( + com.android.internal.R.bool.config_useSystemClockforRotationSensor); + if (!TextUtils.isEmpty(mSensorType)) { List sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); final int N = sensors.size(); @@ -598,7 +602,8 @@ public void onSensorChanged(SensorEvent event) { // Reset the orientation listener state if the samples are too far apart in time // or when we see values of (0, 0, 0) which indicates that we polled the // accelerometer too soon after turning it on and we don't have any data yet. - final long now = event.timestamp; + final long now = mUseSystemClockforRotationSensor + ? SystemClock.elapsedRealtimeNanos() : event.timestamp; final long then = mLastFilteredTimestampNanos; final float timeDeltaMS = (now - then) * 0.000001f; final boolean skipSample; diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index cb09dd41d3a0f..a223d056854d4 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -431,4 +431,15 @@ public void dump(String prefix, PrintWriter pw) { mKeyguardService.dump(prefix, pw); } } + + public void showKeyguard() { + mKeyguardService.showKeyguard(); + } + + public boolean isKeyguardPanelFocused() { + if (mKeyguardService != null) { + return mKeyguardService.isKeyguardPanelFocused(); + } + return false; + } } diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java index 429b18866a61a..31c7a046402ac 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java @@ -245,4 +245,16 @@ public boolean isInputRestricted() { public void dump(String prefix, PrintWriter pw) { mKeyguardStateMonitor.dump(prefix, pw); } + + public void showKeyguard() { + try { + mService.showKeyguard(); + } catch (RemoteException e) { + Slog.w(TAG, "Remote Exception", e); + } + } + + public boolean isKeyguardPanelFocused() { + return mKeyguardStateMonitor.isKeyguardPanelFocused(); + } } \ No newline at end of file diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index 30cff039f11ad..09f908711e3da 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -43,6 +43,7 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { private volatile boolean mIsShowing = true; private volatile boolean mSimSecure = true; private volatile boolean mInputRestricted = true; + private volatile boolean mKeyguardPanelFocused = false; private int mCurrentUserId; @@ -70,6 +71,10 @@ public boolean isInputRestricted() { return mInputRestricted; } + public boolean isKeyguardPanelFocused() { + return mKeyguardPanelFocused; + } + @Override // Binder interface public void onShowingStateChanged(boolean showing) { mIsShowing = showing; @@ -80,6 +85,11 @@ public void onSimSecureStateChanged(boolean simSecure) { mSimSecure = simSecure; } + @Override // Binder interface + public void onKeyguardPanelFocusChanged(boolean focused) { + mKeyguardPanelFocused = focused; + } + public synchronized void setCurrentUser(int userId) { mCurrentUserId = userId; } @@ -100,5 +110,6 @@ public void dump(String prefix, PrintWriter pw) { pw.println(prefix + "mSimSecure=" + mSimSecure); pw.println(prefix + "mInputRestricted=" + mInputRestricted); pw.println(prefix + "mCurrentUserId=" + mCurrentUserId); + pw.println(prefix + "mKeyguardPanelFocused=" + mKeyguardPanelFocused); } } \ No newline at end of file diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 76d4a27e79157..a197c6ecf12b6 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -17,14 +17,18 @@ package com.android.server.power; import android.app.ActivityManager; +import android.os.IDeviceIdleController; +import android.os.ServiceManager; import android.util.SparseIntArray; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; +import com.android.internal.util.ArrayUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.ServiceThread; +import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.am.BatteryStatsService; import com.android.server.lights.Light; @@ -108,6 +112,8 @@ public final class PowerManagerService extends SystemService private static final int MSG_SANDMAN = 2; // Message: Sent when the screen brightness boost expires. private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3; + // Message: Sent when the sandman fails to acknowledge the dream state change. + private static final int MSG_SANDMAN_TIMEOUT = 4; private static final int MSG_WAKE_UP = 5; @@ -135,6 +141,8 @@ public final class PowerManagerService extends SystemService private static final int DIRTY_DOCK_STATE = 1 << 10; // Dirty bit: brightness boost changed private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11; + // Dirty bit: sandman state changed + private static final int DIRTY_SANDMAN_STATE = 1 << 12; // Summarizes the state of all active wakelocks. private static final int WAKE_LOCK_CPU = 1 << 0; @@ -179,6 +187,9 @@ public final class PowerManagerService extends SystemService // Max time (microseconds) to allow a CPU boost for private static final int MAX_CPU_BOOST_TIME = 5000000; + // Max time (milliseconds) to wait for the sandman to acknowledge dream state changes + private static final int SANDMAN_RESPONSE_TIMEOUT = 2 * 1000; + private final Context mContext; private final ServiceThread mHandlerThread; private final PowerManagerHandler mHandler; @@ -278,6 +289,13 @@ public final class PowerManagerService extends SystemService // True if the display suspend blocker has been acquired. private boolean mHoldingDisplaySuspendBlocker; + // The suspend blocker used to keep the CPU alive when dreams are requesting to be + // started. + private final SuspendBlocker mDreamSuspendBlocker; + + // True if the dream suspend blocker has been acquired. + private boolean mHoldingDreamSuspendBlocker; + // True if systemReady() has been called. private boolean mSystemReady; @@ -434,6 +452,14 @@ public final class PowerManagerService extends SystemService // Use -1 to disable. private int mButtonBrightnessOverrideFromWindowManager = -1; + // The window manager has determined the user to be inactive via other means. + // Set this to false to disable. + private boolean mUserInactiveOverrideFromWindowManager; + + // The next possible user activity timeout after being explicitly told the user is inactive. + // Set to -1 when not told the user is inactive since the last period spent dozing or asleep. + private long mOverriddenTimeout = -1; + // The user activity timeout override from the window manager // to allow the current foreground activity to override the user activity timeout. // Use -1 to disable. @@ -516,6 +542,7 @@ public final class PowerManagerService extends SystemService private boolean mProximityWakeSupported; android.os.PowerManager.WakeLock mProximityWakeLock; SensorEventListener mProximityListener; + private boolean mForceNavbar; private PerformanceManagerInternal mPerf; @@ -530,6 +557,7 @@ public PowerManagerService(Context context) { synchronized (mLock) { mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks"); mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display"); + mDreamSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Dreams"); mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; mHalAutoSuspendModeEnabled = false; @@ -690,6 +718,9 @@ mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"), resolver.registerContentObserver(CMSettings.Global.getUriFor( CMSettings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.Global.getUriFor( + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR), + false, mSettingsObserver, UserHandle.USER_ALL); // Go. readConfigurationLocked(); @@ -834,7 +865,8 @@ private void updateSettingsLocked() { mKeyboardBrightness = CMSettings.Secure.getIntForUser(resolver, CMSettings.Secure.KEYBOARD_BRIGHTNESS, mKeyboardBrightnessSettingDefault, UserHandle.USER_CURRENT); - + mForceNavbar = CMSettings.Global.getIntForUser(resolver, + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; mDirty |= DIRTY_SETTINGS; } @@ -1151,6 +1183,11 @@ private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, mNotifier.onUserActivity(event, uid); + if (mUserInactiveOverrideFromWindowManager) { + mUserInactiveOverrideFromWindowManager = false; + mOverriddenTimeout = -1; + } + if (mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) { @@ -1366,12 +1403,28 @@ private void setWakefulnessLocked(int wakefulness, int reason) { } } + /** + * Logs the time the device would have spent awake before user activity timeout, + * had the system not been told the user was inactive. + */ + private void logSleepTimeoutRecapturedLocked() { + final long now = SystemClock.uptimeMillis(); + final long savedWakeTimeMs = mOverriddenTimeout - now; + if (savedWakeTimeMs >= 0) { + EventLog.writeEvent(EventLogTags.POWER_SOFT_SLEEP_REQUESTED, savedWakeTimeMs); + mOverriddenTimeout = -1; + } + } + private void finishWakefulnessChangeIfNeededLocked() { if (mWakefulnessChanging && mDisplayReady) { if (mWakefulness == WAKEFULNESS_DOZING && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) { return; // wait until dream has enabled dozing } + if (mWakefulness == WAKEFULNESS_DOZING || mWakefulness == WAKEFULNESS_ASLEEP) { + logSleepTimeoutRecapturedLocked(); + } mWakefulnessChanging = false; mNotifier.onWakefulnessChangeFinished(); } @@ -1657,6 +1710,7 @@ private void updateUserActivitySummaryLocked(long now, int dirty) { final int sleepTimeout = getSleepTimeoutLocked(); final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout); final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout); + final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager; mUserActivitySummary = 0; if (mLastUserActivityTime >= mLastWakeTime) { @@ -1670,7 +1724,11 @@ private void updateUserActivitySummaryLocked(long now, int dirty) { buttonBrightness = mButtonBrightnessOverrideFromWindowManager; keyboardBrightness = mButtonBrightnessOverrideFromWindowManager; } else { - buttonBrightness = mButtonBrightness; + if (!mForceNavbar) { + buttonBrightness = mButtonBrightness; + } else { + buttonBrightness = 0; + } keyboardBrightness = mKeyboardBrightness; } @@ -1710,6 +1768,7 @@ private void updateUserActivitySummaryLocked(long now, int dirty) { } } } + if (mUserActivitySummary == 0) { if (sleepTimeout >= 0) { final long anyUserActivity = Math.max(mLastUserActivityTime, @@ -1725,6 +1784,20 @@ private void updateUserActivitySummaryLocked(long now, int dirty) { nextTimeout = -1; } } + + if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) { + if ((mUserActivitySummary & + (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) { + // Device is being kept awake by recent user activity + if (nextTimeout >= now && mOverriddenTimeout == -1) { + // Save when the next timeout would have occurred + mOverriddenTimeout = nextTimeout; + } + } + mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; + nextTimeout = -1; + } + if (mUserActivitySummary != 0 && nextTimeout >= 0) { Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT); msg.setAsynchronous(true); @@ -1869,15 +1942,16 @@ private void updateDreamLocked(int dirty, boolean displayBecameReady) { | DIRTY_PROXIMITY_POSITIVE | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) { if (mDisplayReady) { - scheduleSandmanLocked(); + scheduleSandmanLocked(false); } } } - private void scheduleSandmanLocked() { + private void scheduleSandmanLocked(boolean fromDreamService) { if (!mSandmanScheduled) { mSandmanScheduled = true; Message msg = mHandler.obtainMessage(MSG_SANDMAN); + msg.arg1 = fromDreamService ? 1 : 0; msg.setAsynchronous(true); mHandler.sendMessage(msg); } @@ -1890,7 +1964,7 @@ private void scheduleSandmanLocked() { * the dream and we don't want to hold our lock while doing so. There is a risk that * the device will wake or go to sleep in the meantime so we have to handle that case. */ - private void handleSandman() { // runs on handler thread + private void handleSandman(boolean fromDreamService) { // runs on handler thread // Handle preconditions. final boolean startDreaming; final int wakefulness; @@ -1903,6 +1977,30 @@ private void handleSandman() { // runs on handler thread } else { startDreaming = false; } + // We hold the display suspend blocker as long as mSandmanSummoned is true + // That guarantees this code to be run before the system enters suspend. However, + // once we exit this lock, we are no longer guaranteed to stay awake. Hold a wake + // lock that is released once the dream service has acknowledged the request + // to start. + if (mDreamManager != null) { + if (startDreaming) { + if (!mHoldingDreamSuspendBlocker) { + mDreamSuspendBlocker.acquire(); + mHoldingDreamSuspendBlocker = true; + Message msg = mHandler.obtainMessage(MSG_SANDMAN_TIMEOUT); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, SANDMAN_RESPONSE_TIMEOUT); + mDirty |= DIRTY_SANDMAN_STATE; + updatePowerStateLocked(); + } + } else if (fromDreamService) { + mHandler.removeMessages(MSG_SANDMAN_TIMEOUT); + if (mHoldingDreamSuspendBlocker) { + mDreamSuspendBlocker.release(); + mHoldingDreamSuspendBlocker = false; + } + } + } } // Start dreaming if needed. @@ -2332,6 +2430,11 @@ private boolean needDisplaySuspendBlockerLocked() { if (mScreenBrightnessBoostInProgress) { return true; } + + if (mSandmanSummoned) { + return true; + } + // Let the system suspend if the screen is off or dozing. return false; } @@ -2654,6 +2757,14 @@ private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness } } + private void setUserInactiveOverrideFromWindowManagerInternal() { + synchronized (mLock) { + mUserInactiveOverrideFromWindowManager = true; + mDirty |= DIRTY_USER_ACTIVITY; + updatePowerStateLocked(); + } + } + private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) { synchronized (mLock) { if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) { @@ -2843,6 +2954,8 @@ private void dumpInternal(PrintWriter pw) { + mScreenBrightnessOverrideFromWindowManager); pw.println(" mUserActivityTimeoutOverrideFromWindowManager=" + mUserActivityTimeoutOverrideFromWindowManager); + pw.println(" mUserInactiveOverrideFromWindowManager=" + + mUserInactiveOverrideFromWindowManager); pw.println(" mTemporaryScreenBrightnessSettingOverride=" + mTemporaryScreenBrightnessSettingOverride); pw.println(" mTemporaryScreenAutoBrightnessAdjustmentSettingOverride=" @@ -2917,7 +3030,7 @@ private final class DreamReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { - scheduleSandmanLocked(); + scheduleSandmanLocked(true); } } } @@ -2974,7 +3087,8 @@ public void handleMessage(Message msg) { handleUserActivityTimeout(); break; case MSG_SANDMAN: - handleSandman(); + boolean fromDreamService = msg.arg1 == 1; + handleSandman(fromDreamService); break; case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT: handleScreenBrightnessBoostTimeout(); @@ -2983,6 +3097,10 @@ public void handleMessage(Message msg) { cleanupProximity(); ((Runnable) msg.obj).run(); break; + case MSG_SANDMAN_TIMEOUT: + Slog.w(TAG, "Sandman unresponsive, releasing suspend blocker"); + handleSandman(true); + break; } } } @@ -3223,6 +3341,29 @@ public void acquireWakeLock(IBinder lock, int flags, String tag, String packageN final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); + + try { + if (mAppOps != null && + mAppOps.checkOperation(AppOpsManager.OP_WAKE_LOCK, uid, packageName) + != AppOpsManager.MODE_ALLOWED) { + + // If this app is whitelisted as "allow-in-power-save" then always allow! + // Current impl only looks at system-loaded ones, if we want to also include + // user apps which have been manually set, we would use IDeviceIdleController + if (!SystemConfig.getInstance().getAllowInPowerSave().contains(packageName)) { + Slog.d(TAG, "acquireWakeLock: ignoring request from " + packageName); + // For (ignore) accounting purposes + mAppOps.noteOperation(AppOpsManager.OP_WAKE_LOCK, uid, packageName); + // silent return + return; + } else { + Slog.d(TAG, "wake lock requested to be ignored but " + packageName + + " is marked to opt-out of all power save restrictions."); + } + } + } catch (RemoteException ignored) { + } + final long ident = Binder.clearCallingIdentity(); try { acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid); @@ -3440,6 +3581,8 @@ public void onSensorChanged(SensorEvent event) { if (distance >= PROXIMITY_NEAR_THRESHOLD || distance >= mProximitySensor.getMaximumRange()) { r.run(); + } else { + Slog.w(TAG, "Not waking up. Proximity sensor blocked."); } } @@ -3775,10 +3918,10 @@ public void updateBlockedUids(int uid, boolean isBlocked) { else { mBlockedUids.clear(); } - } - if(changed){ - mDirty |= DIRTY_WAKE_LOCKS; - updatePowerStateLocked(); + if(changed){ + mDirty |= DIRTY_WAKE_LOCKS; + updatePowerStateLocked(); + } } } } @@ -3836,6 +3979,11 @@ public void setDozeOverrideFromDreamManager(int screenState, int screenBrightnes setDozeOverrideFromDreamManagerInternal(screenState, screenBrightness); } + @Override + public void setUserInactiveOverrideFromWindowManager() { + setUserInactiveOverrideFromWindowManagerInternal(); + } + @Override public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) { setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index 9b8ea1488196d..36a9ca26d9c70 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -26,7 +26,6 @@ import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.IBluetoothManager; -import android.content.pm.ThemeUtils; import android.media.AudioAttributes; import android.nfc.NfcAdapter; import android.nfc.INfcAdapter; @@ -78,6 +77,8 @@ import java.io.PrintWriter; import java.io.OutputStreamWriter; +import org.cyanogenmod.internal.util.ThemeUtils; + public final class ShutdownThread extends Thread { // constants private static final String TAG = "ShutdownThread"; @@ -629,6 +630,16 @@ public void onShutDownComplete(int statusCode) throws RemoteException { } }; + final String cryptoStatus = SystemProperties.get("ro.crypto.state", "unsupported"); + final boolean isEncrypted = "encrypted".equalsIgnoreCase(cryptoStatus); + + if (mRebootUpdate && isEncrypted) { + sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null); + + // If it's to reboot to install update, invoke uncrypt via init service. + uncrypt(); + } + Log.i(TAG, "Shutting down MountService"); // Set initial variables and time out time. @@ -664,12 +675,6 @@ public void onShutDownComplete(int statusCode) throws RemoteException { } } } - if (mRebootUpdate) { - sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null); - - // If it's to reboot to install update, invoke uncrypt via init service. - uncrypt(); - } rebootOrShutdown(mContext, mReboot, mRebootReason); } @@ -1001,7 +1006,7 @@ private static Context getUiContext(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) { uiContext.setTheme(com.android.internal.R.style.Theme_Leanback_Dialog_Alert); } else { - uiContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + uiContext.setTheme(com.android.internal.R.style.Theme_Power_Dialog); } } return uiContext != null ? uiContext : context; diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index e9ace29395a26..0e519533118ba 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -249,7 +249,7 @@ public void disableForUser(int what, IBinder token, String pkg, int userId) { */ @Override public void disable2(int what, IBinder token, String pkg) { - disableForUser(what, token, pkg, mCurrentUserId); + disable2ForUser(what, token, pkg, mCurrentUserId); } /** diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java index a71961c8fe9b7..2185b19cf1bbf 100644 --- a/services/core/java/com/android/server/twilight/TwilightService.java +++ b/services/core/java/com/android/server/twilight/TwilightService.java @@ -309,6 +309,13 @@ public void handleMessage(Message msg) { } sendEmptyMessageDelayed(MSG_ENABLE_LOCATION_UPDATES, mLastUpdateInterval); } + + if (!networkLocationEnabled && mLocation == null) { + if (DEBUG) { + Slog.d(TAG, "Network location unavailable"); + } + retrieveLocation(); + } break; case MSG_DO_TWILIGHT_UPDATE: diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java index 7c2da2dc292e5..be3e922ad7a6b 100644 --- a/services/core/java/com/android/server/wm/CircularDisplayMask.java +++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java @@ -56,7 +56,7 @@ public CircularDisplayMask(Display display, SurfaceSession session, int zOrder, int screenOffset, int maskThickness) { mScreenSize = new Point(); display.getSize(mScreenSize); - if (mScreenSize.x != mScreenSize.y) { + if (mScreenSize.x != mScreenSize.y + screenOffset) { Slog.w(TAG, "Screen dimensions of displayId = " + display.getDisplayId() + "are not equal, circularMask will not be drawn."); mDimensionsUnequal = true; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 331ddbfb6ba3f..2edf5520b449a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -116,6 +116,7 @@ class DisplayContent { display.getDisplayInfo(mDisplayInfo); isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; mService = service; + initializeDisplayBaseInfo(); } int getDisplayId() { @@ -176,6 +177,21 @@ void updateDisplayInfo() { } } + void initializeDisplayBaseInfo() { + synchronized(mDisplaySizeLock) { + // Bootstrap the default logical display from the display manager. + final DisplayInfo newDisplayInfo = + mService.mDisplayManagerInternal.getDisplayInfo(mDisplayId); + if (newDisplayInfo != null) { + mDisplayInfo.copyFrom(newDisplayInfo); + } + mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; + mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; + mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; + mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); + } + } + void getLogicalDisplayRect(Rect out) { // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. final int orientation = mDisplayInfo.rotation; diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java index 01f878c1562e7..80526f28ea209 100644 --- a/services/core/java/com/android/server/wm/DisplaySettings.java +++ b/services/core/java/com/android/server/wm/DisplaySettings.java @@ -79,17 +79,20 @@ public void getOverscanLocked(String name, String uniqueId, Rect outRect) { } } - public void setOverscanLocked(String name, int left, int top, int right, int bottom) { + public void setOverscanLocked(String uniqueId, String name, int left, int top, int right, + int bottom) { if (left == 0 && top == 0 && right == 0 && bottom == 0) { // Right now all we are storing is overscan; if there is no overscan, // we have no need for the entry. + mEntries.remove(uniqueId); + // Legacy name might have been in used, so we need to clear it. mEntries.remove(name); return; } - Entry entry = mEntries.get(name); + Entry entry = mEntries.get(uniqueId); if (entry == null) { - entry = new Entry(name); - mEntries.put(name, entry); + entry = new Entry(uniqueId); + mEntries.put(uniqueId, entry); } entry.overscanLeft = left; entry.overscanTop = top; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 480da441593fe..7e437c7d96e25 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -399,7 +399,9 @@ void detachDisplay() { void resetAnimationBackgroundAnimator() { mAnimationBackgroundAnimator = null; - mAnimationBackgroundSurface.hide(); + if (mAnimationBackgroundSurface != null) { + mAnimationBackgroundSurface.hide(); + } } private long getBlurBehindFadeDuration(long duration) { @@ -468,11 +470,14 @@ boolean testDimmingTag() { } boolean isDimming() { + if (mDimLayer == null) { + return false; + } return mDimLayer.isDimming(); } boolean isDimming(WindowStateAnimator winAnimator) { - return mDimWinAnimator == winAnimator && mDimLayer.isDimming(); + return mDimWinAnimator == winAnimator && isDimming(); } void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) { diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 5d9878fdea8ab..362e9590069df 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -30,12 +30,15 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING; import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.view.Display; import android.view.SurfaceControl; +import android.view.WindowManager; import android.view.WindowManagerPolicy; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; @@ -43,6 +46,8 @@ import com.android.server.wm.WindowManagerService.LayoutFields; +import cyanogenmod.providers.CMSettings; + import java.io.PrintWriter; import java.util.ArrayList; @@ -97,7 +102,7 @@ public class WindowAnimator { /** Use one animation for all entering activities after keyguard is dismissed. */ Animation mPostKeyguardExitAnimation; - private final boolean mBlurUiEnabled; + private boolean mKeyguardBlurEnabled; // forceHiding states. static final int KEYGUARD_NOT_SHOWN = 0; @@ -119,9 +124,14 @@ private String forceHidingToString() { mContext = service.mContext; mPolicy = service.mPolicy; - mBlurUiEnabled = mContext.getResources().getBoolean( + boolean blurUiEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_ui_blur_enabled); + if (blurUiEnabled) { + SettingsObserver observer = new SettingsObserver(new Handler()); + observer.observe(mContext); + } + mAnimationFrameCallback = new Choreographer.FrameCallback() { public void doFrame(long frameTimeNs) { synchronized (mService.mWindowMap) { @@ -209,6 +219,10 @@ private boolean shouldForceHide(WindowState win) { allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard; // Show SHOW_WHEN_LOCKED windows that turn on the screen allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen; + // Show windows that use TYPE_STATUS_BAR_SUB_PANEL when locked + allowWhenLocked |= win.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD_PANEL && + winShowWhenLocked == null; + if (appShowWhenLocked != null) { allowWhenLocked |= appShowWhenLocked == win.mAppToken @@ -220,7 +234,14 @@ private boolean shouldForceHide(WindowState win) { // Only hide windows if the keyguard is active and not animating away. boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded() - && (mForceHiding != KEYGUARD_ANIMATING_OUT && !mBlurUiEnabled); + && mForceHiding != KEYGUARD_ANIMATING_OUT; + + final WindowState winKeyguardPanel = (WindowState) mPolicy.getWinKeyguardPanelLw(); + // If a keyguard panel is currently being shown, we should + // continue to hide the windows as if blur is disabled. + if (winKeyguardPanel == null) { + keyguardOn &= !mKeyguardBlurEnabled; + } return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY); } @@ -229,7 +250,7 @@ private void updateWindowsLocked(final int displayId) { final WindowList windows = mService.getWindowListLocked(displayId); - if (mKeyguardGoingAway && !mBlurUiEnabled) { + if (mKeyguardGoingAway && !mKeyguardBlurEnabled) { for (int i = windows.size() - 1; i >= 0; i--) { WindowState win = windows.get(i); if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) { @@ -244,7 +265,7 @@ private void updateWindowsLocked(final int displayId) { // Create a new animation to delay until keyguard is gone on its own. winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f); winAnimator.mAnimation.setDuration( - mBlurUiEnabled ? 0 : KEYGUARD_ANIM_TIMEOUT_MS); + mKeyguardBlurEnabled ? 0 : KEYGUARD_ANIM_TIMEOUT_MS); winAnimator.mAnimationIsEntrance = false; winAnimator.mAnimationStartTime = -1; winAnimator.mKeyguardGoingAwayAnimation = true; @@ -334,7 +355,7 @@ private void updateWindowsLocked(final int displayId) { if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) { mForceHiding = KEYGUARD_ANIMATING_OUT; } else { - mForceHiding = win.isDrawnLw() && !mBlurUiEnabled ? + mForceHiding = win.isDrawnLw() && !mKeyguardBlurEnabled ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN; } } @@ -887,4 +908,30 @@ ScreenRotationAnimation getScreenRotationAnimationLocked(int displayId) { private class DisplayContentsAnimator { ScreenRotationAnimation mScreenRotationAnimation = null; } + + private class SettingsObserver extends ContentObserver { + public SettingsObserver(Handler handler) { + super(handler); + } + + public void observe(Context context) { + context.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED), + false, + this); + + onChange(true); + } + + public void unobserve(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange) { + // default to being enabled since we are here because the blur config was set to true + mKeyguardBlurEnabled = CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED, 1) == 1; + } + } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 60ddd85070068..3d79757230a24 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; @@ -65,6 +66,7 @@ import android.os.SystemService; import android.os.Trace; import android.os.UserHandle; +import android.os.UserManager; import android.os.WorkSource; import android.provider.Settings; import android.util.ArraySet; @@ -128,6 +130,8 @@ import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; import com.android.server.input.InputManagerService; +import com.android.server.lights.Light; +import com.android.server.lights.LightsManager; import com.android.server.policy.PhoneWindowManager; import com.android.server.power.ShutdownThread; @@ -1015,7 +1019,6 @@ public void onLowPowerModeChanged(boolean enabled) { // Load hardware rotation from prop mSfHwRotation = android.os.SystemProperties.getInt("ro.sf.hwrotation",0) / 90; - updateCircularDisplayMaskIfNeeded(); showEmulatorDisplayOverlayIfNeeded(); } @@ -3163,7 +3166,9 @@ public int relayoutWindow(Session session, IWindow client, int seq, } if (attrs != null) { + Binder.restoreCallingIdentity(origId); mPolicy.adjustWindowParamsLw(attrs); + origId = Binder.clearCallingIdentity(); } // if they don't have the permission, mask out the status bar bits @@ -4361,7 +4366,7 @@ public void setAppStartingWindow(IBinder token, String pkg, AppWindowToken ttoken = findAppWindowToken(transferFrom); if (ttoken != null) { WindowState startingWindow = ttoken.startingWindow; - if (startingWindow != null) { + if (startingWindow != null && ttoken.startingView != null) { // In this case, the starting icon has already been displayed, so start // letting windows get shown immediately without any more transitions. mSkipAppTransitionAnimation = true; @@ -4490,13 +4495,8 @@ public void setAppStartingWindow(IBinder token, String pkg, + " ShowWallpaper=" + ent.array.getBoolean( com.android.internal.R.styleable.Window_windowShowWallpaper, false)); - final boolean windowIsTranslucentDefined = ent.array.hasValue( - com.android.internal.R.styleable.Window_windowIsTranslucent); - final boolean windowIsTranslucent = ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowIsTranslucent, false); - final boolean windowSwipeToDismiss = ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowSwipeToDismiss, false); - if (windowIsTranslucent || (!windowIsTranslucentDefined && windowSwipeToDismiss)) { + if (ent.array.getBoolean( + com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { return; } if (ent.array.getBoolean( @@ -5934,6 +5934,17 @@ public void performEnableScreen() { mPolicy.enableScreenAfterBoot(); + // clear any intrusive lighting which may still be on from the + // crypto landing ui + LightsManager lm = LocalServices.getService(LightsManager.class); + Light batteryLight = lm.getLight(LightsManager.LIGHT_ID_BATTERY); + Light notifLight = lm.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS); + if (batteryLight != null) { + batteryLight.turnOff(); + } + if (notifLight != null) { + notifLight.turnOff(); + } // Make sure the last requested orientation has been applied. updateRotationUnchecked(false, false); } @@ -5950,13 +5961,18 @@ private boolean checkBootAnimationCompleteLocked() { return true; } - public void showBootMessage(final CharSequence msg, final boolean always) { + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount, final boolean always) { boolean first = false; synchronized(mWindowMap) { if (DEBUG_BOOT) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); - Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always + Slog.i(TAG, "updateBootProgress: stage=" + stage + + " optimizedApp=" + optimizedApp + + " currentAppPos=" + currentAppPos + + " totalAppCount=" + totalAppCount + + " always=" + always + " mAllowBootMessages=" + mAllowBootMessages + " mShowingBootMessages=" + mShowingBootMessages + " mSystemBooted=" + mSystemBooted, here); @@ -5974,7 +5990,7 @@ public void showBootMessage(final CharSequence msg, final boolean always) { return; } mShowingBootMessages = true; - mPolicy.showBootMessage(msg, always); + mPolicy.updateBootProgress(stage, optimizedApp, currentAppPos, totalAppCount); } if (first) { performEnableScreen(); @@ -6003,7 +6019,7 @@ public void setInTouchMode(boolean mode) { } } - public void updateCircularDisplayMaskIfNeeded() { + private void updateCircularDisplayMaskIfNeeded() { // we're fullscreen and not hosted in an ActivityView if (mContext.getResources().getConfiguration().isScreenRound() && mContext.getResources().getBoolean( @@ -6043,8 +6059,8 @@ public void showCircularMask(boolean visible) { if (visible) { // TODO(multi-display): support multiple displays if (mCircularDisplayMask == null) { - int screenOffset = mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.circular_display_mask_offset); + int screenOffset = mContext.getResources().getInteger( + com.android.internal.R.integer.config_windowOutsetBottom); int maskThickness = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.circular_display_mask_thickness); @@ -7672,6 +7688,12 @@ public boolean detectSafeMode() { + " milliseconds before attempting to detect safe mode."); } + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + if (um != null && um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { + mSafeMode = false; + return false; + } + int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_MENU); int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); @@ -7726,6 +7748,8 @@ public void displayReady() { mActivityManager.updateConfiguration(null); } catch (RemoteException e) { } + + updateCircularDisplayMaskIfNeeded(); } private void displayReady(int displayId) { @@ -7733,22 +7757,7 @@ private void displayReady(int displayId) { final DisplayContent displayContent = getDisplayContentLocked(displayId); if (displayContent != null) { mAnimator.addDisplayLocked(displayId); - synchronized(displayContent.mDisplaySizeLock) { - // Bootstrap the default logical display from the display manager. - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); - if (newDisplayInfo != null) { - displayInfo.copyFrom(newDisplayInfo); - } - displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; - displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; - displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; - displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; - displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; - displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; - displayContent.mBaseDisplayRect.set(0, 0, - displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); - } + displayContent.initializeDisplayBaseInfo(); } } } @@ -8787,7 +8796,8 @@ private void setOverscanLocked(DisplayContent displayContent, displayInfo.overscanBottom = bottom; } - mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, left, top, right, bottom); + mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top, + right, bottom); mDisplaySettings.writeSettingsLocked(); reconfigureDisplayLocked(displayContent); @@ -10184,6 +10194,7 @@ private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMe } } + winAnimator.computeShownFrameLocked(); winAnimator.setSurfaceBoundariesLocked(recoveringMemory); } @@ -11969,6 +11980,14 @@ public Object getWindowManagerLock() { return mWindowMap; } + @Override + public void setLiveLockscreenEdgeDetector(boolean enable) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) + == PackageManager.PERMISSION_GRANTED) { + mPolicy.setLiveLockscreenEdgeDetector(enable); + } + } + private final class LocalService extends WindowManagerInternal { @Override public void requestTraversalFromDisplayManager() { diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 0496592a41152..69488b163ac8c 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -79,6 +79,3 @@ $(shell mkdir -p $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/) $(shell touch $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/export_includes) endif -ifeq ($(BOARD_HAVE_TIMERFD_POWEROFF_ALARM),true) -LOCAL_CFLAGS += -DWITH_TIMERFD_POWEROFF_ALARM -endif diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp index 80b89239d15e6..34d863cd94775 100644 --- a/services/core/jni/com_android_server_AlarmManagerService.cpp +++ b/services/core/jni/com_android_server_AlarmManagerService.cpp @@ -40,6 +40,8 @@ #include #include +#include + #if HAVE_QC_TIME_SERVICES extern "C" { #include @@ -48,18 +50,16 @@ extern "C" { namespace android { -static const clockid_t android_alarm_to_clockid[] = { +static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1; +static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { CLOCK_REALTIME_ALARM, CLOCK_REALTIME, CLOCK_BOOTTIME_ALARM, CLOCK_BOOTTIME, CLOCK_MONOTONIC, -#ifdef WITH_TIMERFD_POWEROFF_ALARM CLOCK_POWEROFF_ALARM, -#endif CLOCK_REALTIME, }; -static const size_t N_ANDROID_TIMERFDS = sizeof(android_alarm_to_clockid)/sizeof(clockid_t); /* to match the legacy alarm driver implementation, we need an extra CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */ @@ -182,7 +182,7 @@ AlarmImplTimerFd::~AlarmImplTimerFd() int AlarmImplTimerFd::set(int type, struct timespec *ts) { - if (type >= static_cast(N_ANDROID_TIMERFDS)) { + if (type > ANDROID_ALARM_TYPE_COUNT) { errno = EINVAL; return -1; } @@ -202,7 +202,7 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts) int AlarmImplTimerFd::clear(int type, struct timespec *ts) { - if (type >= static_cast(N_ANDROID_TIMERFDS)) { + if (type > ANDROID_ALARM_TYPE_COUNT) { errno = EINVAL; return -1; } @@ -283,7 +283,7 @@ int AlarmImplTimerFd::waitForAlarm() uint64_t unused; ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused)); if (err < 0) { - if (alarm_idx == (N_ANDROID_TIMERFDS - 1) && errno == ECANCELED) { + if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) { result |= ANDROID_ALARM_TIME_CHANGE_MASK; } else { return err; @@ -380,14 +380,14 @@ static bool rtc_is_hctosys(unsigned int rtc_id) static int wall_clock_rtc() { - DIR *dir = opendir(rtc_sysfs); - if (!dir) { + std::unique_ptr dir(opendir(rtc_sysfs), closedir); + if (!dir.get()) { ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno)); return -1; } struct dirent *dirent; - while (errno = 0, dirent = readdir(dir)) { + while (errno = 0, dirent = readdir(dir.get())) { unsigned int rtc_id; int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id); @@ -424,6 +424,10 @@ static jlong init_timerfd() for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { fds[i] = timerfd_create(android_alarm_to_clockid[i], 0); + if ((fds[i] < 0) && (android_alarm_to_clockid[i] == CLOCK_POWEROFF_ALARM)) { + ALOGV("timerfd does not support CLOCK_POWEROFF_ALARM, using CLOCK_REALTIME_ALARM instead"); + fds[i] = timerfd_create(CLOCK_REALTIME_ALARM, 0); + } if (fds[i] < 0) { ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i], strerror(errno)); @@ -455,7 +459,7 @@ static jlong init_timerfd() /* 0 = disarmed; the timerfd doesn't need to be armed to get RTC change notifications, just set up as cancelable */ - int err = timerfd_settime(fds[N_ANDROID_TIMERFDS - 1], + int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT], TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL); if (err < 0) { ALOGV("timerfd_settime() failed: %s", strerror(errno)); diff --git a/services/core/jni/com_android_server_PersistentDataBlockService.cpp b/services/core/jni/com_android_server_PersistentDataBlockService.cpp index 4ccfa56cd30cb..9b0393b44d727 100644 --- a/services/core/jni/com_android_server_PersistentDataBlockService.cpp +++ b/services/core/jni/com_android_server_PersistentDataBlockService.cpp @@ -84,7 +84,11 @@ namespace android { if (fd < 0) return 0; - return get_block_device_size(fd); + const uint64_t size = get_block_device_size(fd); + + close(fd); + + return size; } static int com_android_server_PersistentDataBlockService_wipe(JNIEnv *env, jclass, jstring jpath) { @@ -94,7 +98,11 @@ namespace android { if (fd < 0) return 0; - return wipe_block_device(fd); + const int ret = wipe_block_device(fd); + + close(fd); + + return ret; } static JNINativeMethod sMethods[] = { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b2cb2ff81d90f..302d23a636f3f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4215,18 +4215,8 @@ public boolean requireSecureKeyguard(int userHandle) { || encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING) { return true; } - - // Keystore.isEmpty() requires system UID - long token = Binder.clearCallingIdentity(); - try { - if (!KeyStore.getInstance().isEmpty()) { - return true; - } - } finally { - Binder.restoreCallingIdentity(token); - } - - return false; + final int keyguardDisabledFeatures = getKeyguardDisabledFeatures(null, userHandle); + return (keyguardDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; } // Returns the active device owner or null if there is no device owner. diff --git a/services/java/com/android/server/AppsFailureReceiver.java b/services/java/com/android/server/AppsFailureReceiver.java deleted file mode 100644 index e99b7a4eda8e7..0000000000000 --- a/services/java/com/android/server/AppsFailureReceiver.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2010, T-Mobile USA, Inc. - * Copyright (C) 2015 The CyanogenMod 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; - -import android.app.Notification; -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ThemeUtils; -import android.content.res.ThemeChangeRequest; -import android.content.res.ThemeChangeRequest.RequestType; -import android.content.res.ThemeConfig; -import android.content.res.ThemeManager; -import android.os.SystemClock; - -import com.android.internal.R; - -public class AppsFailureReceiver extends BroadcastReceiver { - - private static final int FAILURES_THRESHOLD = 3; - private static final int EXPIRATION_TIME_IN_MILLISECONDS = 30000; // 30 seconds - - private static final int THEME_RESET_NOTIFICATION_ID = 0x4641494C; - - private int mFailuresCount = 0; - private long mStartTime = 0; - - // This function implements the following logic. - // If after a theme was applied the number of application launch failures - // at any moment was equal to FAILURES_THRESHOLD - // in less than EXPIRATION_TIME_IN_MILLISECONDS - // the default theme is applied unconditionally. - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_APP_FAILURE)) { - long currentTime = SystemClock.uptimeMillis(); - String pkgName = intent.getStringExtra("package"); - if (currentTime - mStartTime > EXPIRATION_TIME_IN_MILLISECONDS) { - // reset both the count and the timer - mStartTime = currentTime; - mFailuresCount = 0; - } - if (mFailuresCount <= FAILURES_THRESHOLD) { - mFailuresCount++; - if (mFailuresCount == FAILURES_THRESHOLD) { - // let the theme manager take care of getting us back on the default theme - ThemeManager tm = - (ThemeManager) context.getSystemService(Context.THEME_SERVICE); - final String themePkgName = ThemeConfig.SYSTEM_DEFAULT; - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - builder.setOverlay(themePkgName) - .setStatusBar(themePkgName) - .setNavBar(themePkgName) - .setIcons(themePkgName) - .setFont(themePkgName) - .setBootanimation(themePkgName) - .setWallpaper(themePkgName) - .setLockWallpaper(themePkgName) - .setAlarm(themePkgName) - .setNotification(themePkgName) - .setRingtone(themePkgName) - .setRequestType(RequestType.THEME_RESET); - // Since we are resetting everything to the system theme, we can have the - // theme service remove all per app themes without setting them explicitly :) - tm.requestThemeChange(builder.build(), true); - postThemeResetNotification(context); - } - } - } else if (action.equals(Intent.ACTION_APP_FAILURE_RESET) - || action.equals(ThemeUtils.ACTION_THEME_CHANGED)) { - mFailuresCount = 0; - mStartTime = SystemClock.uptimeMillis(); - } else if (action.equals(Intent.ACTION_PACKAGE_ADDED) || - action.equals(Intent.ACTION_PACKAGE_REMOVED)) { - mFailuresCount = 0; - mStartTime = SystemClock.uptimeMillis(); - } - } - - /** - * Posts a notification to let the user know their theme was reset - * @param context - */ - private void postThemeResetNotification(Context context) { - NotificationManager nm = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - String title = context.getString(R.string.theme_reset_notification_title); - String body = context.getString(R.string.theme_reset_notification_body); - Notification notice = new Notification.Builder(context) - .setAutoCancel(true) - .setOngoing(false) - .setContentTitle(title) - .setContentText(body) - .setStyle(new Notification.BigTextStyle().bigText(body)) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setWhen(System.currentTimeMillis()) - .setCategory(Notification.CATEGORY_SYSTEM) - .setPriority(Notification.PRIORITY_MAX) - .build(); - nm.notify(THEME_RESET_NOTIFICATION_ID, notice); - } -} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3146366854f14..d19f8acad238f 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -18,6 +18,7 @@ import android.app.ActivityManagerNative; import android.app.ActivityThread; +import android.app.IActivityManager; import android.app.IAlarmManager; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; @@ -25,16 +26,11 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.ThemeUtils; import android.content.res.Configuration; import android.content.res.Resources.Theme; import android.database.ContentObserver; -import android.database.Cursor; -import android.content.res.ThemeConfig; -import android.database.ContentObserver; import android.os.Build; import android.os.Environment; import android.os.FactoryTest; @@ -47,7 +43,6 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.IMountService; -import android.provider.Settings; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; @@ -81,7 +76,6 @@ import com.android.server.notification.NotificationManagerService; import com.android.server.os.SchedulingPolicyService; import com.android.server.pm.BackgroundDexOptService; -import com.android.server.gesture.EdgeGestureService; import com.android.server.pm.Installer; import com.android.server.pm.LauncherAppsService; import com.android.server.pm.PackageManagerService; @@ -106,6 +100,9 @@ import dalvik.system.VMRuntime; import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; @@ -333,7 +330,7 @@ private void performPendingShutdown() { private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); - mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + mSystemContext.setTheme(com.android.internal.R.style.Theme_Power_Dialog); } /** @@ -462,8 +459,9 @@ private void startOtherServices() { boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false); boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false); boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); - String[] externalServices = context.getResources() - .getStringArray(com.android.internal.R.array.config_externalCMServices); + String externalServer = context.getResources().getString( + org.cyanogenmod.platform.internal.R.string.config_externalSystemServer); + boolean disableAtlas = SystemProperties.getBoolean("config.disable_atlas", false); try { Slog.i(TAG, "Reading configuration..."); @@ -569,8 +567,6 @@ private void startOtherServices() { AssetAtlasService atlas = null; MediaRouterService mediaRouter = null; GestureService gestureService = null; - EdgeGestureService edgeGestureService = null; - ThemeService themeService = null; // Bring up services needed for UI. if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { @@ -625,10 +621,8 @@ private void startOtherServices() { } try { - ActivityManagerNative.getDefault().showBootMessage( - context.getResources().getText( - com.android.internal.R.string.android_upgrading_starting_apps), - false); + ActivityManagerNative.getDefault().updateBootProgress( + IActivityManager.BOOT_STAGE_STARTING_APPS, null, 0, 0, false); } catch (RemoteException e) { } @@ -854,6 +848,11 @@ private void startOtherServices() { if (!disableNonCoreServices) { mSystemServiceManager.startService(DockObserver.class); + + if (context.getPackageManager().hasSystemFeature + (PackageManager.FEATURE_WATCH)) { + mSystemServiceManager.startService(ThermalObserver.class); + } } try { @@ -961,7 +960,7 @@ private void startOtherServices() { mSystemServiceManager.startService(DreamManagerService.class); } - if (!disableNonCoreServices) { + if (!disableNonCoreServices && !disableAtlas) { try { Slog.i(TAG, "Assets Atlas Service"); atlas = new AssetAtlasService(context); @@ -1003,14 +1002,6 @@ private void startOtherServices() { mSystemServiceManager.startService(TvInputManagerService.class); } - try { - Slog.i(TAG, "Theme Service"); - themeService = new ThemeService(context); - ServiceManager.addService(Context.THEME_SERVICE, themeService); - } catch (Throwable e) { - reportWtf("starting Theme Service", e); - } - if (!disableNonCoreServices) { try { Slog.i(TAG, "Media Router Service"); @@ -1034,14 +1025,6 @@ private void startOtherServices() { } mSystemServiceManager.startService(LauncherAppsService.class); - - try { - Slog.i(TAG, "EdgeGesture service"); - edgeGestureService = new EdgeGestureService(context, inputManager); - ServiceManager.addService("edgegestureservice", edgeGestureService); - } catch (Throwable e) { - Slog.e(TAG, "Failure starting EdgeGesture service", e); - } } if (!disableNonCoreServices) { @@ -1072,13 +1055,22 @@ private void startOtherServices() { // MMS service broker mmsService = mSystemServiceManager.startService(MmsServiceBroker.class); - for (String service : externalServices) { - try { - Slog.i(TAG, service); - mSystemServiceManager.startService(service); - } catch (Throwable e) { - reportWtf("starting " + service , e); - } + final Class serverClazz; + try { + serverClazz = Class.forName(externalServer); + final Constructor constructor = serverClazz.getDeclaredConstructor(Context.class); + constructor.setAccessible(true); + final Object baseObject = constructor.newInstance(mSystemContext); + final Method method = baseObject.getClass().getDeclaredMethod("run"); + method.setAccessible(true); + method.invoke(baseObject); + } catch (ClassNotFoundException + | IllegalAccessException + | InvocationTargetException + | InstantiationException + | NoSuchMethodException e) { + Slog.wtf(TAG, "Unable to start " + externalServer); + Slog.wtf(TAG, e); } // It is now time to start up the app processes... @@ -1121,6 +1113,12 @@ private void startOtherServices() { w.getDefaultDisplay().getMetrics(metrics); context.getResources().updateConfiguration(config, metrics); + // The system context's theme may be configuration-dependent. + final Theme systemTheme = context.getTheme(); + if (systemTheme.getChangingConfigurations() != 0) { + systemTheme.rebase(); + } + try { // TODO: use boot phase mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); @@ -1141,14 +1139,6 @@ private void startOtherServices() { reportWtf("making Display Manager Service ready", e); } - if (edgeGestureService != null) { - try { - edgeGestureService.systemReady(); - } catch (Throwable e) { - reportWtf("making EdgeGesture service ready", e); - } - } - if (gestureService != null) { try { gestureService.systemReady(); @@ -1157,16 +1147,6 @@ private void startOtherServices() { } } - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_APP_FAILURE); - filter.addAction(Intent.ACTION_APP_FAILURE_RESET); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addAction(ThemeUtils.ACTION_THEME_CHANGED); - filter.addCategory(Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE); - filter.addDataScheme("package"); - context.registerReceiver(new AppsFailureReceiver(), filter); - // These are needed to propagate to the runnable below. final NetworkManagementService networkManagementF = networkManagement; final NetworkStatsService networkStatsF = networkStats; @@ -1187,7 +1167,6 @@ private void startOtherServices() { final MediaRouterService mediaRouterF = mediaRouter; final AudioService audioServiceF = audioService; final MmsServiceBroker mmsServiceF = mmsService; - final ThemeService themeServiceF = themeService; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -1210,15 +1189,6 @@ public void run() { Slog.i(TAG, "WebViewFactory preparation"); WebViewFactory.prepareWebViewInSystemServer(); - // Start Nfc before SystemUi to ensure NfcTile and other apps gets a - // valid NfcAdapter from NfcManager - try { - startNfcService(context); - } catch (Throwable e) { - // Don't crash. Nfc is an optional service. Just annotate that isn't ready - Slog.e(TAG, "Nfc service didn't start. Nfc will not be available.", e); - } - try { startSystemUi(context); } catch (Throwable e) { @@ -1326,17 +1296,6 @@ public void run() { } catch (Throwable e) { reportWtf("Notifying MmsService running", e); } - - try { - // now that the system is up, apply default theme if applicable - if (themeServiceF != null) themeServiceF.systemRunning(); - ThemeConfig themeConfig = - ThemeConfig.getBootTheme(context.getContentResolver()); - String iconPkg = themeConfig.getIconPackPkgName(); - mPackageManagerService.updateIconMapping(iconPkg); - } catch (Throwable e) { - reportWtf("Icon Mapping failed", e); - } } }); } @@ -1348,23 +1307,4 @@ static final void startSystemUi(Context context) { //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.OWNER); } - - static final void startNfcService(Context context) { - IPackageManager pm = ActivityThread.getPackageManager(); - if (pm == null) { - Slog.w(TAG, "Cannot get package manager, assuming no NFC feature"); - return; - } - try { - if (pm.hasSystemFeature(PackageManager.FEATURE_NFC)) { - Intent intent = new Intent(); - intent.setComponent(new ComponentName("com.android.nfc", - "com.android.nfc.NfcBootstrapService")); - context.startServiceAsUser(intent, UserHandle.OWNER); - } - } catch (RemoteException e) { - Slog.w(TAG, "Package manager query failed, assuming no NFC feature", e); - return; - } - } } diff --git a/services/java/com/android/server/gesture/EdgeGestureInputFilter.java b/services/java/com/android/server/gesture/EdgeGestureInputFilter.java deleted file mode 100644 index c42b7d098b45d..0000000000000 --- a/services/java/com/android/server/gesture/EdgeGestureInputFilter.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * 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.gesture; - -import android.content.Context; -import android.content.res.Resources; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.Trace; -import android.util.Slog; -import android.view.Display; -import android.view.DisplayInfo; -import android.view.IInputFilter; -import android.view.IInputFilterHost; -import android.view.InputDevice; -import android.view.InputEvent; -import android.view.MotionEvent; -import android.view.WindowManagerPolicy; -import android.view.MotionEvent.PointerCoords; -import android.view.MotionEvent.PointerProperties; - -import com.android.internal.R; -import com.android.internal.util.gesture.EdgeGesturePosition; -import com.android.server.gesture.EdgeGestureTracker.OnActivationListener; - -import java.io.PrintWriter; - -/** - * A simple input filter, that listens for edge swipe gestures in the motion event input - * stream. - *

- * There are 5 distinct states of this filter. - * 1) LISTEN: - * mTracker.active == false - * All motion events are passed through. If a ACTION_DOWN within a gesture trigger area happen - * switch to DETECTING. - * 2) DETECTING: - * mTracker.active == true - * All events are buffered now, and the gesture is checked by mTracker. If mTracker rejects - * the gesture (hopefully as fast as possible) all cached events will be flushed out and the - * filter falls back to LISTEN. - * If mTracker accepts the gesture, clear all cached events and go to LOCKED. - * 3) LOCKED: - * mTracker.active == false - * All events will be cached until the state changes to SYNTHESIZE through a filter - * unlock event. If there is a ACTION_UP, _CANCEL or any PointerId differently to the last - * event seen when mTracker accepted the gesture, we flush all events and go to LISTEN. - * 4) SYNTHESIZE: - * The first motion event found will be turned into a ACTION_DOWN event, all previous events - * will be discarded. - * 5) POSTSYNTHESIZE: - * mSyntheticDownTime != -1 - * All following events will have the down time set to the synthesized ACTION_DOWN event time - * until an ACTION_UP or ACTION_CANCEL is encountered and the state is reset to LISTEN. - * 6) DROP: - * All following events will be discarded. If there is an ACTION_UP, _CANCEL - * we go to LISTEN state. - *

- * If you are reading this within Java Doc, you are doing something wrong ;) - */ -public class EdgeGestureInputFilter implements IInputFilter { - /* WARNING!! The IInputFilter interface is used directly, there is no Binder between this and - * the InputDispatcher. - * This is fine, because it prevents unnecessary parceling, but beware: - * This means we are running on the dispatch or listener thread of the input dispatcher. Every - * cycle we waste here adds to the overall input latency. - */ - private static final String TAG = "EdgeGestureInputFilter"; - private static final boolean DEBUG = false; - private static final boolean DEBUG_INPUT = false; - // TODO: Should be turned off in final commit - private static final boolean SYSTRACE = false; - - private final Handler mHandler; - - private IInputFilterHost mHost = null; // dispatcher thread - - private static final class MotionEventInfo { - private static final int MAX_POOL_SIZE = 16; - - private static final Object sLock = new Object(); - private static MotionEventInfo sPool; - private static int sPoolSize; - - private boolean mInPool; - - public static MotionEventInfo obtain(MotionEvent event, int policyFlags) { - synchronized (sLock) { - MotionEventInfo info; - if (sPoolSize > 0) { - sPoolSize--; - info = sPool; - sPool = info.next; - info.next = null; - info.mInPool = false; - } else { - info = new MotionEventInfo(); - } - info.initialize(event, policyFlags); - return info; - } - } - - private void initialize(MotionEvent event, int policyFlags) { - this.event = MotionEvent.obtain(event); - this.policyFlags = policyFlags; - cachedTimeMillis = SystemClock.uptimeMillis(); - } - - public void recycle() { - synchronized (sLock) { - if (mInPool) { - throw new IllegalStateException("Already recycled."); - } - clear(); - if (sPoolSize < MAX_POOL_SIZE) { - sPoolSize++; - next = sPool; - sPool = this; - mInPool = true; - } - } - } - - private void clear() { - event.recycle(); - event = null; - policyFlags = 0; - } - - public MotionEventInfo next; - public MotionEvent event; - public int policyFlags; - public long cachedTimeMillis; - } - private final Object mLock = new Object(); - private MotionEventInfo mMotionEventQueue; // guarded by mLock - private MotionEventInfo mMotionEventQueueTail; // guarded by mLock - /* DEBUG */ - private int mMotionEventQueueCountDebug; // guarded by mLock - - private int mDeviceId; // dispatcher only - private enum State { - LISTEN, DETECTING, LOCKED, SYNTHESIZE, POSTSYNTHESIZE, DROP; - } - private State mState = State.LISTEN; // guarded by mLock - private EdgeGestureTracker mTracker; // guarded by mLock - private volatile int mPositions; // written by handler / read by dispatcher - private volatile int mSensitivity; // written by handler / read by dispatcher - - // only used by dispatcher - private long mSyntheticDownTime = -1; - private PointerCoords[] mTempPointerCoords = new PointerCoords[1]; - private PointerProperties[] mTempPointerProperties = new PointerProperties[1]; - - public EdgeGestureInputFilter(Context context, Handler handler) { - mHandler = handler; - - final Resources res = context.getResources(); - mTracker = new EdgeGestureTracker(res.getDimensionPixelSize( - R.dimen.edge_gesture_trigger_thickness), - res.getDimensionPixelSize(R.dimen.edge_gesture_trigger_distance), - res.getDimensionPixelSize(R.dimen.edge_gesture_perpendicular_distance)); - mTracker.setOnActivationListener(new OnActivationListener() { - public void onActivation(MotionEvent event, int touchX, int touchY, EdgeGesturePosition position) { - // mLock is held by #processMotionEvent - mHandler.obtainMessage(EdgeGestureService.MSG_EDGE_GESTURE_ACTIVATION, - touchX, touchY, position).sendToTarget(); - mState = State.LOCKED; - } - }); - mTempPointerCoords[0] = new PointerCoords(); - mTempPointerProperties[0] = new PointerProperties(); - } - - // called from handler thread (lock taken) - public void updateDisplay(Display display, DisplayInfo displayInfo) { - synchronized (mLock) { - mTracker.updateDisplay(display); - } - } - - // called from handler thread (lock taken) - public void updatePositions(int positions) { - mPositions = positions; - } - - // called from handler thread (lock taken) - public void updateSensitivity(int sensitivity) { - mSensitivity = sensitivity; - } - - // called from handler thread - public boolean unlockFilter() { - synchronized (mLock) { - if (mState == State.LOCKED) { - mState = State.SYNTHESIZE; - return true; - } - } - return false; - } - - public boolean dropSequence() { - synchronized (mLock) { - if (mState == State.LOCKED) { - mState = State.DROP; - return true; - } - } - return false; - } - - /** - * Called to enqueue the input event for filtering. - * The event must be recycled after the input filter processed it. - * This method is guaranteed to be non-reentrant. - * - * @see InputFilter#filterInputEvent(InputEvent, int) - * @param event The input event to enqueue. - */ - // called by the input dispatcher thread - public void filterInputEvent(InputEvent event, int policyFlags) throws RemoteException { - if (SYSTRACE) { - Trace.traceBegin(Trace.TRACE_TAG_INPUT, "filterInputEvent"); - } - try { - if (((event.getSource() & InputDevice.SOURCE_TOUCHSCREEN) - != InputDevice.SOURCE_TOUCHSCREEN) - || !(event instanceof MotionEvent)) { - sendInputEvent(event, policyFlags); - return; - } - if (DEBUG_INPUT) { - Slog.d(TAG, "Received event: " + event + ", policyFlags=0x" - + Integer.toHexString(policyFlags)); - } - MotionEvent motionEvent = (MotionEvent) event; - final int deviceId = event.getDeviceId(); - if (deviceId != mDeviceId) { - processDeviceSwitch(deviceId, motionEvent, policyFlags); - } else { - if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) { - synchronized (mLock) { - clearAndResetStateLocked(false, true); - } - } - processMotionEvent(motionEvent, policyFlags); - } - } finally { - event.recycle(); - if (SYSTRACE) { - Trace.traceEnd(Trace.TRACE_TAG_INPUT); - } - } - } - - private void processDeviceSwitch(int deviceId, MotionEvent motionEvent, int policyFlags) { - if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) { - mDeviceId = deviceId; - synchronized (mLock) { - clearAndResetStateLocked(true, false); - processMotionEvent(motionEvent, policyFlags); - } - } else { - sendInputEvent(motionEvent, policyFlags); - } - } - - private void processMotionEvent(MotionEvent motionEvent, int policyFlags) { - final int action = motionEvent.getActionMasked(); - - synchronized (mLock) { - switch (mState) { - case LISTEN: - if (action == MotionEvent.ACTION_DOWN) { - boolean hit = mPositions != 0 - && mTracker.start(motionEvent, mPositions, mSensitivity); - if (DEBUG) Slog.d(TAG, "start:" + hit); - if (hit) { - // cache the down event - cacheDelayedMotionEventLocked(motionEvent, policyFlags); - mState = State.DETECTING; - return; - } - } - sendInputEvent(motionEvent, policyFlags); - break; - case DETECTING: - cacheDelayedMotionEventLocked(motionEvent, policyFlags); - if (action == MotionEvent.ACTION_MOVE) { - if (mTracker.move(motionEvent)) { - // return: the tracker is either detecting or triggered onActivation - return; - } - } - if (DEBUG) { - Slog.d(TAG, "move: reset!"); - } - clearAndResetStateLocked(false, true); - break; - case LOCKED: - cacheDelayedMotionEventLocked(motionEvent, policyFlags); - if (action != MotionEvent.ACTION_MOVE) { - clearAndResetStateLocked(false, true); - } - break; - case SYNTHESIZE: - if (action == MotionEvent.ACTION_MOVE) { - clearDelayedMotionEventsLocked(); - sendSynthesizedMotionEventLocked(motionEvent, policyFlags); - mState = State.POSTSYNTHESIZE; - } else { - // This is the case where a race condition caught us: We already - // returned the handler thread that it is all right to call - // #gainTouchFocus(), but apparently this was wrong, as the gesture - // was canceled now. - clearAndResetStateLocked(false, true); - } - break; - case POSTSYNTHESIZE: - motionEvent.setDownTime(mSyntheticDownTime); - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - mState = State.LISTEN; - mSyntheticDownTime = -1; - } - sendInputEvent(motionEvent, policyFlags); - break; - case DROP: - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - clearDelayedMotionEventsLocked(); - mState = State.LISTEN; - } - break; - } - } - } - - private void clearAndResetStateLocked(boolean force, boolean shift) { - // ignore soft reset in POSTSYNTHESIZE, because we need to tamper with - // the event stream and going to LISTEN after an ACTION_UP anyway - if (!force && (mState == State.POSTSYNTHESIZE)) { - return; - } - switch (mState) { - case LISTEN: - // this is a nop - break; - case DETECTING: - mTracker.reset(); - // intentionally no break here - case LOCKED: - case SYNTHESIZE: - sendDelayedMotionEventsLocked(shift); - break; - case POSTSYNTHESIZE: - // hard reset (this will break the event stream) - Slog.w(TAG, "Quit POSTSYNTHESIZE without ACTION_UP from ACTION_DOWN at " - + mSyntheticDownTime); - mSyntheticDownTime = -1; - break; - } - // if there are future events that need to be tampered with, goto POSTSYNTHESIZE - mState = mSyntheticDownTime == -1 ? State.LISTEN : State.POSTSYNTHESIZE; - } - - private void sendInputEvent(InputEvent event, int policyFlags) { - try { - mHost.sendInputEvent(event, policyFlags); - } catch (RemoteException e) { - /* ignore */ - } - } - - private void cacheDelayedMotionEventLocked(MotionEvent event, int policyFlags) { - MotionEventInfo info = MotionEventInfo.obtain(event, policyFlags); - if (mMotionEventQueue == null) { - mMotionEventQueue = info; - } else { - mMotionEventQueueTail.next = info; - } - mMotionEventQueueTail = info; - mMotionEventQueueCountDebug++; - if (SYSTRACE) { - Trace.traceCounter(Trace.TRACE_TAG_INPUT, "meq", mMotionEventQueueCountDebug); - } - } - - private void sendDelayedMotionEventsLocked(boolean shift) { - while (mMotionEventQueue != null) { - MotionEventInfo info = mMotionEventQueue; - mMotionEventQueue = info.next; - - if (DEBUG) { - Slog.d(TAG, "Replay event: " + info.event); - } - mMotionEventQueueCountDebug--; - if (SYSTRACE) { - Trace.traceCounter(Trace.TRACE_TAG_INPUT, "meq", mMotionEventQueueCountDebug); - } - if (shift) { - final long offset = SystemClock.uptimeMillis() - info.cachedTimeMillis; - if (info.event.getActionMasked() == MotionEvent.ACTION_DOWN) { - mSyntheticDownTime = info.event.getDownTime() + offset; - } - sendMotionEventWithOffsetLocked(info.event, info.policyFlags, mSyntheticDownTime, offset); - if (info.event.getActionMasked() == MotionEvent.ACTION_UP) { - mSyntheticDownTime = -1; - } - } else { - sendInputEvent(info.event, info.policyFlags); - } - info.recycle(); - } - mMotionEventQueueTail = null; - } - - private void clearDelayedMotionEventsLocked() { - while (mMotionEventQueue != null) { - MotionEventInfo next = mMotionEventQueue.next; - mMotionEventQueue.recycle(); - mMotionEventQueue = next; - } - mMotionEventQueueTail = null; - mMotionEventQueueCountDebug = 0; - if (SYSTRACE) { - Trace.traceCounter(Trace.TRACE_TAG_INPUT, "meq", mMotionEventQueueCountDebug); - } - } - - private void sendMotionEventWithOffsetLocked(MotionEvent event, int policyFlags, - long downTime, long offset) { - final int pointerCount = event.getPointerCount(); - PointerCoords[] coords = getTempPointerCoordsWithMinSizeLocked(pointerCount); - PointerProperties[] properties = getTempPointerPropertiesWithMinSizeLocked(pointerCount); - for (int i = 0; i < pointerCount; i++) { - event.getPointerCoords(i, coords[i]); - event.getPointerProperties(i, properties[i]); - } - final long eventTime = event.getEventTime() + offset; - sendInputEvent(MotionEvent.obtain(downTime, eventTime, event.getAction(), pointerCount, - properties, coords, event.getMetaState(), event.getButtonState(), 1.0f, 1.0f, - event.getDeviceId(), event.getEdgeFlags(), event.getSource(), event.getFlags()), - policyFlags); - } - - private PointerCoords[] getTempPointerCoordsWithMinSizeLocked(int size) { - final int oldSize = mTempPointerCoords.length; - if (oldSize < size) { - PointerCoords[] oldTempPointerCoords = mTempPointerCoords; - mTempPointerCoords = new PointerCoords[size]; - System.arraycopy(oldTempPointerCoords, 0, mTempPointerCoords, 0, oldSize); - } - for (int i = oldSize; i < size; i++) { - mTempPointerCoords[i] = new PointerCoords(); - } - return mTempPointerCoords; - } - - private PointerProperties[] getTempPointerPropertiesWithMinSizeLocked(int size) { - final int oldSize = mTempPointerProperties.length; - if (oldSize < size) { - PointerProperties[] oldTempPointerProperties = mTempPointerProperties; - mTempPointerProperties = new PointerProperties[size]; - System.arraycopy(oldTempPointerProperties, 0, mTempPointerProperties, 0, oldSize); - } - for (int i = oldSize; i < size; i++) { - mTempPointerProperties[i] = new PointerProperties(); - } - return mTempPointerProperties; - } - - private void sendSynthesizedMotionEventLocked(MotionEvent event, int policyFlags) { - if (event.getPointerCount() == 1) { - event.getPointerCoords(0, mTempPointerCoords[0]); - event.getPointerProperties(0, mTempPointerProperties[0]); - MotionEvent down = MotionEvent.obtain(event.getEventTime(), event.getEventTime(), - MotionEvent.ACTION_DOWN, 1, mTempPointerProperties, mTempPointerCoords, - event.getMetaState(), event.getButtonState(), - 1.0f, 1.0f, event.getDeviceId(), event.getEdgeFlags(), - event.getSource(), event.getFlags()); - Slog.d(TAG, "Synthesized event:" + down); - sendInputEvent(down, policyFlags); - mSyntheticDownTime = event.getEventTime(); - } else { - Slog.w(TAG, "Could not synthesize MotionEvent, this will drop all following events!"); - } - } - - // should never be called - public IBinder asBinder() { - throw new UnsupportedOperationException(); - } - - // called by the input dispatcher thread - public void install(IInputFilterHost host) throws RemoteException { - if (DEBUG) { - Slog.d(TAG, "EdgeGesture input filter installed."); - } - mHost = host; - synchronized (mLock) { - clearAndResetStateLocked(true, false); - } - } - - // called by the input dispatcher thread - public void uninstall() throws RemoteException { - if (DEBUG) { - Slog.d(TAG, "EdgeGesture input filter uninstalled."); - } - } - - // called by a Binder thread - public void dump(PrintWriter pw, String prefix) { - synchronized (mLock) { - pw.print(prefix); - pw.println("mState=" + mState.name()); - pw.print(prefix); - pw.println("mPositions=0x" + Integer.toHexString(mPositions)); - pw.print(prefix); - pw.println("mQueue=" + mMotionEventQueueCountDebug + " items"); - } - } -} diff --git a/services/java/com/android/server/gesture/EdgeGestureService.java b/services/java/com/android/server/gesture/EdgeGestureService.java deleted file mode 100644 index 0581831869c77..0000000000000 --- a/services/java/com/android/server/gesture/EdgeGestureService.java +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * 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.gesture; - -import static com.android.internal.util.gesture.EdgeServiceConstants.POSITION_MASK; -import static com.android.internal.util.gesture.EdgeServiceConstants.SENSITIVITY_DEFAULT; -import static com.android.internal.util.gesture.EdgeServiceConstants.SENSITIVITY_MASK; -import static com.android.internal.util.gesture.EdgeServiceConstants.SENSITIVITY_NONE; -import static com.android.internal.util.gesture.EdgeServiceConstants.SENSITIVITY_SHIFT; -import static com.android.internal.util.gesture.EdgeServiceConstants.LONG_LIVING; - -import android.Manifest; -import android.content.Context; -import android.content.pm.PackageManager; -import android.hardware.display.DisplayManager; -import android.hardware.display.DisplayManager.DisplayListener; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.RemoteException; -import android.service.gesture.IEdgeGestureActivationListener; -import android.service.gesture.IEdgeGestureHostCallback; -import android.service.gesture.IEdgeGestureService; -import android.util.Slog; -import android.view.Display; -import android.view.DisplayInfo; -import android.view.WindowManager; - -import com.android.internal.util.gesture.EdgeGesturePosition; -import com.android.server.gesture.EdgeGestureInputFilter; -import com.android.server.input.InputManagerService; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * A system service to track and handle edge swipe gestures. This service interacts with - * the {@link InputManagerService} to do all the dirty work for listeners: - *

  • Installing an input filter and listen for edge swipe gestures
  • - *
  • Removing those gestures from the input stream
  • - *
  • Transferring touch focus to new recipient
  • - */ -public class EdgeGestureService extends IEdgeGestureService.Stub { - public static final String TAG = "EdgeGestureService"; - public static final boolean DEBUG = false; - public static final boolean DEBUG_INPUT = false; - - public static final int MSG_EDGE_GESTURE_ACTIVATION = 32023; - public static final int MSG_UPDATE_SERVICE = 32025; - - private final Context mContext; - private final InputManagerService mInputManager; - - private final HandlerThread mHandlerThread = new HandlerThread("EdgeGestureHandler"); - private Handler mHandler; - - // Lock for mInputFilter, activations and listener related variables - private final Object mLock = new Object(); - private EdgeGestureInputFilter mInputFilter; - - private int mGlobalPositions = 0; - private int mGlobalSensitivity = 3; - - private final class EdgeGestureActivationListenerRecord extends IEdgeGestureHostCallback.Stub implements DeathRecipient { - private boolean mActive; - - public EdgeGestureActivationListenerRecord(IEdgeGestureActivationListener listener) { - this.listener = listener; - this.positions = 0; - } - - public void binderDied() { - removeListenerRecord(this); - } - - private void updateFlags(int flags) { - this.positions = flags & POSITION_MASK; - this.sensitivity = (flags & SENSITIVITY_MASK) >> SENSITIVITY_SHIFT; - this.longLiving = (flags & LONG_LIVING) != 0; - } - - private boolean eligibleForActivation(int positionFlag) { - return (positions & positionFlag) != 0; - } - - private boolean notifyEdgeGestureActivation(int touchX, int touchY, EdgeGesturePosition position) { - if ((positions & position.FLAG) != 0) { - try { - mActive = true; - listener.onEdgeGestureActivation(touchX, touchY, position.INDEX, 0); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to notify process, assuming it died.", e); - mActive = false; - binderDied(); - } - } - return mActive; - } - - // called through Binder - public boolean gainTouchFocus(IBinder windowToken) { - if (DEBUG) { - Slog.d(TAG, "Gain touch focus for " + windowToken); - } - if (mActive) { - return mInputFilter.unlockFilter(); - } - return false; - } - - public boolean dropEventsUntilLift() { - if (DEBUG) { - Slog.d(TAG, "Will drop all next events till touch up"); - } - if (mActive) { - return mInputFilter.dropSequence(); - } - return false; - } - - // called through Binder - public void restoreListenerState() throws RemoteException { - if (DEBUG) { - Slog.d(TAG, "Restore listener state"); - } - if (mActive) { - mInputFilter.unlockFilter(); - mActive = false; - synchronized (mLock) { - // restore input filter state by updating - mHandler.sendEmptyMessage(MSG_UPDATE_SERVICE); - } - } - } - - public boolean isActive() { - return mActive; - } - - public void dump(PrintWriter pw, String prefix) { - pw.print(prefix); - pw.print("mPositions=0x" + Integer.toHexString(positions)); - pw.println(" mActive=" + mActive); - pw.print(prefix); - pw.println("mBinder=" + listener); - } - - public int positions; - public int sensitivity; - public final IEdgeGestureActivationListener listener; - public boolean longLiving = false; - } - private final List mEdgeGestureActivationListener = - new ArrayList(); - // end of lock guarded variables - - private DisplayObserver mDisplayObserver; - - // called by system server - public EdgeGestureService(Context context, InputManagerService inputManager) { - mContext = context; - mInputManager = inputManager; - } - - // called by system server - public void systemReady() { - if (DEBUG) Slog.d(TAG, "Starting the edge gesture capture thread ..."); - - synchronized (mLock) { - mHandlerThread.start(); - mHandler = new H(mHandlerThread.getLooper()); - mHandler.post(new Runnable() { - @Override - public void run() { - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_FOREGROUND); - android.os.Process.setCanSelfBackground(false); - } - }); - mDisplayObserver = new DisplayObserver(mContext, mHandler); - // check if anyone registered during startup - mHandler.sendEmptyMessage(MSG_UPDATE_SERVICE); - } - } - - - private void updateMonitoring() { - synchronized(mLock) { - mGlobalPositions = 0; - mGlobalSensitivity = SENSITIVITY_NONE; - boolean someLongLiving = false; - int activePositions = 0; - for (EdgeGestureActivationListenerRecord temp : mEdgeGestureActivationListener) { - mGlobalPositions |= temp.positions; - if (temp.isActive()) { - activePositions |= temp.positions; - } - if (temp.sensitivity != SENSITIVITY_NONE) { - mGlobalSensitivity = Math.max(mGlobalSensitivity, temp.sensitivity); - } - someLongLiving |= temp.longLiving; - } - boolean havePositions = mGlobalPositions != 0; - mGlobalPositions &= ~activePositions; - // if no special sensitivity is requested, we settle on DEFAULT - if (mGlobalSensitivity == SENSITIVITY_NONE) { - mGlobalSensitivity = SENSITIVITY_DEFAULT; - } - - if (mInputFilter == null && havePositions) { - enforceMonitoringLocked(); - } else if (mInputFilter != null && !havePositions && !someLongLiving) { - shutdownMonitoringLocked(); - } - } - } - - private void enforceMonitoringLocked() { - if (DEBUG) { - Slog.d(TAG, "Attempting to start monitoring input events ..."); - } - mInputFilter = new EdgeGestureInputFilter(mContext, mHandler); - mInputManager.registerSecondaryInputFilter(mInputFilter); - mDisplayObserver.observe(); - } - - private void shutdownMonitoringLocked() { - if (DEBUG) { - Slog.d(TAG, "Shutting down monitoring input events ..."); - } - mDisplayObserver.unobserve(); - mInputManager.unregisterSecondaryInputFilter(mInputFilter); - mInputFilter = null; - } - - // called through Binder - public IEdgeGestureHostCallback registerEdgeGestureActivationListener(IEdgeGestureActivationListener listener) { - if (mContext.checkCallingOrSelfPermission(Manifest.permission.INJECT_EVENTS) - != PackageManager.PERMISSION_GRANTED) { - Slog.w(TAG, "Permission Denial: can't register from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); - return null; - } - - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - - EdgeGestureActivationListenerRecord record = null; - synchronized(mLock) { - record = findListenerRecordLocked(listener.asBinder()); - if (record == null) { - record = new EdgeGestureActivationListenerRecord(listener); - try { - listener.asBinder().linkToDeath(record, 0); - } catch (RemoteException e) { - Slog.w(TAG, "Recipient died during registration pid=" + Binder.getCallingPid()); - return null; - } - mEdgeGestureActivationListener.add(record); - } - } - return record; - } - - // called through Binder - public void updateEdgeGestureActivationListener(IBinder listener, int positionFlags) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - synchronized(mLock) { - EdgeGestureActivationListenerRecord record = findListenerRecordLocked(listener); - if (record == null) { - Slog.w(TAG, "Unknown listener on update listener. Register first?"); - throw new IllegalStateException("listener not registered"); - } - record.updateFlags(positionFlags); - // update input filter only when #systemReady() was called - if (mHandler != null) { - mHandler.sendEmptyMessage(MSG_UPDATE_SERVICE); - } - } - } - - private EdgeGestureActivationListenerRecord findListenerRecordLocked(IBinder listener) { - for (EdgeGestureActivationListenerRecord record : mEdgeGestureActivationListener) { - if (record.listener.asBinder().equals(listener)) { - return record; - } - } - return null; - } - - private void removeListenerRecord(EdgeGestureActivationListenerRecord record) { - synchronized(mLock) { - mEdgeGestureActivationListener.remove(record); - // restore input filter state by updating - mHandler.sendEmptyMessage(MSG_UPDATE_SERVICE); - } - } - - // called by handler thread - private boolean propagateActivation(int touchX, int touchY, EdgeGesturePosition position) { - synchronized(mLock) { - EdgeGestureActivationListenerRecord target = null; - for (EdgeGestureActivationListenerRecord record : mEdgeGestureActivationListener) { - if (record.eligibleForActivation(position.FLAG)) { - target = record; - break; - } - } - // NOTE: We can do this here because the #onGestureActivation() is a oneway - // Binder call. This means we do not block with holding the mListenerLock!!! - // If this ever change, this needs to be adjusted and if you don't know what - // this means, you should probably not mess around with this code, anyway. - if (target != null && !target.notifyEdgeGestureActivation(touchX, touchY, position)) { - target = null; - } - return target != null; - } - } - - private final class H extends Handler { - public H(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message m) { - switch (m.what) { - case MSG_EDGE_GESTURE_ACTIVATION: - if (DEBUG) { - Slog.d(TAG, "Activating edge gesture on " + m.obj.toString()); - } - // Since input filter runs asynchronously to us, double activation may happen - // theoretically. Take the safe route here. - removeMessages(MSG_EDGE_GESTURE_ACTIVATION); - if (propagateActivation(m.arg1, m.arg2, (EdgeGesturePosition) m.obj)) { - // switch off activated positions - updateMonitoring(); - updateServiceHandler(mGlobalPositions, mGlobalSensitivity); - } - break; - case MSG_UPDATE_SERVICE: - updateMonitoring(); - if (DEBUG) { - Slog.d(TAG, "Updating positions 0x" + Integer.toHexString(mGlobalPositions) - + " sensitivity: " + mGlobalSensitivity); - } - updateServiceHandler(mGlobalPositions, mGlobalSensitivity); - break; - } - } - - private void updateServiceHandler(int positions, int sensitivity) { - synchronized (mLock) { - if (mInputFilter != null) { - mInputFilter.updatePositions(positions); - mInputFilter.updateSensitivity(sensitivity); - } - } - } - } - - private final class DisplayObserver implements DisplayListener { - private final Handler mHandler; - private final DisplayManager mDisplayManager; - - private final Display mDefaultDisplay; - private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo(); - - public DisplayObserver(Context context, Handler handler) { - mHandler = handler; - mDisplayManager = (DisplayManager) context.getSystemService( - Context.DISPLAY_SERVICE); - final WindowManager windowManager = (WindowManager) context.getSystemService( - Context.WINDOW_SERVICE); - - mDefaultDisplay = windowManager.getDefaultDisplay(); - updateDisplayInfo(); - } - - private void updateDisplayInfo() { - if (DEBUG) { - Slog.d(TAG, "Updating display information ..."); - } - if (mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) { - synchronized (mLock) { - if (mInputFilter != null) { - mInputFilter.updateDisplay(mDefaultDisplay, mDefaultDisplayInfo); - } - } - } else { - Slog.e(TAG, "Default display is not valid."); - } - } - - public void observe() { - mDisplayManager.registerDisplayListener(this, mHandler); - updateDisplayInfo(); - } - - public void unobserve() { - mDisplayManager.unregisterDisplayListener(this); - } - - @Override - public void onDisplayAdded(int displayId) { - /* do noting */ - } - - @Override - public void onDisplayRemoved(int displayId) { - /* do nothing */ - } - - @Override - public void onDisplayChanged(int displayId) { - updateDisplayInfo(); - } - } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - try { - return super.onTransact(code, data, reply, flags); - } catch (RuntimeException e) { - // let's log all exceptions we do not know about. - if (!(e instanceof IllegalArgumentException || e instanceof IllegalStateException)) { - Slog.e(TAG, "EdgeGestureService crashed: ", e); - } - throw e; - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump EdgeGestureService from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - pw.println("EDGE GESTURE SERVICE (dumpsys edgegestureservice)\n"); - synchronized(mLock) { - pw.println(" mInputFilter=" + mInputFilter); - if (mInputFilter != null) { - mInputFilter.dump(pw, " "); - } - pw.println(" mGlobalPositions=0x" + Integer.toHexString(mGlobalPositions)); - pw.println(" mGlobalSensitivity=" + mGlobalSensitivity); - int i = 0; - for (EdgeGestureActivationListenerRecord record : mEdgeGestureActivationListener) { - if (record.isActive()) { - pw.println(" Active record: #" + (i + 1)); - } - } - i = 0; - for (EdgeGestureActivationListenerRecord record : mEdgeGestureActivationListener) { - pw.println(" Listener #" + i + ":"); - record.dump(pw, " "); - i++; - } - } - } -} diff --git a/services/java/com/android/server/gesture/EdgeGestureTracker.java b/services/java/com/android/server/gesture/EdgeGestureTracker.java deleted file mode 100644 index 17cd95eda0d0b..0000000000000 --- a/services/java/com/android/server/gesture/EdgeGestureTracker.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * 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.gesture; - -import android.graphics.Point; -import android.os.SystemClock; -import android.util.Slog; -import android.view.Display; -import android.view.MotionEvent; - -import com.android.internal.util.gesture.EdgeGesturePosition; -import com.android.internal.util.gesture.EdgeServiceConstants; - -/** - * A simple {@link MotionEvent} tracker class. The main aim of this tracker is to - * reject gestures as fast as possible, so there is only a small amount of events - * that will be delayed. - */ -public class EdgeGestureTracker { - public final static String TAG = "EdgeGestureTracker"; - public final static boolean DEBUG = false; - - public final static long TRIGGER_TIME_MS = 140; - public final static int PIXEL_SWIPE_OFFTAKE_SLOP = 2; - - private final int mBaseThickness; - private final int mBaseTriggerDistance; - private final int mBasePerpendicularDistance; - - private int mThickness; - private int mTriggerDistance; - private int mPerpendicularDistance; - private int mGracePeriodDistance; - private long mTimeOut; - - private int mDisplayWidth; - private int mDisplayHeight; - - private boolean mActive; - private EdgeGesturePosition mPosition; - private long mDownTime; - private int mInitialX; - private int mInitialY; - private int mOffTake; - private int mGracePeriod; - - public interface OnActivationListener { - public void onActivation(MotionEvent event, int touchX, int touchY, EdgeGesturePosition position); - } - private OnActivationListener mActivationListener; - - public EdgeGestureTracker(int thickness, int distance, int perpendicular) { - if (DEBUG) { - Slog.d(TAG, "init: " + thickness + "," + distance); - } - mBaseThickness = thickness; - mBaseTriggerDistance = distance; - mBasePerpendicularDistance = perpendicular; - setSensitivity(0); - } - - private void setSensitivity(int sensitivity) { - float factor = 0.0f; - if (sensitivity >= 1) { - factor = (sensitivity - 1) / 4.0f; - } - if (DEBUG) { - Slog.d(TAG, "sensitivity: " + sensitivity + " => factor:" + factor); - } - // default values (without overlay): - // 140ms ... 210ms - mTimeOut = (long) (TRIGGER_TIME_MS * (factor + 1.0f)); - // 12dp ... 18dp - mThickness = (int) (mBaseThickness * (factor + 1.0f)); - // 12dp ... 6dp - mTriggerDistance = (int) (mBaseTriggerDistance * (1.0f - factor)); - mPerpendicularDistance = (int) (mBasePerpendicularDistance * (1.0f - factor)); - mGracePeriodDistance = (int) (mThickness / 3.0f); - } - - public void setOnActivationListener(OnActivationListener listener) { - mActivationListener = listener; - } - - public void reset() { - mActive = false; - } - - public void updateDisplay(Display display) { - Point outSize = new Point(0,0); - display.getRealSize(outSize); - mDisplayWidth = outSize.x; - mDisplayHeight = outSize.y; - if (DEBUG) { - Slog.d(TAG, "new display: " + mDisplayWidth + "," + mDisplayHeight); - } - } - - public boolean start(MotionEvent motionEvent, int positions, int sensitivity) { - final boolean unrestricted = (positions & EdgeServiceConstants.UNRESTRICTED) != 0; - final int x = (int) motionEvent.getX(); - final float fx = motionEvent.getX() / mDisplayWidth; - final int y = (int) motionEvent.getY(); - final float fy = motionEvent.getY() / mDisplayHeight; - - // calculate trigger geometry based on sensitivity - setSensitivity(sensitivity); - - if ((positions & EdgeGesturePosition.LEFT.FLAG) != 0) { - if (x < mThickness && (unrestricted || (fy > 0.1f && fy < 0.9f))) { - startWithPosition(motionEvent, EdgeGesturePosition.LEFT); - return true; - } - } - if ((positions & EdgeGesturePosition.BOTTOM.FLAG) != 0) { - if (y > mDisplayHeight - mThickness && (unrestricted || (fx > 0.1f && fx < 0.9f))) { - startWithPosition(motionEvent, EdgeGesturePosition.BOTTOM); - return true; - } - } - if ((positions & EdgeGesturePosition.RIGHT.FLAG) != 0) { - if (x > mDisplayWidth - mThickness && (unrestricted || (fy > 0.1f && fy < 0.9f))) { - startWithPosition(motionEvent, EdgeGesturePosition.RIGHT); - return true; - } - } - if ((positions & EdgeGesturePosition.TOP.FLAG) != 0) { - if (y < mThickness && (unrestricted || (fx > 0.1f && fx < 0.9f))) { - startWithPosition(motionEvent, EdgeGesturePosition.TOP); - return true; - } - } - return false; - } - - private void startWithPosition(MotionEvent motionEvent, EdgeGesturePosition position) { - if (DEBUG) { - Slog.d(TAG, "start tracking from " + position.name()); - } - - mDownTime = motionEvent.getDownTime(); - this.mPosition = position; - mInitialX = (int) motionEvent.getX(); - mInitialY = (int) motionEvent.getY(); - switch (position) { - case LEFT: - mGracePeriod = mGracePeriodDistance; - mOffTake = mInitialX - PIXEL_SWIPE_OFFTAKE_SLOP; - break; - case BOTTOM: - mOffTake = mInitialY + PIXEL_SWIPE_OFFTAKE_SLOP; - break; - case RIGHT: - mGracePeriod = mDisplayWidth - mGracePeriodDistance; - mOffTake = mInitialX + PIXEL_SWIPE_OFFTAKE_SLOP; - break; - case TOP: - mOffTake = mInitialY - PIXEL_SWIPE_OFFTAKE_SLOP; - break; - } - mActive = true; - } - - public boolean move(MotionEvent motionEvent) { - if (!mActive || motionEvent.getEventTime() - mDownTime > mTimeOut) { - Slog.d(TAG, "edge gesture timeout: " + (motionEvent.getEventTime() - mDownTime)); - mActive = false; - return false; - } - - final int x = (int) motionEvent.getX(); - final int y = (int) motionEvent.getY(); - final int deltaX = x - mInitialX; - final int deltaY = y - mInitialY; - - if (DEBUG) { - Slog.d(TAG, "move at " + x + "," + y + " " + deltaX + "," + deltaY); - } - - boolean loaded = false; - switch (mPosition) { - case LEFT: - if (x < mGracePeriod) { - mInitialY = y; - } - if (deltaY < mPerpendicularDistance && deltaY > -mPerpendicularDistance - && x >= mOffTake) { - if (deltaX < mTriggerDistance) { - mOffTake = x - PIXEL_SWIPE_OFFTAKE_SLOP; - return true; - } - loaded = true; - } - break; - case BOTTOM: - if (deltaX < mPerpendicularDistance && deltaX > -mPerpendicularDistance - && y <= mOffTake) { - if (deltaY > -mTriggerDistance) { - mOffTake = y + PIXEL_SWIPE_OFFTAKE_SLOP; - return true; - } - loaded = true; - } - break; - case RIGHT: - if (x > mGracePeriod) { - mInitialY = y; - } - if (deltaY < mPerpendicularDistance && deltaY > -mPerpendicularDistance - && x <= mOffTake) { - if (deltaX > -mTriggerDistance) { - mOffTake = x + PIXEL_SWIPE_OFFTAKE_SLOP; - return true; - } - loaded = true; - } - break; - case TOP: - if (deltaX < mPerpendicularDistance && deltaX > -mPerpendicularDistance - && y >= mOffTake) { - if (deltaY < mTriggerDistance) { - mOffTake = y - PIXEL_SWIPE_OFFTAKE_SLOP; - return true; - } - loaded = true; - } - break; - } - mActive = false; - if (loaded && mActivationListener != null) { - if (DEBUG) { - Slog.d(TAG, "activate at " + x + "," + y + " " + mPosition + " within " - + (SystemClock.uptimeMillis() - mDownTime) + "ms"); - } - mActivationListener.onActivation(motionEvent, x, y, mPosition); - } - return loaded; - } -} \ No newline at end of file diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index 8927bfa25654e..f97df83706fff 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -602,7 +602,12 @@ protected static void addTlvEnd(ByteBuffer buf) { protected void addCommonClientTlvs(ByteBuffer buf) { addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH); addTlv(buf, DHCP_VENDOR_CLASS_ID, "android-dhcp-" + Build.VERSION.RELEASE); - addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname")); + + /* the default 'android-dhcp' is there to make sure the hostname is + * never empty, because the DHCP standard forbids it (RFC2132, section + * 3.14) and certain DHCP forwarders and servers ignore such malformed + * requests */ + addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname", "android-dhcp")); } /** diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 993faa9379232..aa8b37fec713d 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -27,6 +27,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.SystemProperties; +import android.os.UserHandle; import android.test.AndroidTestCase; import android.test.mock.MockContext; import android.text.TextUtils; @@ -263,7 +264,7 @@ public void testReadKeySetSettings() writeOldFiles(); createUserManagerServiceRef(); Settings settings = new Settings(getContext().getFilesDir(), new Object()); - assertEquals(true, settings.readLPw(null, null, 0, false)); + assertEquals(true, settings.readLPw(null, null, 0, false, null)); verifyKeySetMetaData(settings); } @@ -275,11 +276,11 @@ public void testWriteKeySetSettings() writeOldFiles(); createUserManagerServiceRef(); Settings settings = new Settings(getContext().getFilesDir(), new Object()); - assertEquals(true, settings.readLPw(null, null, 0, false)); + assertEquals(true, settings.readLPw(null, null, 0, false, null)); /* write out, read back in and verify the same */ settings.writeLPr(); - assertEquals(true, settings.readLPw(null, null, 0, false)); + assertEquals(true, settings.readLPw(null, null, 0, false, null)); verifyKeySetMetaData(settings); } @@ -357,7 +358,7 @@ public void testEnableDisable() { // Checks if a package that is locked to a different region is rejected // from being installed public void testPrebundledDifferentRegionReject() { - Settings settings = new Settings(getContext(), getContext().getFilesDir()); + Settings settings = new Settings(getContext().getFilesDir()); String expectedPackageNeededForRegion = "org.cyanogenmod.restricted.package"; Resources resources = Mockito.mock(Resources.class); String[] regionRestrictedPackages = new String[] { @@ -365,7 +366,7 @@ public void testPrebundledDifferentRegionReject() { }; Mockito.when(resources.getStringArray(R.array.config_restrict_to_region_locked_devices)) .thenReturn(regionRestrictedPackages); - assertFalse(settings.shouldPrebundledPackageBeInstalled(resources, + assertFalse(settings.shouldPrebundledPackageBeInstalledForRegion(resources, expectedPackageNeededForRegion, resources)); } @@ -373,7 +374,7 @@ public void testPrebundledDifferentRegionReject() { // This also covers the test for a package that needs to be installed on a // non region locked device public void testPrebundledMatchingRegionAccept() { - Settings settings = new Settings(getContext(), getContext().getFilesDir()); + Settings settings = new Settings(getContext().getFilesDir()); String expectedPackageNeededForRegion = "org.cyanogenmod.restricted.package"; Resources resources = Mockito.mock(Resources.class); String[] regionLockedPackages = new String[] { @@ -384,7 +385,70 @@ public void testPrebundledMatchingRegionAccept() { Mockito.when(resources.getStringArray(R.array.config_restrict_to_region_locked_devices)) .thenReturn(regionLockedPackages); - assertTrue(settings.shouldPrebundledPackageBeInstalled(resources, + assertTrue(settings.shouldPrebundledPackageBeInstalledForRegion(resources, expectedPackageNeededForRegion, resources)); } + + // Shamelessly kanged from KeySetManagerServiceTest + public PackageSetting generateFakePackageSetting(String name) { + return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"), + new File(mContext.getCacheDir(), "fakeResPath"), "", "", "", + "", 1, 0, 0); + } + + // Checks if a package that was installed and currently isn't installed for the owner + // is accepted for a secondary user + public void testPrebundledSecondaryUserAccept() { + Settings settings = new Settings(getContext().getFilesDir()); + String expectedPackageToBeInstalled = "org.cyanogenmod.secondaryuser.package"; + + PackageSetting packageSetting = + generateFakePackageSetting(expectedPackageToBeInstalled); + + int userOwner = UserHandle.USER_OWNER; + int userSecondary = 1000; + + // Return true that the package was installed for the owner at some point + settings.markPrebundledPackageInstalledLPr(userOwner, expectedPackageToBeInstalled); + assertTrue(settings.wasPrebundledPackageInstalledLPr(userOwner, + expectedPackageToBeInstalled)); + + // Return false that the package was installed for the secondary user at some point + // DON'T MARK PREBUNDLED PACKAGE INSTALLED + + // Return false that the package is currently not installed for the owner + packageSetting.setInstalled(false, userOwner); + assertFalse(packageSetting.getInstalled(userOwner)); + + // Return false that the package is currently not installed for the secondary user + packageSetting.setInstalled(false, userSecondary); + assertFalse(packageSetting.getInstalled(userSecondary)); + + assertFalse(settings.shouldPrebundledPackageBeInstalledForUserLPr(packageSetting, + userSecondary, expectedPackageToBeInstalled)); + } + + // Checks if a package that was installed for a secondary user and currently isn't installed + // for the user is accepted to be reinstalled + public void testPrebundledSecondaryUserReinstallAccept() { + Settings settings = new Settings(getContext().getFilesDir()); + String expectedPackageToBeInstalled = "org.cyanogenmod.secondaryuser.package"; + + PackageSetting packageSetting = + generateFakePackageSetting(expectedPackageToBeInstalled); + + int userSecondary = 1000; + + // Return true that the package was installed for the secondary user at some point + settings.markPrebundledPackageInstalledLPr(userSecondary, expectedPackageToBeInstalled); + assertTrue(settings.wasPrebundledPackageInstalledLPr(userSecondary, + expectedPackageToBeInstalled)); + + // Return false that the package is currently not installed for the secondary user + packageSetting.setInstalled(false, userSecondary); + assertFalse(packageSetting.getInstalled(userSecondary)); + + assertFalse(settings.shouldPrebundledPackageBeInstalledForUserLPr(packageSetting, + userSecondary, expectedPackageToBeInstalled)); + } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 54d9cd98f32b3..583bac2fedb64 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -123,6 +123,7 @@ public class UsageStatsService extends SystemService implements static final int MSG_PAROLE_END_TIMEOUT = 7; static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8; static final int MSG_PAROLE_STATE_CHANGED = 9; + static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10; private final Object mLock = new Object(); Handler mHandler; @@ -144,8 +145,10 @@ public class UsageStatsService extends SystemService implements private boolean mScreenOn; private long mLastAppIdleParoledTime; + private volatile boolean mPendingOneTimeCheckIdleStates; + long mScreenOnTime; - long mScreenOnSystemTimeSnapshot; + long mLastScreenOnEventRealtime; @GuardedBy("mLock") private AppIdleHistory mAppIdleHistory = new AppIdleHistory(); @@ -188,6 +191,8 @@ public void onStart() { synchronized (mLock) { cleanUpRemovedUsersLocked(); + mLastScreenOnEventRealtime = SystemClock.elapsedRealtime(); + mScreenOnTime = readScreenOnTimeLocked(); } mRealTimeSnapshot = SystemClock.elapsedRealtime(); @@ -214,14 +219,14 @@ public void onBootPhase(int phase) { Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); - mScreenOnSystemTimeSnapshot = System.currentTimeMillis(); - synchronized (this) { - mScreenOnTime = readScreenOnTimeLocked(); - } - mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); + mDisplayManager.registerDisplayListener(mDisplayListener, null); synchronized (this) { updateDisplayLocked(); } + + if (mPendingOneTimeCheckIdleStates) { + postOneTimeCheckIdleStates(); + } } else if (phase == PHASE_BOOT_COMPLETED) { setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging()); } @@ -280,6 +285,16 @@ public void onStatsUpdated() { mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); } + @Override + public void onStatsReloaded() { + postOneTimeCheckIdleStates(); + } + + @Override + public long getAppIdleRollingWindowDurationMillis() { + return mAppIdleWallclockThresholdMillis * 2; + } + private void cleanUpRemovedUsersLocked() { final List users = mUserManager.getUsers(true); if (users == null || users.size() == 0) { @@ -354,6 +369,20 @@ void postCheckIdleStates(int userId) { mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); } + /** + * We send a different message to check idle states once, otherwise we would end up + * scheduling a series of repeating checkIdleStates each time we fired off one. + */ + void postOneTimeCheckIdleStates() { + if (mDeviceIdleController == null) { + // Not booted yet; wait for it! + mPendingOneTimeCheckIdleStates = true; + } else { + mHandler.sendEmptyMessage(MSG_ONE_TIME_CHECK_IDLE_STATES); + mPendingOneTimeCheckIdleStates = false; + } + } + /** Check all running users' or specified user's apps to see if they enter an idle state. */ void checkIdleStates(int checkUserId) { if (!mAppIdleEnabled) { @@ -380,7 +409,7 @@ void checkIdleStates(int checkUserId) { userId); synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); - final long screenOnTime = getScreenOnTimeLocked(timeNow); + final long screenOnTime = getScreenOnTimeLocked(); UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, timeNow); final int packageCount = packages.size(); @@ -396,8 +425,6 @@ void checkIdleStates(int checkUserId) { } } } - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0), - mCheckIdleIntervalMillis); } /** Check if it's been a while since last parole and let idle apps do some work */ @@ -437,21 +464,21 @@ void updateDisplayLocked() { if (screenOn == mScreenOn) return; mScreenOn = screenOn; - long now = System.currentTimeMillis(); + long now = SystemClock.elapsedRealtime(); if (mScreenOn) { - mScreenOnSystemTimeSnapshot = now; + mLastScreenOnEventRealtime = now; } else { - mScreenOnTime += now - mScreenOnSystemTimeSnapshot; + mScreenOnTime += now - mLastScreenOnEventRealtime; writeScreenOnTimeLocked(mScreenOnTime); } } - private long getScreenOnTimeLocked(long now) { + long getScreenOnTimeLocked() { + long screenOnTime = mScreenOnTime; if (mScreenOn) { - return now - mScreenOnSystemTimeSnapshot + mScreenOnTime; - } else { - return mScreenOnTime; + screenOnTime += SystemClock.elapsedRealtime() - mLastScreenOnEventRealtime; } + return screenOnTime; } private File getScreenOnTimeFile() { @@ -521,7 +548,7 @@ private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId, if (service == null) { service = new UserUsageStatsService(getContext(), userId, new File(mUsageStatsDir, Integer.toString(userId)), this); - service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis)); + service.init(currentTimeMillis, getScreenOnTimeLocked()); mUserState.put(userId, service); } return service; @@ -534,20 +561,15 @@ private long checkAndGetTimeLocked() { final long actualSystemTime = System.currentTimeMillis(); final long actualRealtime = SystemClock.elapsedRealtime(); final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; - boolean resetBeginIdleTime = false; - if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { + final long diffSystemTime = actualSystemTime - expectedSystemTime; + if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { // The time has changed. - - // Check if it's severe enough a change to reset screenOnTime - if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) { - mScreenOnSystemTimeSnapshot = actualSystemTime; - mScreenOnTime = 0; - resetBeginIdleTime = true; - } + Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds"); final int userCount = mUserState.size(); for (int i = 0; i < userCount; i++) { final UserUsageStatsService service = mUserState.valueAt(i); - service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime); + service.onTimeChanged(expectedSystemTime, actualSystemTime, getScreenOnTimeLocked(), + false); } mRealTimeSnapshot = actualRealtime; mSystemTimeSnapshot = actualSystemTime; @@ -579,7 +601,7 @@ void shutdown() { void reportEvent(UsageEvents.Event event, int userId) { synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); - final long screenOnTime = getScreenOnTimeLocked(timeNow); + final long screenOnTime = getScreenOnTimeLocked(); convertToSystemTimeLocked(event); final UserUsageStatsService service = @@ -595,7 +617,6 @@ void reportEvent(UsageEvents.Event event, int userId) { || event.mEventType == Event.SYSTEM_INTERACTION || event.mEventType == Event.USER_INTERACTION)) { if (previouslyIdle) { - // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ 0, event.mPackage)); notifyBatteryStats(event.mPackage, userId, false); @@ -636,7 +657,7 @@ void reportContentProviderUsage(String authority, String providerPkgName, int us void forceIdleState(String packageName, int userId, boolean idle) { synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); - final long screenOnTime = getScreenOnTimeLocked(timeNow); + final long screenOnTime = getScreenOnTimeLocked(); final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000; final UserUsageStatsService service = @@ -650,7 +671,6 @@ void forceIdleState(String packageName, int userId, boolean idle) { timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000); // Inform listeners if necessary if (previouslyIdle != idle) { - // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ idle ? 1 : 0, packageName)); if (!idle) { @@ -789,7 +809,7 @@ boolean isAppIdleFiltered(String packageName, int uidForAppId, int userId, long timeNow = checkAndGetTimeLocked(); } userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); - screenOnTime = getScreenOnTimeLocked(timeNow); + screenOnTime = getScreenOnTimeLocked(); } return isAppIdleFiltered(packageName, UserHandle.getAppId(uidForAppId), userId, userService, timeNow, screenOnTime); @@ -858,7 +878,7 @@ int[] getIdleUidsForUser(int userId) { synchronized (mLock) { timeNow = checkAndGetTimeLocked(); userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); - screenOnTime = getScreenOnTimeLocked(timeNow); + screenOnTime = getScreenOnTimeLocked(); } List apps; @@ -980,7 +1000,7 @@ private void flushToDiskLocked() { */ void dump(String[] args, PrintWriter pw) { synchronized (mLock) { - final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked()); + final long screenOnTime = getScreenOnTimeLocked(); IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); ArraySet argSet = new ArraySet<>(); argSet.addAll(Arrays.asList(args)); @@ -1001,7 +1021,11 @@ void dump(String[] args, PrintWriter pw) { } idpw.decreaseIndent(); } - pw.println("Screen On Timebase:" + mScreenOnTime); + pw.print("Screen On Timebase: "); + pw.print(screenOnTime); + pw.print(" ("); + TimeUtils.formatDuration(screenOnTime, pw); + pw.println(")"); pw.println(); pw.println("Settings:"); @@ -1035,8 +1059,8 @@ void dump(String[] args, PrintWriter pw) { pw.println(); pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw); pw.println(); - pw.print("mScreenOnSystemTimeSnapshot="); - TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw); + pw.print("mLastScreenOnEventRealtime="); + TimeUtils.formatDuration(mLastScreenOnEventRealtime, pw); pw.println(); } } @@ -1071,6 +1095,14 @@ public void handleMessage(Message msg) { case MSG_CHECK_IDLE_STATES: checkIdleStates(msg.arg1); + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MSG_CHECK_IDLE_STATES, msg.arg1, 0), + mCheckIdleIntervalMillis); + break; + + case MSG_ONE_TIME_CHECK_IDLE_STATES: + mHandler.removeMessages(MSG_ONE_TIME_CHECK_IDLE_STATES); + checkIdleStates(UserHandle.USER_ALL); break; case MSG_CHECK_PAROLE_TIMEOUT: @@ -1106,7 +1138,13 @@ public void handleMessage(Message msg) { * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}. */ private class SettingsObserver extends ContentObserver { - private static final String KEY_IDLE_DURATION = "idle_duration"; + /** + * This flag has been used to disable app idle on older builds with bug b/26355386. + */ + @Deprecated + private static final String KEY_IDLE_DURATION_OLD = "idle_duration"; + + private static final String KEY_IDLE_DURATION = "idle_duration2"; private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold"; private static final String KEY_PAROLE_INTERVAL = "parole_interval"; private static final String KEY_PAROLE_DURATION = "parole_duration"; @@ -1125,7 +1163,7 @@ void registerObserver() { @Override public void onChange(boolean selfChange) { updateSettings(); - postCheckIdleStates(UserHandle.USER_ALL); + postOneTimeCheckIdleStates(); } void updateSettings() { diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index b07b8153279d2..a9f7ae0107acf 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -59,6 +59,7 @@ class UserUsageStatsService { private final Context mContext; private final UsageStatsDatabase mDatabase; private final IntervalStats[] mCurrentStats; + private IntervalStats mAppIdleRollingWindow; private boolean mStatsChanged = false; private final UnixCalendar mDailyExpiryDate; private final StatsUpdatedListener mListener; @@ -67,6 +68,8 @@ class UserUsageStatsService { interface StatsUpdatedListener { void onStatsUpdated(); + void onStatsReloaded(); + long getAppIdleRollingWindowDurationMillis(); } UserUsageStatsService(Context context, int userId, File usageStatsDir, @@ -134,6 +137,8 @@ void init(final long currentTimeMillis, final long deviceUsageTime) { stat.updateConfigurationStats(null, stat.lastTimeSaved); } + refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime); + if (mDatabase.isNewUpdate()) { initializeDefaultsForApps(currentTimeMillis, deviceUsageTime, mDatabase.isFirstUpdate()); @@ -159,18 +164,23 @@ && getBeginIdleTime(packageName) == -1) { for (IntervalStats stats : mCurrentStats) { stats.update(packageName, currentTimeMillis, Event.SYSTEM_INTERACTION); stats.updateBeginIdleTime(packageName, deviceUsageTime); - mStatsChanged = true; } + mAppIdleRollingWindow.update(packageName, currentTimeMillis, + Event.SYSTEM_INTERACTION); + mAppIdleRollingWindow.updateBeginIdleTime(packageName, deviceUsageTime); + mStatsChanged = true; } } // Persist the new OTA-related access stats. persistActiveStats(); } - void onTimeChanged(long oldTime, long newTime, boolean resetBeginIdleTime) { + void onTimeChanged(long oldTime, long newTime, long deviceUsageTime, + boolean resetBeginIdleTime) { persistActiveStats(); mDatabase.onTimeChanged(newTime - oldTime); loadActiveStats(newTime, /* force= */ true, resetBeginIdleTime); + refreshAppIdleRollingWindow(newTime, deviceUsageTime); } void reportEvent(UsageEvents.Event event, long deviceUsageTime) { @@ -182,7 +192,7 @@ void reportEvent(UsageEvents.Event event, long deviceUsageTime) { if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) { // Need to rollover - rolloverStats(event.mTimeStamp); + rolloverStats(event.mTimeStamp, deviceUsageTime); } final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY]; @@ -212,6 +222,11 @@ void reportEvent(UsageEvents.Event event, long deviceUsageTime) { } } + if (event.mEventType != Event.CONFIGURATION_CHANGE) { + mAppIdleRollingWindow.update(event.mPackage, event.mTimeStamp, event.mEventType); + mAppIdleRollingWindow.updateBeginIdleTime(event.mPackage, deviceUsageTime); + } + notifyStatsChanged(); } @@ -223,6 +238,7 @@ void setBeginIdleTime(String packageName, long beginIdleTime) { for (IntervalStats stats : mCurrentStats) { stats.updateBeginIdleTime(packageName, beginIdleTime); } + mAppIdleRollingWindow.updateBeginIdleTime(packageName, beginIdleTime); notifyStatsChanged(); } @@ -230,6 +246,7 @@ void setSystemLastUsedTime(String packageName, long lastUsedTime) { for (IntervalStats stats : mCurrentStats) { stats.updateSystemLastUsedTime(packageName, lastUsedTime); } + mAppIdleRollingWindow.updateSystemLastUsedTime(packageName, lastUsedTime); notifyStatsChanged(); } @@ -388,9 +405,8 @@ public void combine(IntervalStats stats, boolean mutable, } long getBeginIdleTime(String packageName) { - final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]; UsageStats packageUsage; - if ((packageUsage = yearly.packageStats.get(packageName)) == null) { + if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) { return -1; } else { return packageUsage.getBeginIdleTime(); @@ -398,9 +414,8 @@ long getBeginIdleTime(String packageName) { } long getSystemLastUsedTime(String packageName) { - final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]; UsageStats packageUsage; - if ((packageUsage = yearly.packageStats.get(packageName)) == null) { + if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) { return -1; } else { return packageUsage.getLastTimeSystemUsed(); @@ -421,7 +436,7 @@ void persistActiveStats() { } } - private void rolloverStats(final long currentTimeMillis) { + private void rolloverStats(final long currentTimeMillis, final long deviceUsageTime) { final long startTime = SystemClock.elapsedRealtime(); Slog.i(TAG, mLogPrefix + "Rolling over usage stats"); @@ -462,6 +477,8 @@ private void rolloverStats(final long currentTimeMillis) { } persistActiveStats(); + refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime); + final long totalTime = SystemClock.elapsedRealtime() - startTime; Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime + " milliseconds"); @@ -521,6 +538,7 @@ private void loadActiveStats(final long currentTimeMillis, boolean force, } } } + mStatsChanged = false; mDailyExpiryDate.setTimeInMillis(currentTimeMillis); mDailyExpiryDate.addDays(1); @@ -528,6 +546,74 @@ private void loadActiveStats(final long currentTimeMillis, boolean force, Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " + sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" + tempCal.getTimeInMillis() + ")"); + + // Tell the listener that the stats reloaded, which may have changed idle states. + mListener.onStatsReloaded(); + } + + private static void mergePackageStats(IntervalStats dst, IntervalStats src, + final long deviceUsageTime) { + dst.endTime = Math.max(dst.endTime, src.endTime); + + final int srcPackageCount = src.packageStats.size(); + for (int i = 0; i < srcPackageCount; i++) { + final String packageName = src.packageStats.keyAt(i); + final UsageStats srcStats = src.packageStats.valueAt(i); + UsageStats dstStats = dst.packageStats.get(packageName); + if (dstStats == null) { + dstStats = new UsageStats(srcStats); + dst.packageStats.put(packageName, dstStats); + } else { + dstStats.add(src.packageStats.valueAt(i)); + } + + // App idle times can not begin in the future. This happens if we had a time change. + if (dstStats.mBeginIdleTime > deviceUsageTime) { + dstStats.mBeginIdleTime = deviceUsageTime; + } + } + } + + /** + * App idle operates on a rolling window of time. When we roll over time, we end up with a + * period of time where in-memory stats are empty and we don't hit the disk for older stats + * for performance reasons. Suddenly all apps will become idle. + * + * Instead, at times we do a deep query to find all the apps that have run in the past few + * days and keep the cached data up to date. + * + * @param currentTimeMillis + */ + void refreshAppIdleRollingWindow(final long currentTimeMillis, final long deviceUsageTime) { + // Start the rolling window for AppIdle requests. + final long startRangeMillis = currentTimeMillis - + mListener.getAppIdleRollingWindowDurationMillis(); + + List stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, + startRangeMillis, currentTimeMillis, new StatCombiner() { + @Override + public void combine(IntervalStats stats, boolean mutable, + List accumulatedResult) { + IntervalStats accum; + if (accumulatedResult.isEmpty()) { + accum = new IntervalStats(); + accum.beginTime = stats.beginTime; + accumulatedResult.add(accum); + } else { + accum = accumulatedResult.get(0); + } + + mergePackageStats(accum, stats, deviceUsageTime); + } + }); + + if (stats == null || stats.isEmpty()) { + mAppIdleRollingWindow = new IntervalStats(); + mergePackageStats(mAppIdleRollingWindow, + mCurrentStats[UsageStatsManager.INTERVAL_YEARLY], deviceUsageTime); + } else { + mAppIdleRollingWindow = stats.get(0); + } } // @@ -552,6 +638,9 @@ void dump(IndentingPrintWriter pw, final long screenOnTime) { pw.println(" stats"); printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true); } + + pw.println("AppIdleRollingWindow cache"); + printIntervalStats(pw, mAppIdleRollingWindow, screenOnTime, true); } private String formatDateTime(long dateTime, boolean pretty) { diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 7eab808479b75..2886ce6f608b3 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -250,7 +250,8 @@ public void systemReady() { final StorageManager storageManager = StorageManager.from(mContext); final StorageVolume primary = storageManager.getPrimaryVolume(); massStorageSupported = primary != null && primary.allowMassStorage(); - mUseUsbNotification = !massStorageSupported; + mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean( + com.android.internal.R.bool.config_usbChargingMessage); // make sure the ADB_ENABLED setting value matches the current state try { @@ -579,7 +580,13 @@ private void updateCurrentAccessory() { if (mConfigured && enteringAccessoryMode) { // successfully entered accessory mode - + if (mCurrentAccessory != null) { + Slog.w(TAG, "USB accessory re-attached, detach was not announced!"); + if (mBootCompleted) { + getCurrentSettings().accessoryDetached(mCurrentAccessory); + } + mCurrentAccessory = null; + } if (mAccessoryStrings != null) { mCurrentAccessory = new UsbAccessory(mAccessoryStrings); Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); @@ -894,6 +901,7 @@ private void updateAdbNotification() { private String getDefaultFunctions() { String func = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE); + func = UsbManager.removeFunction(func, "charging"); if (UsbManager.USB_FUNCTION_NONE.equals(func)) { func = UsbManager.USB_FUNCTION_MTP; } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 36de974b2c044..438e7bb42bd29 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -230,8 +230,20 @@ public static class Details { */ public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000; + /** + * Remote device supports call transfers. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_TRANSFER = 0x04000000; + + /** + * Call sends responses through connection. + * @hide + */ + public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x08000000; + //****************************************************************************************** - // Next CAPABILITY value: 0x04000000 + // Next CAPABILITY value: 0x10000000 //****************************************************************************************** /** @@ -400,6 +412,9 @@ public static String capabilitiesToString(int capabilities) { if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) { builder.append(" CAPABILITY_ADD_PARTICIPANT"); } + if (can(capabilities, CAPABILITY_SUPPORTS_TRANSFER)) { + builder.append(" CAPABILITY_SUPPORTS_TRANSFER"); + } builder.append("]"); return builder.toString(); } @@ -816,6 +831,16 @@ public void answer(int videoState) { mInCallAdapter.answerCall(mTelecomCallId, videoState); } + /** + * Instructs this {@link #STATE_RINGING} {@code Call} to answer. + * @param videoState The video state in which to answer the call. + * @param callWaitingResponseType Type of response for call waiting + * @hide + */ + public void answer(int videoState, int callWaitingResponseType) { + mInCallAdapter.answerCall(mTelecomCallId, videoState, callWaitingResponseType); + } + /** * Instructs this {@link #STATE_RINGING} {@code Call} to reject. * @@ -927,6 +952,15 @@ public void mergeConference() { mInCallAdapter.mergeConference(mTelecomCallId); } + /** + * Instructs this {@code Call} to connect the current active call and the call on hold. + * The current call will then disconnect. See {@link Details#CAPABILITY_SUPPORTS_TRANSFER}. + * @hide + */ + public void transferCall() { + mInCallAdapter.transferCall(mTelecomCallId); + } + /** * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}. */ @@ -1148,6 +1182,7 @@ final void internalUpdate(ParcelableCall parcelableCall, Map callI && !parcelableCall.getCannedSmsResponses().isEmpty()) { mCannedTextResponses = Collections.unmodifiableList(parcelableCall.getCannedSmsResponses()); + cannedTextResponsesChanged = true; } boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() && diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 01582a8475953..5e2ec3cfdb459 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -272,8 +272,21 @@ public abstract class Connection extends Conferenceable { */ public static final int CAPABILITY_SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE = 0x01000000; + /** + * Remote device supports call transfers. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_TRANSFER = 0x04000000; + + /** + * Indicates that the connection itself wants to handle any sort of reply response, rather than + * relying on SMS. + * @hide + */ + public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00400000; + //********************************************************************************************** - // Next CAPABILITY value: 0x04000000 + // Next CAPABILITY value: 0x00800000 //********************************************************************************************** /** @@ -458,6 +471,10 @@ public static String capabilitiesToString(int capabilities) { if (can(capabilities, CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)) { builder.append(" CAPABILITY_SINGLE_PARTY_CONFERENCE"); } + if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) { + builder.append(" CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION"); + } + builder.append("]"); return builder.toString(); } @@ -1944,6 +1961,26 @@ public void onAnswer() { */ public void onReject() {} + /** + * Transfers the current call. + * @hide + */ + public void onTransfer() { } + + /** + * Notifies ths Connection of a request reject with a message. + * + * @hide + */ + public void onReject(String replyMessage) {} + + /** + * Notifies the Connection of a request to silence the ringer. + * + * @hide + */ + public void onSilence() {} + /** * Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes. */ diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 9e4f9bbf5b811..f64fc99a8af42 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -101,7 +101,10 @@ public abstract class ConnectionService extends Service { private static final int MSG_ANSWER_VIDEO = 17; private static final int MSG_MERGE_CONFERENCE = 18; private static final int MSG_SWAP_CONFERENCE = 19; - private static final int MSG_SET_LOCAL_HOLD = 20; + private static final int MSG_REJECT_WITH_MESSAGE = 20; + private static final int MSG_SILENCE = 21; + private static final int MSG_SET_LOCAL_HOLD = 22; + private static final int MSG_EXPLICIT_TRANSFER = 23; //Proprietary values starts after this. private static final int MSG_ADD_PARTICIPANT_WITH_CONFERENCE = 30; @@ -168,6 +171,19 @@ public void reject(String callId) { mHandler.obtainMessage(MSG_REJECT, callId).sendToTarget(); } + @Override + public void rejectWithMessage(String callId, String message) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = message; + mHandler.obtainMessage(MSG_REJECT_WITH_MESSAGE, args).sendToTarget(); + } + + @Override + public void silence(String callId) { + mHandler.obtainMessage(MSG_SILENCE, callId).sendToTarget(); + } + @Override public void disconnect(String callId) { mHandler.obtainMessage(MSG_DISCONNECT, callId).sendToTarget(); @@ -247,6 +263,11 @@ public void onPostDialContinue(String callId, boolean proceed) { args.argi1 = proceed ? 1 : 0; mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget(); } + + @Override + public void explicitTransfer(String callId) { + mHandler.obtainMessage(MSG_EXPLICIT_TRANSFER, callId).sendToTarget(); + } }; private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -315,9 +336,21 @@ public void run() { case MSG_REJECT: reject((String) msg.obj); break; + case MSG_REJECT_WITH_MESSAGE: { + SomeArgs args = (SomeArgs) msg.obj; + try { + reject((String) args.arg1, (String) args.arg2); + } finally { + args.recycle(); + } + break; + } case MSG_DISCONNECT: disconnect((String) msg.obj); break; + case MSG_SILENCE: + silence((String) msg.obj); + break; case MSG_HOLD: hold((String) msg.obj); break; @@ -394,6 +427,9 @@ public void run() { } break; } + case MSG_EXPLICIT_TRANSFER: + transfer((String) msg.obj); + break; default: break; } @@ -748,6 +784,16 @@ private void reject(String callId) { findConnectionForAction(callId, "reject").onReject(); } + private void reject(String callId, String rejectWithMessage) { + Log.d(this, "reject %s with message", callId); + findConnectionForAction(callId, "reject").onReject(rejectWithMessage); + } + + private void silence(String callId) { + Log.d(this, "silence %s", callId); + findConnectionForAction(callId, "silence").onSilence(); + } + private void disconnect(String callId) { Log.d(this, "disconnect %s", callId); if (mConnectionById.containsKey(callId)) { @@ -766,6 +812,11 @@ private void hold(String callId) { } } + private void transfer(String callId) { + Log.d(this, "transfer %s", callId); + findConnectionForAction(callId, "transfer").onTransfer(); + } + private void unhold(String callId) { Log.d(this, "unhold %s", callId); if (mConnectionById.containsKey(callId)) { diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index 7d0f5a72d03c1..d660f59a7db3e 100644 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -56,6 +56,20 @@ public void answerCall(String callId, int videoState) { } } + /** + * Instructs Telecom to answer the specified call. + * + * @param callId The identifier of the call to answer. + * @param videoState The video state in which to answer the call. + * @param callWaitingResponseType Response type for call waiting. + */ + public void answerCall(String callId, int videoState, int callWaitingResponseType) { + try { + mAdapter.answerCallWithCallWaitingResponse(callId, videoState, callWaitingResponseType); + } catch (RemoteException e) { + } + } + /** * Instructs Telecom to reject the specified call. * @@ -240,6 +254,13 @@ public void mergeConference(String callId) { } } + public void transferCall(String callId) { + try { + mAdapter.transferCall(callId); + } catch (RemoteException ignored) { + } + } + /** * Instructs Telecom to swap the child calls of the specified conference call. */ diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index f890f4d15b36b..635a48be6fe6d 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -121,6 +121,14 @@ public final class PhoneAccount implements Parcelable { */ public static final int CAPABILITY_CALL_SUBJECT = 0x40; + /** + * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls. + *

    + * See {@link #getCapabilities} + * @hide + */ + public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80; + /** * URI scheme for telephone number URIs. */ diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 673adb2b0e0a7..ca9792b51233a 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -116,6 +116,15 @@ public class TelecomManager { public static final String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED"; + /** + * The {@link android.content.Intent} action used indicate that a phone account was + * just unregistered. + * @hide + */ + @SystemApi + public static final String ACTION_PHONE_ACCOUNT_UNREGISTERED = + "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"; + /** * Activity action: Shows a dialog asking the user whether or not they want to replace the * current default Dialer with the one specified in @@ -367,6 +376,48 @@ public class TelecomManager { public static final String EXTRA_TTY_PREFERRED_MODE = "android.telecom.intent.extra.TTY_PREFERRED"; + /** + * Broadcast intent action for letting custom component know to show the missed call + * notification. + * @hide + */ + @SystemApi + public static final String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = + "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION"; + + /** + * The number of calls associated with the notification. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_COUNT = + "android.telecom.extra.NOTIFICATION_COUNT"; + + /** + * The number associated with the missed calls. This number is only relevant + * when EXTRA_NOTIFICATION_COUNT is 1. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_PHONE_NUMBER = + "android.telecom.extra.NOTIFICATION_PHONE_NUMBER"; + + /** + * The intent to clear missed calls. + * @hide + */ + @SystemApi + public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = + "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT"; + + /** + * The intent to call back a missed call. + * @hide + */ + @SystemApi + public static final String EXTRA_CALL_BACK_INTENT = + "android.telecom.extra.CALL_BACK_INTENT"; + /** * The following 4 constants define how properties such as phone numbers and names are * displayed to the user. @@ -392,6 +443,25 @@ public class TelecomManager { */ public static final int PRESENTATION_PAYPHONE = 4; + /** + * The following 2 constants define how the incoming call should be handled by the Telecomm + * server when there is already an active call. + */ + + /** + * Indicates that Telecom server should end the current active call when another incoming + * call is detected + * @hide + */ + public static final int CALL_WAITING_RESPONSE_NO_POPUP_END_CALL = 1; + + /** + * Indicates that Telecom server should hold the current active call when another incoming + * call is detected + * @hide + */ + public static final int CALL_WAITING_RESPONSE_NO_POPUP_HOLD_CALL = 2; + private static final String TAG = "TelecomManager"; private final Context mContext; diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl index 23d70d59230d7..398d2e1e7dc98 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -50,8 +50,12 @@ oneway interface IConnectionService { void reject(String callId); + void rejectWithMessage(String callId, String message); + void disconnect(String callId); + void silence(String callId); + void hold(String callId); void unhold(String callId); @@ -75,4 +79,6 @@ oneway interface IConnectionService { void setLocalCallHold(String callId, boolean lchState); void addParticipantWithConference(String callId, String recipients); + + void explicitTransfer(String callId); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl index ee51efa691563..3104fb27a6ccb 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl @@ -62,4 +62,9 @@ oneway interface IInCallAdapter { void turnOffProximitySensor(boolean screenOnImmediately); void switchToOtherActiveSub(String subId); + + void transferCall(String callId); + + void answerCallWithCallWaitingResponse(String callId, int videoState, int + callWaitingResponseType); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 29e54a32a4801..bd6662dd1bfd1 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -421,12 +421,28 @@ public CarrierConfigManager() { */ public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool"; + /** + * Determine whether HD icon should displayed when audio codec is EVS. + * @hide + */ + public static final String KEY_IMS_SUPPORT_EVS_HD_ICON_BOOL = + "carrier_ims_support_evs_hd_icon_bool"; + /** * Determine whether preferred network type can be shown. * @hide */ public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool"; + /** + * Determine whether user can switch Wi-Fi preferred or Cellular preferred in calling preference. + * Some operators support Wi-Fi Calling only, not VoLTE. + * They don't need "Cellular preferred" option. + * In this case, set uneditalbe attribute for preferred preference. + * @hide + */ + public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool"; + /** * Specifies the amount of gap to be added in millis between postdial DTMF tones. When a * non-zero value is specified, the UE shall wait for the specified amount of time before it @@ -449,6 +465,13 @@ public CarrierConfigManager() { */ public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; + /** + * Boolean indicating if intent for emergency call state changes should be broadcast + * @hide + */ + public static final String KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL = + "broadcast_emergency_call_state_changes_bool"; + // These variables are used by the MMS service and exposed through another API, {@link // SmsManager}. The variable names and string values are copied from there. public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled"; @@ -527,7 +550,7 @@ public CarrierConfigManager() { sDefaults.putBoolean(KEY_SHOW_CDMA_CHOICES_BOOL, false); sDefaults.putBoolean(KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL, true); sDefaults.putBoolean(KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL, true); - sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, true); + sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, false); sDefaults.putBoolean(KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL, true); sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false); sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false); @@ -547,6 +570,7 @@ public CarrierConfigManager() { sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, ""); sDefaults.putBoolean(KEY_CSP_ENABLED_BOOL, false); sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true); + sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false); sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false); sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null); @@ -559,7 +583,9 @@ public CarrierConfigManager() { sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true); sDefaults.putBoolean(KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true); sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false); + sDefaults.putBoolean(KEY_IMS_SUPPORT_EVS_HD_ICON_BOOL, false); sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false); + sDefaults.putBoolean(KEY_EDITABLE_WFC_MODE_BOOL, true); sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100); // MMS defaults @@ -612,12 +638,15 @@ public CarrierConfigManager() { @Nullable public PersistableBundle getConfigForSubId(int subId) { try { - return getICarrierConfigLoader().getConfigForSubId(subId); + ICarrierConfigLoader loader = getICarrierConfigLoader(); + if (loader == null) { + Rlog.w(TAG, "Error getting config for subId " + subId + + " ICarrierConfigLoader is null"); + return null; + } + return loader.getConfigForSubId(subId); } catch (RemoteException ex) { - Rlog.e(TAG, "Error getting config for subId " + Integer.toString(subId) + ": " - + ex.toString()); - } catch (NullPointerException ex) { - Rlog.e(TAG, "Error getting config for subId " + Integer.toString(subId) + ": " + Rlog.e(TAG, "Error getting config for subId " + subId + ": " + ex.toString()); } return null; @@ -653,11 +682,15 @@ public PersistableBundle getConfig() { */ public void notifyConfigChangedForSubId(int subId) { try { - getICarrierConfigLoader().notifyConfigChangedForSubId(subId); + ICarrierConfigLoader loader = getICarrierConfigLoader(); + if (loader == null) { + Rlog.w(TAG, "Error reloading config for subId=" + subId + + " ICarrierConfigLoader is null"); + return; + } + loader.notifyConfigChangedForSubId(subId); } catch (RemoteException ex) { Rlog.e(TAG, "Error reloading config for subId=" + subId + ": " + ex.toString()); - } catch (NullPointerException ex) { - Rlog.e(TAG, "Error reloading config for subId=" + subId + ": " + ex.toString()); } } @@ -673,11 +706,15 @@ public void notifyConfigChangedForSubId(int subId) { @SystemApi public void updateConfigForPhoneId(int phoneId, String simState) { try { - getICarrierConfigLoader().updateConfigForPhoneId(phoneId, simState); + ICarrierConfigLoader loader = getICarrierConfigLoader(); + if (loader == null) { + Rlog.w(TAG, "Error updating config for phoneId=" + phoneId + + " ICarrierConfigLoader is null"); + return; + } + loader.updateConfigForPhoneId(phoneId, simState); } catch (RemoteException ex) { Rlog.e(TAG, "Error updating config for phoneId=" + phoneId + ": " + ex.toString()); - } catch (NullPointerException ex) { - Rlog.e(TAG, "Error updating config for phoneId=" + phoneId + ": " + ex.toString()); } } @@ -693,6 +730,7 @@ public static PersistableBundle getDefaultConfig() { } /** @hide */ + @Nullable private ICarrierConfigLoader getICarrierConfigLoader() { return ICarrierConfigLoader.Stub .asInterface(ServiceManager.getService(Context.CARRIER_CONFIG_SERVICE)); diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index cb68b6b0b30bc..1821f30ef206f 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -241,6 +241,8 @@ public class DisconnectCause { /** EMERGENCY call failed with permanent fail cause */ public static final int EMERGENCY_PERM_FAILURE = 97; + public static final int NON_SELECTED_USER_CLEARING = 98; + /** * Call was rejected due to number being blacklisted by user. * {@@hide} @@ -255,7 +257,7 @@ public class DisconnectCause { // 4) Update toString() with the newly added disconnect type. // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. // - // NextId: 98 + // NextId: 99 //********************************************************************************************* /** Smallest valid value for call disconnect codes. */ @@ -370,6 +372,8 @@ public static String toString(int cause) { return "IMS_MERGED_SUCCESSFULLY"; case CDMA_ALREADY_ACTIVATED: return "CDMA_ALREADY_ACTIVATED"; + case NON_SELECTED_USER_CLEARING: + return "NON_SELECTED_USER_CLEARING"; case HO_NOT_FEASIBLE: return "HO_NOT_FEASIBLE"; case NO_CIRCUIT_AVAIL: diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 5ee1fb2e6a5da..a70233f233782 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1935,11 +1935,13 @@ private static boolean isEmergencyNumberInternal(int subId, String number, // It is not possible to append additional digits to an emergency number to dial // the number in Brazil - it won't connect. if (useExactMatch || "BR".equalsIgnoreCase(defaultCountryIso)) { - if (number.equals(emergencyNum)) { + if (number.equals(emergencyNum) && + isEmergencyNumberForCurrentIso(number, defaultCountryIso, slotId)) { return true; } } else { - if (number.startsWith(emergencyNum)) { + if (number.startsWith(emergencyNum) && + isEmergencyNumberForCurrentIso(number, defaultCountryIso, slotId)) { return true; } } @@ -1981,6 +1983,57 @@ private static boolean isEmergencyNumberInternal(int subId, String number, return false; } + /** + * When checking for ECC numbers the country (defaultCountryIso) passed in is not taken into + * consideration by the function isEmergencyNumberInternal(subId, number, defaultCountryIso, + * useExactMatchecclist) this causes the function to return TRUE even in the case when the + * number is not emergency for defaultCountryIso. + */ + private static boolean isEmergencyNumberForCurrentIso(String number, + String country, + int slotId) { + Rlog.w(LOG_TAG, "isEmergencyNumberForCurrentIso: number =" + number + " iso=" + country); + + String mccEccIso = ""; + String mccEccIsoProp = (slotId == 0) ? "ril.mcc.ecc.iso" : ("ril.mcc.ecc.iso" + slotId); + mccEccIso = SystemProperties.get(mccEccIsoProp, ""); + + if (TextUtils.isEmpty(mccEccIso) || TextUtils.isEmpty(country) || slotId < 0 || + isEmergencyIsoMatchCountryIso(mccEccIso, country)) { + Rlog.w(LOG_TAG, "MCC/ISO is empty or matches region for ECC#'s set via RIL db"); + return true; + } + + String mccEccList = ""; + String mccEccListProp = (slotId == 0) ? "ril.mcc.ecclist" : ("ril.mcc.ecclist" + slotId); + mccEccList = SystemProperties.get(mccEccListProp, ""); + + if (!TextUtils.isEmpty(mccEccList)) { + for (String emergencyNum : mccEccList.split(",")) { + if (number.equals(emergencyNum)) { + Rlog.w(LOG_TAG, "Number " + number + " matches with " + mccEccListProp); + return false; + } + } + } + + return true; + } + + /** + * Checks if the two strings passed are equal ignoring the case + */ + private static boolean isEmergencyIsoMatchCountryIso(String iso, String country) { + Rlog.w(LOG_TAG, "isEmergencyIsoMatchCountryIso: iso=" + iso + " country=" + country); + + if(iso.equalsIgnoreCase(country)) { + return true; + } else { + return false; + } + + } + /** * Checks if a given number is an emergency number for the country that the user is in. * diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 1578b438eab9e..3b375e218cb8e 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -343,6 +343,14 @@ public class SubscriptionManager { */ public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts"; + + + /** + * TelephonyProvider column name for enable channel60 alert in CB settings + *@hide + */ + public static final String CB_CHANNEL_60_ALERT = "enable_channel_60_alerts"; + /** * TelephonyProvider column name for CMAS test alert in CB settings *@hide @@ -1389,7 +1397,7 @@ public static Resources getResourcesForSubId(Context context, int subId) { newConfig.setTo(config); if (subInfo != null) { newConfig.mcc = subInfo.getMcc(); - newConfig.mnc = subInfo.getMnc(); + newConfig.mnc = subInfo.getMnc() == 0 ? Configuration.MNC_ZERO : subInfo.getMnc(); } DisplayMetrics metrics = context.getResources().getDisplayMetrics(); DisplayMetrics newMetrics = new DisplayMetrics(); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 0c52783f3bf0d..5ec6950d79930 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -608,6 +608,46 @@ public boolean isMultiSimEnabled() { */ public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY; + /** + * Broadcast intent action for letting custom component know to show voicemail notification. + * @hide + */ + @SystemApi + public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = + "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION"; + + /** + * The number of voice messages associated with the notification. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_COUNT = + "android.telephony.extra.NOTIFICATION_COUNT"; + + /** + * The voicemail number. + * @hide + */ + @SystemApi + public static final String EXTRA_VOICEMAIL_NUMBER = + "android.telephony.extra.VOICEMAIL_NUMBER"; + + /** + * The intent to call voicemail. + * @hide + */ + @SystemApi + public static final String EXTRA_CALL_VOICEMAIL_INTENT = + "android.telephony.extra.CALL_VOICEMAIL_INTENT"; + + /** + * The intent to launch voicemail settings. + * @hide + */ + @SystemApi + public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = + "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT"; + /** * Response codes for sim activation. Activation completed successfully. * @hide @@ -739,7 +779,7 @@ public String getDeviceId(int slotId) { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) return null; - return info.getDeviceIdForPhone(slotId); + return info.getDeviceIdForPhone(slotId, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { @@ -3028,6 +3068,50 @@ public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) { return null; } + /** + * Opens a logical channel to the ICC card + * + * Input parameters equivalent to TS 27.007 AT+CCHO command. + * + * @param AID application id. See ETSI 102.221 and 101.220. + * @param p2 byte P2 parameter + * @return an IccOpenLogicalChannelResponse object + * @hide + */ + public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, byte p2) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.iccOpenLogicalChannelWithP2(AID, p2); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + } + return null; + } + + /** + * Opens a logical channel to the ICC card for the given subId + * + * @param subId subid to send the command to + * @param AID applcation id. See ETSI 102.221 and 101.220. + * @param p2 byte P2 parameter + * @return an IccOpenLogicalChannelResponse object + * @hide + */ + public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, + String AID, byte p2) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.iccOpenLogicalChannelUsingSubIdWithP2(subId, AID, p2); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + } + return null; + } + /** * Closes a previously opened logical channel to the ICC card. * diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.java b/telephony/java/com/android/ims/ImsCallForwardInfo.java index 3f8fd19a16cec..97dcbd509d83e 100644 --- a/telephony/java/com/android/ims/ImsCallForwardInfo.java +++ b/telephony/java/com/android/ims/ImsCallForwardInfo.java @@ -31,6 +31,8 @@ public class ImsCallForwardInfo implements Parcelable { public int mStatus; // 0x91: International, 0x81: Unknown public int mToA; + // Service class + public int mServiceClass; // Number (it will not include the "sip" or "tel" URI scheme) public String mNumber; // No reply timer for CF @@ -53,6 +55,7 @@ public void writeToParcel(Parcel out, int flags) { out.writeInt(mCondition); out.writeInt(mStatus); out.writeInt(mToA); + out.writeInt(mServiceClass); out.writeString(mNumber); out.writeInt(mTimeSeconds); } @@ -62,6 +65,7 @@ public String toString() { return super.toString() + ", Condition: " + mCondition + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled") + ", ToA: " + mToA + ", Number=" + mNumber + + ", Service Class: " + mServiceClass + ", Time (seconds): " + mTimeSeconds; } @@ -69,6 +73,7 @@ private void readFromParcel(Parcel in) { mCondition = in.readInt(); mStatus = in.readInt(); mToA = in.readInt(); + mServiceClass = in.readInt(); mNumber = in.readString(); mTimeSeconds = in.readInt(); } diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java index 3ab415c12e445..85ec16298da4e 100644 --- a/telephony/java/com/android/ims/ImsReasonInfo.java +++ b/telephony/java/com/android/ims/ImsReasonInfo.java @@ -250,6 +250,14 @@ public class ImsReasonInfo implements Parcelable { */ public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; + /** + * Supplementary services (HOLD/RESUME) failure error codes. + * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision. + */ + public static final int CODE_SUPP_SVC_FAILED = 1201; + public static final int CODE_SUPP_SVC_CANCELLED = 1202; + public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; + /** * Network string error messages. * mExtraMessage may have these values. diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl index 4ab5ee3c4f8c7..278465353a1ff 100644 --- a/telephony/java/com/android/ims/internal/IImsUt.aidl +++ b/telephony/java/com/android/ims/internal/IImsUt.aidl @@ -111,4 +111,9 @@ interface IImsUt { * Sets the listener. */ void setListener(in IImsUtListener listener); + + /** + * Retrieves the configuration of the call forward for specified service class. + */ + int queryCFForServiceClass(int condition, String number, int serviceClass); } diff --git a/telephony/java/com/android/internal/telephony/IExtTelephony.aidl b/telephony/java/com/android/internal/telephony/IExtTelephony.aidl index 063308d42de9c..7040f8079f682 100644 --- a/telephony/java/com/android/internal/telephony/IExtTelephony.aidl +++ b/telephony/java/com/android/internal/telephony/IExtTelephony.aidl @@ -116,4 +116,56 @@ interface IExtTelephony { * @return phone id */ int getPhoneIdForECall(); + + /** + * Check is FDN is enabled or not. + * @param - void + * @return true or false + */ + boolean isFdnEnabled(); + + /** + * Get application count from card. + * @param - slotId user preferred slotId + * @return application count + */ + int getUiccApplicationCount(int slotId); + + /** + * Get application type by index. + * @param - slotId user preferred slotId + * - appIndex application index + * @return application type as Integer, below are + * supported return values: + * '0' - APPTYPE_UNKNOWN + * '1' - APPTYPE_SIM + * '2' - APPTYPE_USIM + * '3 - APPTYPE_RUIM + * '4' - APPTYPE_CSIM + * '5' - APPTYPE_ISIM + */ + int getUiccApplicationType(int slotId, int appIndex); + + /** + * Get application state by index. + * @param - slotId user preferred slotId + * - appIndex application index + * @return application state as Integer, below are + * supported return values: + * '0' - APPSTATE_UNKNOWN + * '1' - APPSTATE_DETECTED + * '2' - APPSTATE_PIN + * '3 - APPSTATE_PUK + * '4' - APPSTATE_SUBSCRIPTION_PERSO + * '5' - APPSTATE_READY + */ + int getUiccApplicationState(int slotId, int appIndex); + + /** + * Get primary stack phone id. + * @param - void + * @return phone id + */ + int getPrimaryStackPhoneId(); + } diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index ed85392dd4d75..dc2b297f6dbe5 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -36,7 +36,7 @@ interface IPhoneSubInfo { * Retrieves the unique device ID of a phone for the device, e.g., IMEI * for GSM phones. */ - String getDeviceIdForPhone(int phoneId); + String getDeviceIdForPhone(int phoneId, String callingPackage); /** * Retrieves the IMEI. diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index 13777348a0940..c7e13aa2ee37a 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -467,12 +467,17 @@ interface ISms { */ String getImsSmsFormatForSubscriber(int subId); - /* + /** * Get SMS prompt property, enabled or not * @return true if enabled, false otherwise */ boolean isSMSPromptEnabled(); + /** + * Set SMS prompt property, enabled or not + */ + void setSMSPromptEnabled(boolean bool); + /** * Send a system stored text message. * diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index c3db8c26d114b..291ce275d4a85 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -570,6 +570,16 @@ interface ITelephony { */ IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID); + /** + * Opens a logical channel to the ICC card. + * + * Input parameters equivalent to TS 27.007 AT+CCHO command. + * + * @param p2 P2 parameter + * @param AID Application id. + * @return an IccOpenLogicalChannelResponse object. + */ + IccOpenLogicalChannelResponse iccOpenLogicalChannelWithP2(String AID, byte p2); /** * Opens a logical channel to the ICC card for a particular subId. @@ -582,6 +592,16 @@ interface ITelephony { */ IccOpenLogicalChannelResponse iccOpenLogicalChannelUsingSubId(int subId, String AID); + /** + * Opens a logical channel to the ICC card for a particular subID + * + * @param subId user preferred subId. + * @param p2 P2 parameter + * @param AID Application id. See ETSI 102.221 and 101.220 + */ + IccOpenLogicalChannelResponse iccOpenLogicalChannelUsingSubIdWithP2(int subId, + String AID, byte p2); + /** * Closes a previously opened logical channel to the ICC card. * diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 76b69cea8ae6b..ecb7dfe2abf8d 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -61,6 +61,8 @@ interface ITelephonyRegistry { void notifyCellInfo(in List cellInfo); void notifyPreciseCallState(int ringingCallState, int foregroundCallState, int backgroundCallState); + void notifyPreciseCallStateForSubscriber(int subId, int ringingCallState, + int foregroundCallState, int backgroundCallState); void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause); void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn, String failCause); diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index 5fd7d5e6bc041..ca3c8a8c9fc48 100755 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -35,17 +35,17 @@ public enum State { IDLE, RINGING, OFFHOOK; }; - /** - * The state of a data connection. - *

      - *
    • CONNECTED = IP traffic should be available
    • - *
    • CONNECTING = Currently setting up data connection
    • - *
    • DISCONNECTED = IP not available
    • - *
    • SUSPENDED = connection is created but IP traffic is - * temperately not available. i.e. voice call is in place - * in 2G network
    • - *
    - */ + /** + * The state of a data connection. + *
      + *
    • CONNECTED = IP traffic should be available
    • + *
    • CONNECTING = Currently setting up data connection
    • + *
    • DISCONNECTED = IP not available
    • + *
    • SUSPENDED = connection is created but IP traffic is + * temperately not available. i.e. voice call is in place + * in 2G network
    • + *
    + */ public enum DataState { CONNECTED, CONNECTING, DISCONNECTED, SUSPENDED; }; @@ -86,6 +86,7 @@ public enum DataState { public static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable"; public static final String DATA_NETWORK_ROAMING_KEY = "networkRoaming"; public static final String PHONE_IN_ECM_STATE = "phoneinECMState"; + public static final String PHONE_IN_EMERGENCY_CALL = "phoneInEmergencyCall"; public static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged"; @@ -199,4 +200,7 @@ public enum CardUnavailableReason { public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0; public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1; public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER; + + /** Copied from ContactsCommon. See comments in ContactsCommon app for more detail. */ + public static final String EXTRA_CALL_ORIGIN = "com.android.phone.CALL_ORIGIN"; } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index af79ff8ba8a5c..216dd38b8901a 100755 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -335,6 +335,8 @@ class C */ int RIL_REQUEST_PULL_LCEDATA = 134; int RIL_REQUEST_GET_ACTIVITY_INFO = 135; int RIL_REQUEST_SIM_GET_ATR = 136; + int RIL_REQUEST_CAF_SIM_OPEN_CHANNEL_WITH_P2 = 137; + int RIL_REQUEST_SET_MAX_TRANSMIT_POWER = 139; int RIL_UNSOL_RESPONSE_BASE = 1000; int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000; diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index f563839e2c937..77b8a6785c84d 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -75,6 +75,7 @@ public class TelephonyIntents { */ public static final String ACTION_RADIO_TECHNOLOGY_CHANGED = "android.intent.action.RADIO_TECHNOLOGY"; + /** *

    Broadcast Action: The emergency callback mode is changed. *

      @@ -94,6 +95,28 @@ public class TelephonyIntents { */ public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED"; + + /** + *

      Broadcast Action: The emergency call state is changed. + *

        + *
      • phoneInEmergencyCall - A boolean value, true if phone in emergency call, + * false otherwise
      • + *
      + *

      + * You can not receive this through components declared + * in manifests, only by explicitly registering for it with + * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver, + * android.content.IntentFilter) Context.registerReceiver()}. + * + *

      + * Requires no permission. + * + *

      This is a protected intent that can only be sent + * by the system. + */ + public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED + = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED"; + /** * Broadcast Action: The phone's signal strength has changed. The intent will have the * following extra values:

      diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 7aacb2345768c..bd0a89a94bd7b 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -891,6 +891,7 @@ public VerifierDeviceIdentity getVerifierDeviceIdentity() { public boolean isUpgrade() { throw new UnsupportedOperationException(); } + /** * @hide */ @@ -899,6 +900,15 @@ public void setComponentProtectedSetting(ComponentName componentName, boolean ne throw new UnsupportedOperationException(); } + /** + * @hide + */ + @Override + public boolean isComponentProtected(String callingPackage, int callingUid, + ComponentName componentName) { + throw new UnsupportedOperationException(); + } + /** * @hide */ diff --git a/tests/UiBench/.gitignore b/tests/UiBench/.gitignore new file mode 100644 index 0000000000000..c39eac2a6309b --- /dev/null +++ b/tests/UiBench/.gitignore @@ -0,0 +1,5 @@ +.gradle +.idea +*.iml +build +local.properties diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk new file mode 100644 index 0000000000000..0e678cde9c70e --- /dev/null +++ b/tests/UiBench/Android.mk @@ -0,0 +1,31 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +# omit gradle 'build' dir +LOCAL_SRC_FILES := $(call all-java-files-under,src) + +# use appcompat/support lib from the tree, so improvements/ +# regressions are reflected in test data +LOCAL_RESOURCE_DIR := \ + $(LOCAL_PATH)/res \ + frameworks/support/v7/appcompat/res \ + frameworks/support/v7/cardview/res \ + frameworks/support/v7/recyclerview/res + +LOCAL_AAPT_FLAGS := \ + --auto-add-overlay \ + --extra-packages android.support.v7.appcompat \ + --extra-packages android.support.v7.cardview \ + --extra-packages android.support.v7.recyclerview + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-v4 \ + android-support-v7-appcompat \ + android-support-v7-cardview \ + android-support-v7-recyclerview + +LOCAL_PACKAGE_NAME := UiBench + +include $(BUILD_PACKAGE) diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml new file mode 100644 index 0000000000000..7b4f01cad8495 --- /dev/null +++ b/tests/UiBench/AndroidManifest.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/UiBench/build.gradle b/tests/UiBench/build.gradle new file mode 100644 index 0000000000000..0756a8aac8789 --- /dev/null +++ b/tests/UiBench/build.gradle @@ -0,0 +1,39 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.3.0' + + } +} + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 23 + buildToolsVersion "22.0.0" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } + } +} + +dependencies { + // Dependencies enumerated specifically for platform-independent / reproducible builds. + compile 'com.android.support:support-v4:23.0.1' + compile 'com.android.support:appcompat-v7:23.0.1' + compile 'com.android.support:cardview-v7:23.0.1' + compile 'com.android.support:recyclerview-v7:23.0.1' +} diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.jar b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000..8c0fb64a8698b Binary files /dev/null and b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.properties b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000..12582f8e993ed --- /dev/null +++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Aug 26 10:51:13 PDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip diff --git a/tests/UiBench/res/drawable-nodpi/ball.jpg b/tests/UiBench/res/drawable-nodpi/ball.jpg new file mode 100644 index 0000000000000..2960b7309f6e1 Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/ball.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/block.jpg b/tests/UiBench/res/drawable-nodpi/block.jpg new file mode 100644 index 0000000000000..04c22a0cf5b47 Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/block.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/ducky.jpg b/tests/UiBench/res/drawable-nodpi/ducky.jpg new file mode 100644 index 0000000000000..830bbe347e47f Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/ducky.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/frantic.jpg b/tests/UiBench/res/drawable-nodpi/frantic.jpg new file mode 100644 index 0000000000000..4c623336e15b4 Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/frantic.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/jellies.jpg b/tests/UiBench/res/drawable-nodpi/jellies.jpg new file mode 100644 index 0000000000000..ee2b5c68c43be Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/jellies.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/large_photo.jpg b/tests/UiBench/res/drawable-nodpi/large_photo.jpg new file mode 100644 index 0000000000000..e23dbb093f39d Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/large_photo.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/mug.jpg b/tests/UiBench/res/drawable-nodpi/mug.jpg new file mode 100644 index 0000000000000..e149e198a9cd7 Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/mug.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/pencil.jpg b/tests/UiBench/res/drawable-nodpi/pencil.jpg new file mode 100644 index 0000000000000..e348311bf4d08 Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/pencil.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/scissors.jpg b/tests/UiBench/res/drawable-nodpi/scissors.jpg new file mode 100644 index 0000000000000..caf0ce8e2f4b0 Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/scissors.jpg differ diff --git a/tests/UiBench/res/drawable-nodpi/woot.jpg b/tests/UiBench/res/drawable-nodpi/woot.jpg new file mode 100644 index 0000000000000..ccaef674b1a5d Binary files /dev/null and b/tests/UiBench/res/drawable-nodpi/woot.jpg differ diff --git a/tests/UiBench/res/layout/activity_bitmap_upload.xml b/tests/UiBench/res/layout/activity_bitmap_upload.xml new file mode 100644 index 0000000000000..70faa07a6d753 --- /dev/null +++ b/tests/UiBench/res/layout/activity_bitmap_upload.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/UiBench/res/layout/activity_invalidate.xml b/tests/UiBench/res/layout/activity_invalidate.xml new file mode 100644 index 0000000000000..34bcca95f79f4 --- /dev/null +++ b/tests/UiBench/res/layout/activity_invalidate.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/UiBench/res/layout/activity_transition.xml b/tests/UiBench/res/layout/activity_transition.xml new file mode 100644 index 0000000000000..d4c661027a353 --- /dev/null +++ b/tests/UiBench/res/layout/activity_transition.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/UiBench/res/layout/activity_transition_details.xml b/tests/UiBench/res/layout/activity_transition_details.xml new file mode 100644 index 0000000000000..1022d2fc2a40d --- /dev/null +++ b/tests/UiBench/res/layout/activity_transition_details.xml @@ -0,0 +1,39 @@ + + + + + + + \ No newline at end of file diff --git a/tests/UiBench/res/layout/card_row.xml b/tests/UiBench/res/layout/card_row.xml new file mode 100644 index 0000000000000..215f9df9b7fdd --- /dev/null +++ b/tests/UiBench/res/layout/card_row.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/UiBench/res/layout/invalidate_row.xml b/tests/UiBench/res/layout/invalidate_row.xml new file mode 100644 index 0000000000000..9feefde0bbfa5 --- /dev/null +++ b/tests/UiBench/res/layout/invalidate_row.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/UiBench/res/layout/recycler_view.xml b/tests/UiBench/res/layout/recycler_view.xml new file mode 100644 index 0000000000000..54c5b5845ae20 --- /dev/null +++ b/tests/UiBench/res/layout/recycler_view.xml @@ -0,0 +1,21 @@ + + + diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java new file mode 100644 index 0000000000000..1106a13bfc2ad --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.app.ActivityOptions; +import android.app.SharedElementCallback; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ImageView; + +import java.util.List; +import java.util.Map; + +public class ActivityTransition extends AppCompatActivity { + private static final String KEY_ID = "ViewTransitionValues:id"; + + private ImageView mHero; + + public static final int[] DRAWABLES = { + R.drawable.ball, + R.drawable.block, + R.drawable.ducky, + R.drawable.jellies, + R.drawable.mug, + R.drawable.pencil, + R.drawable.scissors, + R.drawable.woot, + }; + + public static final int[] IDS = { + R.id.ball, + R.id.block, + R.id.ducky, + R.id.jellies, + R.id.mug, + R.id.pencil, + R.id.scissors, + R.id.woot, + }; + + public static final String[] NAMES = { + "ball", + "block", + "ducky", + "jellies", + "mug", + "pencil", + "scissors", + "woot", + }; + + public static int getIdForKey(String id) { + return IDS[getIndexForKey(id)]; + } + + public static int getDrawableIdForKey(String id) { + return DRAWABLES[getIndexForKey(id)]; + } + + public static int getIndexForKey(String id) { + for (int i = 0; i < NAMES.length; i++) { + String name = NAMES[i]; + if (name.equals(id)) { + return i; + } + } + return 2; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK)); + setContentView(R.layout.activity_transition); + setupHero(); + } + + private void setupHero() { + String name = getIntent().getStringExtra(KEY_ID); + mHero = null; + if (name != null) { + mHero = (ImageView) findViewById(getIdForKey(name)); + setEnterSharedElementCallback(new SharedElementCallback() { + @Override + public void onMapSharedElements(List names, + Map sharedElements) { + sharedElements.put("hero", mHero); + } + }); + } + } + + public void clicked(View v) { + mHero = (ImageView) v; + Intent intent = new Intent(this, ActivityTransitionDetails.class); + intent.putExtra(KEY_ID, v.getTransitionName()); + ActivityOptions activityOptions + = ActivityOptions.makeSceneTransitionAnimation(this, mHero, "hero"); + startActivity(intent, activityOptions.toBundle()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java new file mode 100644 index 0000000000000..a654c61071340 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.app.ActivityOptions; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ImageView; + +import com.android.test.uibench.ActivityTransition; +import com.android.test.uibench.R; + + +public class ActivityTransitionDetails extends AppCompatActivity { + private static final String KEY_ID = "ViewTransitionValues:id"; + private int mImageResourceId = R.drawable.ducky; + private String mName = "ducky"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable(Color.DKGRAY)); + setContentView(R.layout.activity_transition_details); + ImageView titleImage = (ImageView) findViewById(R.id.titleImage); + titleImage.setImageDrawable(getHeroDrawable()); + } + + private Drawable getHeroDrawable() { + String name = getIntent().getStringExtra(KEY_ID); + if (name != null) { + mName = name; + mImageResourceId = ActivityTransition.getDrawableIdForKey(name); + } + + return getResources().getDrawable(mImageResourceId); + } + + public void clicked(View v) { + Intent intent = new Intent(this, ActivityTransition.class); + intent.putExtra(KEY_ID, mName); + ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation( + this, v, "hero"); + startActivity(intent, activityOptions.toBundle()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java new file mode 100644 index 0000000000000..e2bf8976a3157 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.View; + +public class BitmapUploadActivity extends AppCompatActivity { + public static class UploadView extends View { + private int mColorValue; + private Bitmap mBitmap; + private final DisplayMetrics mMetrics = new DisplayMetrics(); + private final Rect mRect = new Rect(); + + public UploadView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @SuppressWarnings("unused") + public void setColorValue(int colorValue) { + if (colorValue == mColorValue) return; + + mColorValue = colorValue; + + // modify the bitmap's color to ensure it's uploaded to the GPU + mBitmap.eraseColor(Color.rgb(mColorValue, 255 - mColorValue, 255)); + + invalidate(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + getDisplay().getMetrics(mMetrics); + int minDisplayDimen = Math.min(mMetrics.widthPixels, mMetrics.heightPixels); + int bitmapSize = Math.min((int) (minDisplayDimen * 0.75), 720); + if (mBitmap == null + || mBitmap.getWidth() != bitmapSize + || mBitmap.getHeight() != bitmapSize) { + mBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mBitmap != null) { + mRect.set(0, 0, getWidth(), getHeight()); + canvas.drawBitmap(mBitmap, null, mRect, null); + } + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_bitmap_upload); + + // animate color to force bitmap uploads + UploadView uploadView = (UploadView) findViewById(R.id.upload_view); + ObjectAnimator colorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255); + colorValueAnimator.setRepeatMode(ValueAnimator.REVERSE); + colorValueAnimator.setRepeatCount(ValueAnimator.INFINITE); + colorValueAnimator.start(); + + // animate scene root to guarantee there's a minimum amount of GPU rendering work + View uploadRoot = findViewById(R.id.upload_root); + ObjectAnimator yAnimator = ObjectAnimator.ofFloat(uploadRoot, "translationY", 0, 100); + yAnimator.setRepeatMode(ValueAnimator.REVERSE); + yAnimator.setRepeatCount(ValueAnimator.INFINITE); + yAnimator.start(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/DialogListActivity.java b/tests/UiBench/src/com/android/test/uibench/DialogListActivity.java new file mode 100644 index 0000000000000..fe712d5230bb6 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/DialogListActivity.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +public class DialogListActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ListView listView = new ListView(this); + listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildSimpleStringList())); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Dialog"); + builder.setView(listView); + builder.create().show(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java b/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java new file mode 100644 index 0000000000000..08ab5105a5e8d --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/EditTextTypeActivity.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.app.Instrumentation; +import android.os.Bundle; +import android.os.Looper; +import android.os.MessageQueue; +import android.support.v7.app.AppCompatActivity; +import android.view.KeyEvent; +import android.widget.EditText; + +import java.util.concurrent.Semaphore; + +/** + * Note: currently incomplete, complexity of input continuously grows, instead of looping + * over a stable amount of work. + * + * Simulates typing continuously into an EditText. + */ +public class EditTextTypeActivity extends AppCompatActivity { + Thread mThread; + + private static String sSeedText = ""; + static { + final int count = 100; + final String string = "hello "; + + StringBuilder builder = new StringBuilder(count * string.length()); + for (int i = 0; i < count; i++) { + builder.append(string); + } + sSeedText = builder.toString(); + } + + final Object mLock = new Object(); + boolean mShouldStop = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + EditText editText = new EditText(this); + editText.setText(sSeedText); + setContentView(editText); + + final Instrumentation instrumentation = new Instrumentation(); + final Semaphore sem = new Semaphore(0); + MessageQueue.IdleHandler handler = new MessageQueue.IdleHandler() { + @Override + public boolean queueIdle() { + // TODO: consider other signaling approaches + sem.release(); + return true; + } + }; + Looper.myQueue().addIdleHandler(handler); + synchronized (mLock) { + mShouldStop = false; + } + mThread = new Thread(new Runnable() { + int codes[] = { KeyEvent.KEYCODE_H, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_L, + KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_SPACE }; + int i = 0; + @Override + public void run() { + while (true) { + try { + sem.acquire(); + } catch (InterruptedException e) { + // TODO, maybe + } + int code = codes[i % codes.length]; + if (i % 100 == 99) code = KeyEvent.KEYCODE_ENTER; + + synchronized (mLock) { + if (mShouldStop) break; + } + + // TODO: bit of a race here, since the event can arrive after pause/stop. + // (Can't synchronize on key send, since it's synchronous.) + instrumentation.sendKeyDownUpSync(code); + i++; + } + } + }); + mThread.start(); + } + + @Override + protected void onPause() { + synchronized (mLock) { + mShouldStop = true; + } + super.onPause(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java new file mode 100644 index 0000000000000..f1ecc5624d577 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/FullscreenOverdrawActivity.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +/** + * Draws hundreds of levels of overdraw over the content area. + * + * This should all be optimized out by the renderer. + */ +public class FullscreenOverdrawActivity extends AppCompatActivity { + private class OverdrawView extends View { + Paint paint = new Paint(); + int mColorValue = 0; + + public OverdrawView(Context context) { + super(context); + } + + @SuppressWarnings("unused") + public void setColorValue(int colorValue) { + mColorValue = colorValue; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + paint.setColor(Color.rgb(mColorValue, 255 - mColorValue, 255)); + + for (int i = 0; i < 400; i++) { + canvas.drawRect(0, 0, getWidth(), getHeight(), paint); + } + } + } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + OverdrawView overdrawView = new OverdrawView(this); + setContentView(overdrawView); + + ObjectAnimator objectAnimator = ObjectAnimator.ofInt(overdrawView, "colorValue", 0, 255); + objectAnimator.setRepeatMode(ValueAnimator.REVERSE); + objectAnimator.setRepeatCount(ValueAnimator.INFINITE); + objectAnimator.start(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java new file mode 100644 index 0000000000000..a12742d83fe7d --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/GlTextureViewActivity.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.graphics.SurfaceTexture; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.Gravity; +import android.view.TextureView; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.android.test.uibench.opengl.ImageFlipRenderThread; + +public class GlTextureViewActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener { + private ImageFlipRenderThread mRenderThread; + private TextureView mTextureView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mTextureView = new TextureView(this); + mTextureView.setSurfaceTextureListener(this); + setContentView(mTextureView, new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, + Gravity.CENTER)); + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mRenderThread = new ImageFlipRenderThread(getResources(), surface); + mRenderThread.start(); + + mTextureView.setCameraDistance(5000); + + ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); + animator.setRepeatMode(ObjectAnimator.REVERSE); + animator.setRepeatCount(ObjectAnimator.INFINITE); + animator.setDuration(4000); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTextureView.invalidate(); + } + }); + animator.start(); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + mRenderThread.finish(); + try { + mRenderThread.join(); + } catch (InterruptedException e) { + Log.e(ImageFlipRenderThread.LOG_TAG, "Could not wait for render thread"); + } + return true; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + } + +} \ No newline at end of file diff --git a/tests/UiBench/src/com/android/test/uibench/InflatingListActivity.java b/tests/UiBench/src/com/android/test/uibench/InflatingListActivity.java new file mode 100644 index 0000000000000..603244eb2a435 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/InflatingListActivity.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class InflatingListActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter(this, + android.R.layout.simple_list_item_1, TextUtils.buildSimpleStringList()) { + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // pathological getView behavior: drop convertView on the floor to force inflation + return super.getView(position, null, parent); + } + }; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java new file mode 100644 index 0000000000000..93d67a60515f6 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/InvalidateActivity.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.ColorInt; +import android.support.v7.app.AppCompatActivity; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +/** + * Tests invalidation performance by invalidating a large number of easily rendered views, + */ +public class InvalidateActivity extends AppCompatActivity { + public static class ColorView extends View { + @ColorInt + public int mColor; + + public ColorView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setColor(@ColorInt int color) { + mColor = color; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.drawColor(mColor); + } + } + + ColorView[][] mColorViews; + + @SuppressWarnings("unused") + public void setColorValue(int colorValue) { + @ColorInt int a = Color.rgb(colorValue, 255 - colorValue, 255); + @ColorInt int b = Color.rgb(255, colorValue, 255 - colorValue); + for (int y = 0; y < mColorViews.length; y++) { + for (int x = 0; x < mColorViews[y].length; x++) { + mColorViews[y][x].setColor((x + y) % 2 == 0 ? a : b); + } + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_invalidate); + + ViewGroup root = (ViewGroup) findViewById(R.id.invalidate_root); + for (int y = 0; y < root.getChildCount(); y++) { + ViewGroup row = (ViewGroup) root.getChildAt(y); + if (mColorViews == null) { + mColorViews = new ColorView[root.getChildCount()][row.getChildCount()]; + } + + for (int x = 0; x < row.getChildCount(); x++) { + mColorViews[y][x] = (ColorView) row.getChildAt(x); + } + } + + ObjectAnimator animator = ObjectAnimator.ofInt(this, "colorValue", 0, 255); + animator.setRepeatMode(ValueAnimator.REVERSE); + animator.setRepeatCount(ValueAnimator.INFINITE); + animator.start(); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/MainActivity.java b/tests/UiBench/src/com/android/test/uibench/MainActivity.java new file mode 100644 index 0000000000000..2111274a93c0b --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/MainActivity.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.ListFragment; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ListView; +import android.widget.SimpleAdapter; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MainActivity extends AppCompatActivity { + private static final String EXTRA_PATH = "activity_path"; + private static final String CATEGORY_HWUI_TEST = "com.android.test.uibench.TEST"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + String path = intent.getStringExtra(EXTRA_PATH); + + if (path == null) { + path = ""; + } else { + // not root level, display where we are in the hierarchy + setTitle(path); + } + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + ListFragment listFragment = new ListFragment() { + @Override + @SuppressWarnings("unchecked") + public void onListItemClick(ListView l, View v, int position, long id) { + Map map = (Map)l.getItemAtPosition(position); + + Intent intent = (Intent) map.get("intent"); + startActivity(intent); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + getListView().setTextFilterEnabled(true); + } + }; + listFragment.setListAdapter(new SimpleAdapter(this, getData(path), + android.R.layout.simple_list_item_1, new String[] { "title" }, + new int[] { android.R.id.text1 })); + fm.beginTransaction().add(android.R.id.content, listFragment).commit(); + } + } + + protected List> getData(String prefix) { + List> myData = new ArrayList<>(); + + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(CATEGORY_HWUI_TEST); + + PackageManager pm = getPackageManager(); + List list = pm.queryIntentActivities(mainIntent, 0); + + if (null == list) + return myData; + + String[] prefixPath; + String prefixWithSlash = prefix; + + if (prefix.equals("")) { + prefixPath = null; + } else { + prefixPath = prefix.split("/"); + prefixWithSlash = prefix + "/"; + } + + int len = list.size(); + + Map entries = new HashMap<>(); + + for (int i = 0; i < len; i++) { + ResolveInfo info = list.get(i); + CharSequence labelSeq = info.loadLabel(pm); + String label = labelSeq != null + ? labelSeq.toString() + : info.activityInfo.name; + + if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) { + + String[] labelPath = label.split("/"); + + String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length]; + + if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) { + addItem(myData, nextLabel, activityIntent( + info.activityInfo.applicationInfo.packageName, + info.activityInfo.name)); + } else { + if (entries.get(nextLabel) == null) { + addItem(myData, nextLabel, browseIntent(prefix.equals("") ? + nextLabel : prefix + "/" + nextLabel)); + entries.put(nextLabel, true); + } + } + } + } + + Collections.sort(myData, sDisplayNameComparator); + + return myData; + } + + private final static Comparator> sDisplayNameComparator = + new Comparator>() { + private final Collator collator = Collator.getInstance(); + + public int compare(Map map1, Map map2) { + return collator.compare(map1.get("title"), map2.get("title")); + } + }; + + protected Intent activityIntent(String pkg, String componentName) { + Intent result = new Intent(); + result.setClassName(pkg, componentName); + return result; + } + + protected Intent browseIntent(String path) { + Intent result = new Intent(); + result.setClass(this, MainActivity.class); + result.putExtra(EXTRA_PATH, path); + return result; + } + + protected void addItem(List> data, String name, Intent intent) { + Map temp = new HashMap<>(); + temp.put("title", name); + temp.put("intent", intent); + data.add(temp); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java new file mode 100644 index 0000000000000..d32f0716fe989 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.ListFragment; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ArrayAdapter; + +public class ShadowGridActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + ListFragment listFragment = new ListFragment() { + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + getListView().setDivider(null); + } + }; + + listFragment.setListAdapter(new ArrayAdapter<>(this, + R.layout.card_row, R.id.card_text, TextUtils.buildSimpleStringList())); + fm.beginTransaction().add(android.R.id.content, listFragment).commit(); + } + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TextCacheHighHitrateActivity.java b/tests/UiBench/src/com/android/test/uibench/TextCacheHighHitrateActivity.java new file mode 100644 index 0000000000000..fc5be35be4a31 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TextCacheHighHitrateActivity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class TextCacheHighHitrateActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildParagraphListWithHitPercentage(80)); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TextCacheLowHitrateActivity.java b/tests/UiBench/src/com/android/test/uibench/TextCacheLowHitrateActivity.java new file mode 100644 index 0000000000000..14dc437d052bc --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TextCacheLowHitrateActivity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class TextCacheLowHitrateActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildParagraphListWithHitPercentage(20)); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TextUtils.java b/tests/UiBench/src/com/android/test/uibench/TextUtils.java new file mode 100644 index 0000000000000..d88ca1e1a8899 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TextUtils.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import java.util.Random; + +public class TextUtils { + private static final int STRING_COUNT = 200; + private static final int SIMPLE_STRING_LENGTH = 10; + + /** + * Create word of random assortment of lower/upper case letters + */ + private static String randomWord(Random random, int length) { + String result = ""; + for (int j = 0; j < length; j++) { + // add random letter + int base = random.nextInt(2) == 0 ? 'A' : 'a'; + result += (char)(random.nextInt(26) + base); + } + return result; + } + + public static String[] buildSimpleStringList() { + String[] strings = new String[STRING_COUNT]; + Random random = new Random(0); + for (int i = 0; i < strings.length; i++) { + strings[i] = randomWord(random, SIMPLE_STRING_LENGTH); + } + return strings; + } + + // a small number of strings reused frequently, expected to hit + // in the word-granularity text layout cache + static final String[] CACHE_HIT_STRINGS = new String[] { + "a", + "small", + "number", + "of", + "strings", + "reused", + "frequently" + }; + + private static final int WORDS_IN_PARAGRAPH = 150; + + // misses are fairly long 'words' to ensure they miss + private static final int PARAGRAPH_MISS_MIN_LENGTH = 4; + private static final int PARAGRAPH_MISS_MAX_LENGTH = 9; + + static String[] buildParagraphListWithHitPercentage(int hitPercentage) { + if (hitPercentage < 0 || hitPercentage > 100) throw new IllegalArgumentException(); + + String[] strings = new String[STRING_COUNT]; + Random random = new Random(0); + for (int i = 0; i < strings.length; i++) { + String result = ""; + for (int word = 0; word < WORDS_IN_PARAGRAPH; word++) { + if (word != 0) { + result += " "; + } + if (random.nextInt(100) < hitPercentage) { + // add a common word, which is very likely to hit in the cache + result += CACHE_HIT_STRINGS[random.nextInt(CACHE_HIT_STRINGS.length)]; + } else { + // construct a random word, which will *most likely* miss + int length = PARAGRAPH_MISS_MIN_LENGTH; + length += random.nextInt(PARAGRAPH_MISS_MAX_LENGTH - PARAGRAPH_MISS_MIN_LENGTH); + + result += randomWord(random, length); + } + } + strings[i] = result; + } + + return strings; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialAnimationActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialAnimationActivity.java new file mode 100644 index 0000000000000..6e984727836e7 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TrivialAnimationActivity.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +public class TrivialAnimationActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable() { + int colorValue = 0; + int colorDelta = 1; + + @Override + public void draw(Canvas canvas) { + colorValue += colorDelta; + if (colorValue == 255 || colorValue == 0) { + colorDelta *= -1; + } + + setColor(Color.rgb(255, colorValue, 255 - colorValue)); + invalidateSelf(); + super.draw(canvas); + } + }); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java new file mode 100644 index 0000000000000..2625a99f3c82c --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; + +import com.android.test.uibench.listview.CompatListActivity; + +public class TrivialListActivity extends CompatListActivity { + @Override + protected ListAdapter createListAdapter() { + return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, + TextUtils.buildSimpleStringList()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialRecyclerViewActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialRecyclerViewActivity.java new file mode 100644 index 0000000000000..4647ba774b2eb --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/TrivialRecyclerViewActivity.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench; + +import android.support.v7.widget.RecyclerView; + +import com.android.test.uibench.recyclerview.RvArrayAdapter; +import com.android.test.uibench.recyclerview.RvCompatListActivity; + +public class TrivialRecyclerViewActivity extends RvCompatListActivity { + @Override + protected RecyclerView.Adapter createAdapter() { + return new RvArrayAdapter(TextUtils.buildSimpleStringList()); + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java new file mode 100644 index 0000000000000..214c07463fd75 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench.listview; + +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.ListFragment; +import android.support.v7.app.AppCompatActivity; +import android.widget.ListAdapter; + +public abstract class CompatListActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + ListFragment listFragment = new ListFragment(); + listFragment.setListAdapter(createListAdapter()); + fm.beginTransaction().add(android.R.id.content, listFragment).commit(); + } + } + + protected abstract ListAdapter createListAdapter(); +} diff --git a/tests/UiBench/src/com/android/test/uibench/opengl/ImageFlipRenderThread.java b/tests/UiBench/src/com/android/test/uibench/opengl/ImageFlipRenderThread.java new file mode 100644 index 0000000000000..119ce52ad322e --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/opengl/ImageFlipRenderThread.java @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench.opengl; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.SurfaceTexture; +import android.opengl.GLUtils; +import android.util.Log; + +import com.android.test.uibench.R; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; + +import static android.opengl.GLES20.GL_CLAMP_TO_EDGE; +import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; +import static android.opengl.GLES20.GL_COMPILE_STATUS; +import static android.opengl.GLES20.GL_FLOAT; +import static android.opengl.GLES20.GL_FRAGMENT_SHADER; +import static android.opengl.GLES20.GL_LINEAR; +import static android.opengl.GLES20.GL_LINK_STATUS; +import static android.opengl.GLES20.GL_NO_ERROR; +import static android.opengl.GLES20.GL_RGBA; +import static android.opengl.GLES20.GL_TEXTURE0; +import static android.opengl.GLES20.GL_TEXTURE_2D; +import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER; +import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER; +import static android.opengl.GLES20.GL_TEXTURE_WRAP_S; +import static android.opengl.GLES20.GL_TEXTURE_WRAP_T; +import static android.opengl.GLES20.GL_TRIANGLE_STRIP; +import static android.opengl.GLES20.GL_TRUE; +import static android.opengl.GLES20.GL_UNSIGNED_BYTE; +import static android.opengl.GLES20.GL_VERTEX_SHADER; +import static android.opengl.GLES20.glActiveTexture; +import static android.opengl.GLES20.glAttachShader; +import static android.opengl.GLES20.glBindTexture; +import static android.opengl.GLES20.glClear; +import static android.opengl.GLES20.glClearColor; +import static android.opengl.GLES20.glCompileShader; +import static android.opengl.GLES20.glCreateProgram; +import static android.opengl.GLES20.glCreateShader; +import static android.opengl.GLES20.glDeleteProgram; +import static android.opengl.GLES20.glDeleteShader; +import static android.opengl.GLES20.glDrawArrays; +import static android.opengl.GLES20.glEnableVertexAttribArray; +import static android.opengl.GLES20.glGenTextures; +import static android.opengl.GLES20.glGetAttribLocation; +import static android.opengl.GLES20.glGetError; +import static android.opengl.GLES20.glGetProgramInfoLog; +import static android.opengl.GLES20.glGetProgramiv; +import static android.opengl.GLES20.glGetShaderInfoLog; +import static android.opengl.GLES20.glGetShaderiv; +import static android.opengl.GLES20.glGetUniformLocation; +import static android.opengl.GLES20.glLinkProgram; +import static android.opengl.GLES20.glShaderSource; +import static android.opengl.GLES20.glTexParameteri; +import static android.opengl.GLES20.glUniform1i; +import static android.opengl.GLES20.glUseProgram; +import static android.opengl.GLES20.glVertexAttribPointer; + +public class ImageFlipRenderThread extends Thread { + public static final String LOG_TAG = "GLTextureView"; + + static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + static final int EGL_OPENGL_ES2_BIT = 4; + + private volatile boolean mFinished; + + private final Resources mResources; + private final SurfaceTexture mSurface; + + private EGL10 mEgl; + private EGLDisplay mEglDisplay; + private EGLConfig mEglConfig; + private EGLContext mEglContext; + private EGLSurface mEglSurface; + + public ImageFlipRenderThread(Resources resources, SurfaceTexture surface) { + mResources = resources; + mSurface = surface; + } + + private static final String sSimpleVS = + "attribute vec4 position;\n" + + "attribute vec2 texCoords;\n" + + "varying vec2 outTexCoords;\n" + + "\nvoid main(void) {\n" + + " outTexCoords = texCoords;\n" + + " gl_Position = position;\n" + + "}\n\n"; + private static final String sSimpleFS = + "precision mediump float;\n\n" + + "varying vec2 outTexCoords;\n" + + "uniform sampler2D texture;\n" + + "\nvoid main(void) {\n" + + " gl_FragColor = texture2D(texture, outTexCoords);\n" + + "}\n\n"; + + private static final int FLOAT_SIZE_BYTES = 4; + private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; + private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; + private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; + private final float[] mTriangleVerticesData = { + // X, Y, Z, U, V + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + }; + + @Override + public void run() { + initGL(); + + FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length + * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); + triangleVertices.put(mTriangleVerticesData).position(0); + + int texture = loadTexture(R.drawable.large_photo); + int program = buildProgram(sSimpleVS, sSimpleFS); + + int attribPosition = glGetAttribLocation(program, "position"); + checkGlError(); + + int attribTexCoords = glGetAttribLocation(program, "texCoords"); + checkGlError(); + + int uniformTexture = glGetUniformLocation(program, "texture"); + checkGlError(); + + glBindTexture(GL_TEXTURE_2D, texture); + checkGlError(); + + glUseProgram(program); + checkGlError(); + + glEnableVertexAttribArray(attribPosition); + checkGlError(); + + glEnableVertexAttribArray(attribTexCoords); + checkGlError(); + + glUniform1i(uniformTexture, 0); + checkGlError(); + + // drawQuad + triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); + glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false, + TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); + checkGlError(); + + triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); + glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false, + TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); + checkGlError(); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + checkGlError(); + + while (!mFinished) { + checkCurrent(); + + glClear(GL_COLOR_BUFFER_BIT); + checkGlError(); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + checkGlError(); + + if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { + throw new RuntimeException("Cannot swap buffers"); + } + checkEglError(); + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + // Ignore + } + } + + finishGL(); + } + + private int loadTexture(int resource) { + int[] textures = new int[1]; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, textures, 0); + checkGlError(); + + int texture = textures[0]; + glBindTexture(GL_TEXTURE_2D, texture); + checkGlError(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource); + + GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0); + checkGlError(); + + bitmap.recycle(); + + return texture; + } + + private static int buildProgram(String vertex, String fragment) { + int vertexShader = buildShader(vertex, GL_VERTEX_SHADER); + if (vertexShader == 0) return 0; + + int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); + if (fragmentShader == 0) return 0; + + int program = glCreateProgram(); + glAttachShader(program, vertexShader); + checkGlError(); + + glAttachShader(program, fragmentShader); + checkGlError(); + + glLinkProgram(program); + checkGlError(); + + int[] status = new int[1]; + glGetProgramiv(program, GL_LINK_STATUS, status, 0); + if (status[0] != GL_TRUE) { + String error = glGetProgramInfoLog(program); + Log.d(LOG_TAG, "Error while linking program:\n" + error); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + glDeleteProgram(program); + return 0; + } + + return program; + } + + private static int buildShader(String source, int type) { + int shader = glCreateShader(type); + + glShaderSource(shader, source); + checkGlError(); + + glCompileShader(shader); + checkGlError(); + + int[] status = new int[1]; + glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0); + if (status[0] != GL_TRUE) { + String error = glGetShaderInfoLog(shader); + Log.d(LOG_TAG, "Error while compiling shader:\n" + error); + glDeleteShader(shader); + return 0; + } + + return shader; + } + + private void checkEglError() { + int error = mEgl.eglGetError(); + if (error != EGL10.EGL_SUCCESS) { + Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error)); + } + } + + private static void checkGlError() { + int error = glGetError(); + if (error != GL_NO_ERROR) { + Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error)); + } + } + + private void finishGL() { + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + } + + private void checkCurrent() { + if (!mEglContext.equals(mEgl.eglGetCurrentContext()) || + !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + } + } + + private void initGL() { + mEgl = (EGL10) EGLContext.getEGL(); + + mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { + throw new RuntimeException("eglGetDisplay failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + int[] version = new int[2]; + if (!mEgl.eglInitialize(mEglDisplay, version)) { + throw new RuntimeException("eglInitialize failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + mEglConfig = chooseEglConfig(); + if (mEglConfig == null) { + throw new RuntimeException("eglConfig not initialized"); + } + + mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); + + mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null); + + if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { + int error = mEgl.eglGetError(); + if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { + Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); + return; + } + throw new RuntimeException("createWindowSurface failed " + + GLUtils.getEGLErrorString(error)); + } + + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + } + + + EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { + int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; + return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); + } + + private EGLConfig chooseEglConfig() { + int[] configsCount = new int[1]; + EGLConfig[] configs = new EGLConfig[1]; + int[] configSpec = getConfig(); + if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { + throw new IllegalArgumentException("eglChooseConfig failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } else if (configsCount[0] > 0) { + return configs[0]; + } + return null; + } + + private static int[] getConfig() { + return new int[]{ + EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_ALPHA_SIZE, 8, + EGL10.EGL_DEPTH_SIZE, 0, + EGL10.EGL_STENCIL_SIZE, 0, + EGL10.EGL_NONE + }; + } + + public void finish() { + mFinished = true; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvArrayAdapter.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvArrayAdapter.java new file mode 100644 index 0000000000000..e5a3a49cf2285 --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvArrayAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench.recyclerview; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class RvArrayAdapter extends RecyclerView.Adapter { + private String[] mDataSet; + private LayoutInflater mLayoutInflater; + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView mTextView; + + public ViewHolder(View v) { + super(v); + mTextView = (TextView) v.findViewById(android.R.id.text1); + } + + public TextView getTextView() { + return mTextView; + } + } + + public RvArrayAdapter(String[] dataSet) { + mDataSet = dataSet; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + if (mLayoutInflater == null) { + mLayoutInflater = LayoutInflater.from(viewGroup.getContext()); + } + View v = mLayoutInflater.inflate(android.R.layout.simple_list_item_1, viewGroup, false); + + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) { + viewHolder.getTextView().setText(mDataSet[position]); + } + + @Override + public int getItemCount() { + return mDataSet.length; + } +} diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java new file mode 100644 index 0000000000000..e08dbc66e7f2b --- /dev/null +++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.test.uibench.recyclerview; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; + +import com.android.test.uibench.R; + +public abstract class RvCompatListActivity extends AppCompatActivity { + public static class RecyclerViewFragment extends Fragment { + RecyclerView.LayoutManager layoutManager; + RecyclerView.Adapter adapter; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + RecyclerView recyclerView = (RecyclerView) inflater.inflate( + R.layout.recycler_view, container, false); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(adapter); + return recyclerView; + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentById(android.R.id.content) == null) { + RecyclerViewFragment fragment = new RecyclerViewFragment(); + fragment.layoutManager = createLayoutManager(this); + fragment.adapter = createAdapter(); + fm.beginTransaction().add(android.R.id.content, fragment).commit(); + } + } + + protected RecyclerView.LayoutManager createLayoutManager(Context context) { + return new LinearLayoutManager(context); + } + + protected abstract RecyclerView.Adapter createAdapter(); +} diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk index 68c2fe8fbcb2b..ee26729385e1d 100644 --- a/tools/aapt/Android.mk +++ b/tools/aapt/Android.mk @@ -63,8 +63,8 @@ aaptHostLdLibs := aaptHostStaticLibs := \ libandroidfw \ libpng \ - liblog \ libutils \ + liblog \ libcutils \ libexpat \ libziparchive-host \ diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 4c108688f2b52..58c65db8f7889 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -383,6 +383,16 @@ static void printUsesPermission(const String8& name, bool optional=false, int ma } } +static void printUsesPermissionSdk23(const String8& name, int maxSdkVersion=-1) { + printf("uses-permission-sdk-23: "); + + printf("name='%s'", ResTable::normalizeForOutput(name.string()).string()); + if (maxSdkVersion != -1) { + printf(" maxSdkVersion='%d'", maxSdkVersion); + } + printf("\n"); +} + static void printUsesImpliedPermission(const String8& name, const String8& reason) { printf("uses-implied-permission: name='%s' reason='%s'\n", ResTable::normalizeForOutput(name.string()).string(), @@ -463,11 +473,19 @@ static void printComponentPresence(const char* componentName) { * a pre-requisite or some other reason. */ struct ImpliedFeature { + ImpliedFeature() : impliedBySdk23(false) {} + ImpliedFeature(const String8& n, bool sdk23) : name(n), impliedBySdk23(sdk23) {} + /** * Name of the implied feature. */ String8 name; + /** + * Was this implied by a permission from SDK 23 ()? + */ + bool impliedBySdk23; + /** * List of human-readable reasons for why this feature was implied. */ @@ -497,18 +515,24 @@ struct FeatureGroup { }; static void addImpliedFeature(KeyedVector* impliedFeatures, - const char* name, const char* reason) { + const char* name, const char* reason, bool sdk23) { String8 name8(name); ssize_t idx = impliedFeatures->indexOfKey(name8); if (idx < 0) { - idx = impliedFeatures->add(name8, ImpliedFeature()); - impliedFeatures->editValueAt(idx).name = name8; + idx = impliedFeatures->add(name8, ImpliedFeature(name8, sdk23)); } - impliedFeatures->editValueAt(idx).reasons.add(String8(reason)); + + ImpliedFeature* feature = &impliedFeatures->editValueAt(idx); + + // A non-sdk 23 implied feature takes precedence. + if (feature->impliedBySdk23 && !sdk23) { + feature->impliedBySdk23 = false; + } + feature->reasons.add(String8(reason)); } -static void printFeatureGroup(const FeatureGroup& grp, - const KeyedVector* impliedFeatures = NULL) { +static void printFeatureGroupImpl(const FeatureGroup& grp, + const KeyedVector* impliedFeatures) { printf("feature-group: label='%s'\n", grp.label.string()); if (grp.openGLESVersion > 0) { @@ -536,9 +560,11 @@ static void printFeatureGroup(const FeatureGroup& grp, String8 printableFeatureName(ResTable::normalizeForOutput( impliedFeature.name.string())); - printf(" uses-feature: name='%s'\n", printableFeatureName.string()); - printf(" uses-implied-feature: name='%s' reason='", - printableFeatureName.string()); + const char* sdk23Suffix = impliedFeature.impliedBySdk23 ? "-sdk-23" : ""; + + printf(" uses-feature%s: name='%s'\n", sdk23Suffix, printableFeatureName.string()); + printf(" uses-implied-feature%s: name='%s' reason='", sdk23Suffix, + printableFeatureName.string()); const size_t numReasons = impliedFeature.reasons.size(); for (size_t j = 0; j < numReasons; j++) { printf("%s", impliedFeature.reasons[j].string()); @@ -552,6 +578,15 @@ static void printFeatureGroup(const FeatureGroup& grp, } } +static void printFeatureGroup(const FeatureGroup& grp) { + printFeatureGroupImpl(grp, NULL); +} + +static void printDefaultFeatureGroup(const FeatureGroup& grp, + const KeyedVector& impliedFeatures) { + printFeatureGroupImpl(grp, &impliedFeatures); +} + static void addParentFeatures(FeatureGroup* grp, const String8& name) { if (name == "android.hardware.camera.autofocus" || name == "android.hardware.camera.flash") { @@ -572,6 +607,72 @@ static void addParentFeatures(FeatureGroup* grp, const String8& name) { } } +static void addImpliedFeaturesForPermission(const int targetSdk, const String8& name, + KeyedVector* impliedFeatures, + bool impliedBySdk23Permission) { + if (name == "android.permission.CAMERA") { + addImpliedFeature(impliedFeatures, "android.hardware.camera", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.ACCESS_FINE_LOCATION") { + addImpliedFeature(impliedFeatures, "android.hardware.location.gps", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + addImpliedFeature(impliedFeatures, "android.hardware.location", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { + addImpliedFeature(impliedFeatures, "android.hardware.location", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { + addImpliedFeature(impliedFeatures, "android.hardware.location.network", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + addImpliedFeature(impliedFeatures, "android.hardware.location", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || + name == "android.permission.INSTALL_LOCATION_PROVIDER") { + addImpliedFeature(impliedFeatures, "android.hardware.location", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.BLUETOOTH" || + name == "android.permission.BLUETOOTH_ADMIN") { + if (targetSdk > 4) { + addImpliedFeature(impliedFeatures, "android.hardware.bluetooth", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + addImpliedFeature(impliedFeatures, "android.hardware.bluetooth", + "targetSdkVersion > 4", impliedBySdk23Permission); + } + } else if (name == "android.permission.RECORD_AUDIO") { + addImpliedFeature(impliedFeatures, "android.hardware.microphone", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.ACCESS_WIFI_STATE" || + name == "android.permission.CHANGE_WIFI_STATE" || + name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { + addImpliedFeature(impliedFeatures, "android.hardware.wifi", + String8::format("requested %s permission", name.string()) + .string(), impliedBySdk23Permission); + } else if (name == "android.permission.CALL_PHONE" || + name == "android.permission.CALL_PRIVILEGED" || + name == "android.permission.MODIFY_PHONE_STATE" || + name == "android.permission.PROCESS_OUTGOING_CALLS" || + name == "android.permission.READ_SMS" || + name == "android.permission.RECEIVE_SMS" || + name == "android.permission.RECEIVE_MMS" || + name == "android.permission.RECEIVE_WAP_PUSH" || + name == "android.permission.SEND_SMS" || + name == "android.permission.WRITE_APN_SETTINGS" || + name == "android.permission.WRITE_SMS") { + addImpliedFeature(impliedFeatures, "android.hardware.telephony", + String8("requested a telephony permission").string(), + impliedBySdk23Permission); + } +} + /* * Handle the "dump" command, to extract select data from an archive. */ @@ -712,7 +813,8 @@ int doDump(Bundle* bundle) size_t len; ResXMLTree::event_code_t code; int depth = 0; - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { + while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && + code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::END_TAG) { depth--; continue; @@ -735,25 +837,53 @@ int doDump(Bundle* bundle) } String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL); printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string()); - } else if (depth == 2 && tag == "permission") { - String8 error; - String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR: %s\n", error.string()); - goto bail; - } - printf("permission: %s\n", - ResTable::normalizeForOutput(name.string()).string()); - } else if (depth == 2 && tag == "uses-permission") { - String8 error; - String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR: %s\n", error.string()); - goto bail; + } else if (depth == 2) { + if (tag == "permission") { + String8 error; + String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR: %s\n", error.string()); + goto bail; + } + + if (name == "") { + fprintf(stderr, "ERROR: missing 'android:name' for permission\n"); + goto bail; + } + printf("permission: %s\n", + ResTable::normalizeForOutput(name.string()).string()); + } else if (tag == "uses-permission") { + String8 error; + String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR: %s\n", error.string()); + goto bail; + } + + if (name == "") { + fprintf(stderr, "ERROR: missing 'android:name' for uses-permission\n"); + goto bail; + } + printUsesPermission(name, + AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, + AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); + } else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") { + String8 error; + String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR: %s\n", error.string()); + goto bail; + } + + if (name == "") { + fprintf(stderr, "ERROR: missing 'android:name' for " + "uses-permission-sdk-23\n"); + goto bail; + } + printUsesPermissionSdk23( + name, + AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); } - printUsesPermission(name, - AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, - AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); } } } else if (strcmp("badging", option) == 0) { @@ -893,7 +1023,8 @@ int doDump(Bundle* bundle) Vector featureGroups; KeyedVector impliedFeatures; - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { + while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && + code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::END_TAG) { depth--; if (depth < 2) { @@ -924,8 +1055,10 @@ int doDump(Bundle* bundle) ResTable::normalizeForOutput(aName.string()).string()); } printf(" label='%s' icon='%s'\n", - ResTable::normalizeForOutput(activityLabel.string()).string(), - ResTable::normalizeForOutput(activityIcon.string()).string()); + ResTable::normalizeForOutput(activityLabel.string()) + .string(), + ResTable::normalizeForOutput(activityIcon.string()) + .string()); } if (isLeanbackLauncherActivity) { printf("leanback-launchable-activity:"); @@ -934,9 +1067,12 @@ int doDump(Bundle* bundle) ResTable::normalizeForOutput(aName.string()).string()); } printf(" label='%s' icon='%s' banner='%s'\n", - ResTable::normalizeForOutput(activityLabel.string()).string(), - ResTable::normalizeForOutput(activityIcon.string()).string(), - ResTable::normalizeForOutput(activityBanner.string()).string()); + ResTable::normalizeForOutput(activityLabel.string()) + .string(), + ResTable::normalizeForOutput(activityIcon.string()) + .string(), + ResTable::normalizeForOutput(activityBanner.string()) + .string()); } } if (!hasIntentFilter) { @@ -964,18 +1100,21 @@ int doDump(Bundle* bundle) hasLauncher |= catLauncher; hasCameraActivity |= actCamera; hasCameraSecureActivity |= actCameraSecure; - hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure; + hasOtherActivities |= + !actMainActivity && !actCamera && !actCameraSecure; } else if (withinReceiver) { hasWidgetReceivers |= actWidgetReceivers; hasDeviceAdminReceiver |= (actDeviceAdminEnabled && hasBindDeviceAdminPermission); - hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled); + hasOtherReceivers |= + (!actWidgetReceivers && !actDeviceAdminEnabled); } else if (withinService) { hasImeService |= actImeService; hasWallpaperService |= actWallpaperService; hasAccessibilityService |= (actAccessibilityService && hasBindAccessibilityServicePermission); - hasPrintService |= (actPrintService && hasBindPrintServicePermission); + hasPrintService |= + (actPrintService && hasBindPrintServicePermission); hasNotificationListenerService |= actNotificationListenerService && hasBindNotificationListenerServicePermission; hasDreamService |= actDreamService && hasBindDreamServicePermission; @@ -984,7 +1123,8 @@ int doDump(Bundle* bundle) !actHostApduService && !actOffHostApduService && !actNotificationListenerService); } else if (withinProvider) { - hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes; + hasDocumentsProvider |= + actDocumentsProvider && hasRequiredSafAttributes; } } withinIntentFilter = false; @@ -1125,7 +1265,8 @@ int doDump(Bundle* bundle) goto bail; } - String8 banner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, &error); + String8 banner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR, + &error); if (error != "") { fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n", error.string()); @@ -1135,7 +1276,8 @@ int doDump(Bundle* bundle) ResTable::normalizeForOutput(label.string()).string()); printf("icon='%s'", ResTable::normalizeForOutput(icon.string()).string()); if (banner != "") { - printf(" banner='%s'", ResTable::normalizeForOutput(banner.string()).string()); + printf(" banner='%s'", + ResTable::normalizeForOutput(banner.string()).string()); } printf("\n"); if (testOnly != 0) { @@ -1178,13 +1320,15 @@ int doDump(Bundle* bundle) } } } else if (tag == "uses-sdk") { - int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); + int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, + &error); if (error != "") { error = ""; String8 name = AaptXml::getResolvedAttribute(res, tree, MIN_SDK_VERSION_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", + fprintf(stderr, + "ERROR getting 'android:minSdkVersion' attribute: %s\n", error.string()); goto bail; } @@ -1205,7 +1349,8 @@ int doDump(Bundle* bundle) String8 name = AaptXml::getResolvedAttribute(res, tree, TARGET_SDK_VERSION_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", + fprintf(stderr, + "ERROR getting 'android:targetSdkVersion' attribute: %s\n", error.string()); goto bail; } @@ -1297,90 +1442,58 @@ int doDump(Bundle* bundle) } } else if (tag == "uses-permission") { String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); - if (name != "" && error == "") { - if (name == "android.permission.CAMERA") { - addImpliedFeature(&impliedFeatures, "android.hardware.camera", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.ACCESS_FINE_LOCATION") { - addImpliedFeature(&impliedFeatures, "android.hardware.location.gps", - String8::format("requested %s permission", name.string()) - .string()); - addImpliedFeature(&impliedFeatures, "android.hardware.location", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { - addImpliedFeature(&impliedFeatures, "android.hardware.location", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { - addImpliedFeature(&impliedFeatures, "android.hardware.location.network", - String8::format("requested %s permission", name.string()) - .string()); - addImpliedFeature(&impliedFeatures, "android.hardware.location", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || - name == "android.permission.INSTALL_LOCATION_PROVIDER") { - addImpliedFeature(&impliedFeatures, "android.hardware.location", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.BLUETOOTH" || - name == "android.permission.BLUETOOTH_ADMIN") { - if (targetSdk > 4) { - addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", - String8::format("requested %s permission", name.string()) - .string()); - addImpliedFeature(&impliedFeatures, "android.hardware.bluetooth", - "targetSdkVersion > 4"); - } - } else if (name == "android.permission.RECORD_AUDIO") { - addImpliedFeature(&impliedFeatures, "android.hardware.microphone", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.ACCESS_WIFI_STATE" || - name == "android.permission.CHANGE_WIFI_STATE" || - name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { - addImpliedFeature(&impliedFeatures, "android.hardware.wifi", - String8::format("requested %s permission", name.string()) - .string()); - } else if (name == "android.permission.CALL_PHONE" || - name == "android.permission.CALL_PRIVILEGED" || - name == "android.permission.MODIFY_PHONE_STATE" || - name == "android.permission.PROCESS_OUTGOING_CALLS" || - name == "android.permission.READ_SMS" || - name == "android.permission.RECEIVE_SMS" || - name == "android.permission.RECEIVE_MMS" || - name == "android.permission.RECEIVE_WAP_PUSH" || - name == "android.permission.SEND_SMS" || - name == "android.permission.WRITE_APN_SETTINGS" || - name == "android.permission.WRITE_SMS") { - addImpliedFeature(&impliedFeatures, "android.hardware.telephony", - String8("requested a telephony permission").string()); - } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { - hasWriteExternalStoragePermission = true; - } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { - hasReadExternalStoragePermission = true; - } else if (name == "android.permission.READ_PHONE_STATE") { - hasReadPhoneStatePermission = true; - } else if (name == "android.permission.READ_CONTACTS") { - hasReadContactsPermission = true; - } else if (name == "android.permission.WRITE_CONTACTS") { - hasWriteContactsPermission = true; - } else if (name == "android.permission.READ_CALL_LOG") { - hasReadCallLogPermission = true; - } else if (name == "android.permission.WRITE_CALL_LOG") { - hasWriteCallLogPermission = true; - } + if (error != "") { + fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", + error.string()); + goto bail; + } - printUsesPermission(name, - AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, - AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); - } else { + if (name == "") { + fprintf(stderr, "ERROR: missing 'android:name' for uses-permission\n"); + goto bail; + } + + addImpliedFeaturesForPermission(targetSdk, name, &impliedFeatures, false); + + if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { + hasWriteExternalStoragePermission = true; + } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { + hasReadExternalStoragePermission = true; + } else if (name == "android.permission.READ_PHONE_STATE") { + hasReadPhoneStatePermission = true; + } else if (name == "android.permission.READ_CONTACTS") { + hasReadContactsPermission = true; + } else if (name == "android.permission.WRITE_CONTACTS") { + hasWriteContactsPermission = true; + } else if (name == "android.permission.READ_CALL_LOG") { + hasReadCallLogPermission = true; + } else if (name == "android.permission.WRITE_CALL_LOG") { + hasWriteCallLogPermission = true; + } + + printUsesPermission(name, + AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0, + AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); + + } else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") { + String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); + if (error != "") { fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string()); goto bail; } + + if (name == "") { + fprintf(stderr, "ERROR: missing 'android:name' for " + "uses-permission-sdk-23\n"); + goto bail; + } + + addImpliedFeaturesForPermission(targetSdk, name, &impliedFeatures, true); + + printUsesPermissionSdk23( + name, AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR)); + } else if (tag == "uses-package") { String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); if (name != "" && error == "") { @@ -1422,7 +1535,8 @@ int doDump(Bundle* bundle) } else if (tag == "package-verifier") { String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); if (name != "" && error == "") { - String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error); + String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, + &error); if (publicKey != "" && error == "") { printf("package-verifier: name='%s' publicKey='%s'\n", ResTable::normalizeForOutput(name.string()).string(), @@ -1485,12 +1599,18 @@ int doDump(Bundle* bundle) if (error == "") { if (orien == 0 || orien == 6 || orien == 8) { // Requests landscape, sensorLandscape, or reverseLandscape. - addImpliedFeature(&impliedFeatures, "android.hardware.screen.landscape", - "one or more activities have specified a landscape orientation"); + addImpliedFeature(&impliedFeatures, + "android.hardware.screen.landscape", + "one or more activities have specified a " + "landscape orientation", + false); } else if (orien == 1 || orien == 7 || orien == 9) { // Requests portrait, sensorPortrait, or reversePortrait. - addImpliedFeature(&impliedFeatures, "android.hardware.screen.portrait", - "one or more activities have specified a portrait orientation"); + addImpliedFeature(&impliedFeatures, + "android.hardware.screen.portrait", + "one or more activities have specified a " + "portrait orientation", + false); } } } else if (tag == "uses-library") { @@ -1524,8 +1644,10 @@ int doDump(Bundle* bundle) hasBindDeviceAdminPermission = true; } } else { - fprintf(stderr, "ERROR getting 'android:permission' attribute for" - " receiver '%s': %s\n", receiverName.string(), error.string()); + fprintf(stderr, + "ERROR getting 'android:permission' attribute for" + " receiver '%s': %s\n", + receiverName.string(), error.string()); } } else if (tag == "service") { withinService = true; @@ -1542,20 +1664,24 @@ int doDump(Bundle* bundle) if (error == "") { if (permission == "android.permission.BIND_INPUT_METHOD") { hasBindInputMethodPermission = true; - } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") { + } else if (permission == + "android.permission.BIND_ACCESSIBILITY_SERVICE") { hasBindAccessibilityServicePermission = true; - } else if (permission == "android.permission.BIND_PRINT_SERVICE") { + } else if (permission == + "android.permission.BIND_PRINT_SERVICE") { hasBindPrintServicePermission = true; - } else if (permission == "android.permission.BIND_NFC_SERVICE") { + } else if (permission == + "android.permission.BIND_NFC_SERVICE") { hasBindNfcServicePermission = true; - } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { + } else if (permission == + "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") { hasBindNotificationListenerServicePermission = true; } else if (permission == "android.permission.BIND_DREAM_SERVICE") { hasBindDreamServicePermission = true; } } else { - fprintf(stderr, "ERROR getting 'android:permission' attribute for" - " service '%s': %s\n", serviceName.string(), error.string()); + fprintf(stderr, "ERROR getting 'android:permission' attribute for " + "service '%s': %s\n", serviceName.string(), error.string()); } } else if (tag == "provider") { withinProvider = true; @@ -1563,7 +1689,8 @@ int doDump(Bundle* bundle) bool exported = AaptXml::getResolvedIntegerAttribute(res, tree, EXPORTED_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:" + fprintf(stderr, + "ERROR getting 'android:exported' attribute for provider:" " %s\n", error.string()); goto bail; } @@ -1571,16 +1698,17 @@ int doDump(Bundle* bundle) bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute( res, tree, GRANT_URI_PERMISSIONS_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:" - " %s\n", error.string()); + fprintf(stderr, + "ERROR getting 'android:grantUriPermissions' attribute for " + "provider: %s\n", error.string()); goto bail; } String8 permission = AaptXml::getResolvedAttribute(res, tree, PERMISSION_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:" - " %s\n", error.string()); + fprintf(stderr, "ERROR getting 'android:permission' attribute for " + "provider: %s\n", error.string()); goto bail; } @@ -1661,8 +1789,9 @@ int doDump(Bundle* bundle) } else if (withinService && tag == "meta-data") { String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute for" - " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); + fprintf(stderr, "ERROR getting 'android:name' attribute for " + "meta-data tag in service '%s': %s\n", serviceName.string(), + error.string()); goto bail; } @@ -1676,8 +1805,9 @@ int doDump(Bundle* bundle) String8 xmlPath = AaptXml::getResolvedAttribute(res, tree, RESOURCE_ATTR, &error); if (error != "") { - fprintf(stderr, "ERROR getting 'android:resource' attribute for" - " meta-data tag in service '%s': %s\n", serviceName.string(), error.string()); + fprintf(stderr, "ERROR getting 'android:resource' attribute for " + "meta-data tag in service '%s': %s\n", + serviceName.string(), error.string()); goto bail; } @@ -1731,15 +1861,19 @@ int doDump(Bundle* bundle) actImeService = true; } else if (action == "android.service.wallpaper.WallpaperService") { actWallpaperService = true; - } else if (action == "android.accessibilityservice.AccessibilityService") { + } else if (action == + "android.accessibilityservice.AccessibilityService") { actAccessibilityService = true; - } else if (action == "android.printservice.PrintService") { + } else if (action =="android.printservice.PrintService") { actPrintService = true; - } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { + } else if (action == + "android.nfc.cardemulation.action.HOST_APDU_SERVICE") { actHostApduService = true; - } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { + } else if (action == + "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") { actOffHostApduService = true; - } else if (action == "android.service.notification.NotificationListenerService") { + } else if (action == + "android.service.notification.NotificationListenerService") { actNotificationListenerService = true; } else if (action == "android.service.dreams.DreamService") { actDreamService = true; @@ -1814,12 +1948,12 @@ int doDump(Bundle* bundle) } addImpliedFeature(&impliedFeatures, "android.hardware.touchscreen", - "default feature for all apps"); + "default feature for all apps", false); const size_t numFeatureGroups = featureGroups.size(); if (numFeatureGroups == 0) { // If no tags were defined, apply auto-implied features. - printFeatureGroup(commonFeatures, &impliedFeatures); + printDefaultFeatureGroup(commonFeatures, impliedFeatures); } else { // tags are defined, so we ignore implied features and diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index c636c2875fdf2..b796b27b4dfcd 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -2543,7 +2543,7 @@ static status_t writeSymbolClass( fprintf(fp, "%s/** %s\n", getIndentSpace(indent), cmt.string()); - } else if (sym.isPublic && !includePrivate) { + } else if (sym.isPublic && !includePrivate && kIsDebug) { sym.sourcePos.warning("No comment for public symbol %s:%s/%s", assets->getPackage().string(), className.string(), String8(sym.name).string()); @@ -2589,7 +2589,7 @@ static status_t writeSymbolClass( "%s */\n", getIndentSpace(indent), cmt.string(), getIndentSpace(indent)); - } else if (sym.isPublic && !includePrivate) { + } else if (sym.isPublic && !includePrivate && kIsDebug) { sym.sourcePos.warning("No comment for public symbol %s:%s/%s", assets->getPackage().string(), className.string(), String8(sym.name).string()); diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 889883adc7f17..fb0299e553fa4 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -1467,6 +1467,11 @@ status_t compileResourceFile(Bundle* bundle, } } } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) { + // Note the existence and locale of every string array we process + char rawLocale[RESTABLE_MAX_LOCALE_LEN]; + curParams.getBcp47Locale(rawLocale); + String8 locale(rawLocale); + String16 name; // Check whether these strings need valid formats. // (simplified form of what string16 does above) bool isTranslatable = false; @@ -1477,7 +1482,9 @@ status_t compileResourceFile(Bundle* bundle, for (size_t i = 0; i < n; i++) { size_t length; const char16_t* attr = block.getAttributeName(i, &length); - if (strcmp16(attr, formatted16.string()) == 0) { + if (strcmp16(attr, name16.string()) == 0) { + name.setTo(block.getAttributeStringValue(i, &length)); + } else if (strcmp16(attr, formatted16.string()) == 0) { const char16_t* value = block.getAttributeStringValue(i, &length); if (strcmp16(value, false16.string()) == 0) { curIsFormatted = false; @@ -1486,6 +1493,15 @@ status_t compileResourceFile(Bundle* bundle, const char16_t* value = block.getAttributeStringValue(i, &length); if (strcmp16(value, false16.string()) == 0) { isTranslatable = false; + // Untranslatable string arrays must only exist + // in the default [empty] locale + if (locale.size() > 0) { + SourcePos(in->getPrintableSource(), block.getLineNumber()).warning( + "string-array '%s' marked untranslatable but exists" + " in locale '%s'\n", String8(name).string(), + locale.string()); + // hasErrors = localHasErrors = true; + } } } } diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp index 9908c44c6d1fe..0d59faece985b 100644 --- a/tools/aapt/StringPool.cpp +++ b/tools/aapt/StringPool.cpp @@ -127,7 +127,7 @@ int StringPool::entry::compare(const entry& o) const { } StringPool::StringPool(bool utf8) : - mUTF8(utf8), mValues(-1) + mUTF8(utf8) { } @@ -144,8 +144,8 @@ ssize_t StringPool::add(const String16& value, const Vector& s ssize_t StringPool::add(const String16& value, bool mergeDuplicates, const String8* configTypeName, const ResTable_config* config) { - ssize_t vidx = mValues.indexOfKey(value); - ssize_t pos = vidx >= 0 ? mValues.valueAt(vidx) : -1; + auto it = mValues.find(value); + ssize_t pos = it != mValues.end() ? it->second : -1; ssize_t eidx = pos >= 0 ? mEntryArray.itemAt(pos) : -1; if (eidx < 0) { eidx = mEntries.add(entry(value)); @@ -192,21 +192,21 @@ ssize_t StringPool::add(const String16& value, } } - const bool first = vidx < 0; + const bool first = (it == mValues.end()); const bool styled = (pos >= 0 && (size_t)pos < mEntryStyleArray.size()) ? mEntryStyleArray[pos].spans.size() : 0; if (first || styled || !mergeDuplicates) { pos = mEntryArray.add(eidx); if (first) { - vidx = mValues.add(value, pos); + mValues[value] = pos; } entry& ent = mEntries.editItemAt(eidx); ent.indices.add(pos); } if (kIsDebug) { - printf("Adding string %s to pool: pos=%zd eidx=%zd vidx=%zd\n", - String8(value).string(), SSIZE(pos), SSIZE(eidx), SSIZE(vidx)); + printf("Adding string %s to pool: pos=%zd eidx=%zd\n", + String8(value).string(), SSIZE(pos), SSIZE(eidx)); } return pos; @@ -349,14 +349,18 @@ void StringPool::sortByConfig() // Now trim any entries at the end of the new style array that are // not needed. - for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) { + ssize_t i; + for (i=newEntryStyleArray.size()-1; i>=0; i--) { const entry_style& style = newEntryStyleArray[i]; if (style.spans.size() > 0) { // That's it. break; } - // This one is not needed; remove. - newEntryStyleArray.removeAt(i); + } + + ssize_t nToRemove=newEntryStyleArray.size()-(i+1); + if (nToRemove) { + newEntryStyleArray.removeItemsAt(i+1, nToRemove); } // All done, install the new data structures and upate mValues with @@ -367,7 +371,7 @@ void StringPool::sortByConfig() mValues.clear(); for (size_t i=0; i* StringPool::offsetsForString(const String16& val) const { - ssize_t pos = mValues.valueFor(val); - if (pos < 0) { + auto it = mValues.find(val); + if (it == mValues.end()) { return NULL; } + ssize_t pos = it->second; return &mEntries[mEntryArray[pos]].indices; } diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h index dbe8c8542185f..3014a3bc6da17 100644 --- a/tools/aapt/StringPool.h +++ b/tools/aapt/StringPool.h @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -175,7 +176,7 @@ class StringPool // Unique set of all the strings added to the pool, mapped to // the first index of mEntryArray where the value was added. - DefaultKeyedVector mValues; + std::map mValues; // This array maps from the original position a string was placed at // in mEntryArray to its new position after being sorted with sortByConfig(). Vector mOriginalPosToNewPos; diff --git a/tools/aapt2/Util.cpp b/tools/aapt2/Util.cpp index 03ecd1aca310e..5b064e33d162e 100644 --- a/tools/aapt2/Util.cpp +++ b/tools/aapt2/Util.cpp @@ -303,8 +303,10 @@ std::string utf16ToUtf8(const StringPiece16& utf16) { } std::string utf8; + // Make room for '\0' explicitly. + utf8.resize(utf8Length + 1); + utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8Length + 1); utf8.resize(utf8Length); - utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin()); return utf8; } diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp index cd4fbe5cd4913..d37a946e93675 100644 --- a/tools/aidl/aidl.cpp +++ b/tools/aidl/aidl.cpp @@ -345,6 +345,13 @@ gather_types(const char* filename, document_item_type* items) name, Type::GENERATED, false, false, false, filename, c->name.lineno); NAMES.Add(proxy); + + name = c->name.data; + name += ".NoOp"; + Type* noOp = new Type(c->package ? c->package : "", + name, Type::GENERATED, false, false, false, + filename, c->name.lineno); + NAMES.Add(noOp); } else if (items->item_type == INTERFACE_TYPE_RPC) { // for interfaces, also add the service base type, we don't @@ -1064,8 +1071,13 @@ compile_aidl(Options& options) // make sure the folders of the output file all exists check_outputFilePath(options.outputFileName); + int flags = 0; + if (options.generateNoOpMethods) { + flags |= GENERATE_NO_OP_CLASS; + } + err = generate_java(options.outputFileName, options.inputFileName.c_str(), - (interface_type*)mainDoc); + (interface_type*)mainDoc, flags); return err; } diff --git a/tools/aidl/generate_java.cpp b/tools/aidl/generate_java.cpp index 9e57407e772ff..881746182dbd3 100644 --- a/tools/aidl/generate_java.cpp +++ b/tools/aidl/generate_java.cpp @@ -59,12 +59,12 @@ append(const char* a, const char* b) // ================================================= int generate_java(const string& filename, const string& originalSrc, - interface_type* iface) + interface_type* iface, int flags) { Class* cl; if (iface->document_item.item_type == INTERFACE_TYPE_BINDER) { - cl = generate_binder_interface_class(iface); + cl = generate_binder_interface_class(iface, flags); } else if (iface->document_item.item_type == INTERFACE_TYPE_RPC) { cl = generate_rpc_interface_class(iface); diff --git a/tools/aidl/generate_java.h b/tools/aidl/generate_java.h index 4bfcfeba07c86..45b2703ef366e 100644 --- a/tools/aidl/generate_java.h +++ b/tools/aidl/generate_java.h @@ -9,9 +9,9 @@ using namespace std; int generate_java(const string& filename, const string& originalSrc, - interface_type* iface); + interface_type* iface, int flags); -Class* generate_binder_interface_class(const interface_type* iface); +Class* generate_binder_interface_class(const interface_type* iface, int flags); Class* generate_rpc_interface_class(const interface_type* iface); string gather_comments(extra_text_type* extra); @@ -29,5 +29,8 @@ class VariableFactory int m_index; }; +//Set of flags that can be passed to generate_java +#define GENERATE_NO_OP_CLASS 1 << 0 + #endif // GENERATE_JAVA_H diff --git a/tools/aidl/generate_java_binder.cpp b/tools/aidl/generate_java_binder.cpp index 1b538ca0181ed..48ac0278fa728 100644 --- a/tools/aidl/generate_java_binder.cpp +++ b/tools/aidl/generate_java_binder.cpp @@ -193,6 +193,36 @@ ProxyClass::~ProxyClass() { } +// ================================================= +class DefaultNoOpClass : public Class { +public: + DefaultNoOpClass(Type* type, InterfaceType* interfaceType); + virtual ~DefaultNoOpClass(); +}; + +DefaultNoOpClass::DefaultNoOpClass(Type* type, InterfaceType* interfaceType) + :Class() +{ + this->comment = "/** No-Op implementation */"; + this->comment += "\n/** @hide */"; + this->modifiers = PUBLIC | STATIC; + this->what = Class::CLASS; + this->type = type; + this->interfaces.push_back(interfaceType); + + // IBinder asBinder() + Method* asBinder = new Method; + asBinder->modifiers = PUBLIC | OVERRIDE; + asBinder->returnType = IBINDER_TYPE; + asBinder->name = "asBinder"; + asBinder->statements = new StatementBlock; + asBinder->statements->Add(new ReturnStatement(NULL_VALUE)); + this->elements.push_back(asBinder); +} + +DefaultNoOpClass::~DefaultNoOpClass() { +} + // ================================================= static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, @@ -245,10 +275,24 @@ generate_read_from_parcel(Type* t, StatementBlock* addTo, Variable* v, } } +static bool +is_numeric_java_type(const char* str) { + static const char* KEYWORDS[] = { "int", "byte", "char", "float", "double", + "short", "long", NULL }; + const char** k = KEYWORDS; + while (*k) { + if (0 == strcmp(str, *k)) { + return true; + } + k++; + } + return false; +} static void generate_method(const method_type* method, Class* interface, - StubClass* stubClass, ProxyClass* proxyClass, int index) + StubClass* stubClass, ProxyClass* proxyClass, DefaultNoOpClass* noOpClass, + int index) { arg_type* arg; int i; @@ -294,6 +338,39 @@ generate_method(const method_type* method, Class* interface, interface->elements.push_back(decl); + // == the no-op method =================================================== + if (noOpClass != NULL) { + Method* noOpMethod = new Method; + noOpMethod->comment = gather_comments(method->comments_token->extra); + noOpMethod->modifiers = OVERRIDE | PUBLIC; + noOpMethod->returnType = NAMES.Search(method->type.type.data); + noOpMethod->returnTypeDimension = method->type.dimension; + noOpMethod->name = method->name.data; + noOpMethod->statements = new StatementBlock; + + arg = method->args; + while (arg != NULL) { + noOpMethod->parameters.push_back(new Variable( + NAMES.Search(arg->type.type.data), arg->name.data, + arg->type.dimension)); + arg = arg->next; + } + + if (0 != strcmp(method->type.type.data, "void")) { + bool isNumeric = is_numeric_java_type(method->type.type.data); + bool isBoolean = 0 == strcmp(method->type.type.data, "boolean"); + + if (isNumeric && method->type.dimension == 0) { + noOpMethod->statements->Add(new ReturnStatement(new LiteralExpression("0"))); + } else if (isBoolean && method->type.dimension == 0) { + noOpMethod->statements->Add(new ReturnStatement(FALSE_VALUE)); + } else { + noOpMethod->statements->Add(new ReturnStatement(NULL_VALUE)); + } + } + noOpMethod->exceptions.push_back(REMOTE_EXCEPTION_TYPE); + noOpClass->elements.push_back(noOpMethod); + } // == the stub method ==================================================== Case* c = new Case(transactCodeName); @@ -520,7 +597,7 @@ generate_interface_descriptors(StubClass* stub, ProxyClass* proxy) } Class* -generate_binder_interface_class(const interface_type* iface) +generate_binder_interface_class(const interface_type* iface, int flags) { InterfaceType* interfaceType = static_cast( NAMES.Find(iface->package, iface->name.data)); @@ -533,6 +610,15 @@ generate_binder_interface_class(const interface_type* iface) interface->type = interfaceType; interface->interfaces.push_back(IINTERFACE_TYPE); + // the No-Op inner class + DefaultNoOpClass* noOpClass = NULL; + if ((flags & GENERATE_NO_OP_CLASS) != 0) { + noOpClass = new DefaultNoOpClass( + NAMES.Find(iface->package, append(iface->name.data, ".NoOp").c_str()), + interfaceType); + interface->elements.push_back(noOpClass); + } + // the stub inner class StubClass* stub = new StubClass( NAMES.Find(iface->package, append(iface->name.data, ".Stub").c_str()), @@ -555,7 +641,8 @@ generate_binder_interface_class(const interface_type* iface) while (item != NULL) { if (item->item_type == METHOD_TYPE) { method_type * method_item = (method_type*) item; - generate_method(method_item, interface, stub, proxy, method_item->assigned_id); + generate_method(method_item, interface, stub, proxy, noOpClass, + method_item->assigned_id); } item = item->next; index++; diff --git a/tools/aidl/options.cpp b/tools/aidl/options.cpp index 7b2daebec09e1..9de1957c886c6 100644 --- a/tools/aidl/options.cpp +++ b/tools/aidl/options.cpp @@ -51,6 +51,7 @@ parse_options(int argc, const char* const* argv, Options *options) options->task = COMPILE_AIDL; options->failOnParcelable = false; options->autoDepFile = false; + options->generateNoOpMethods = false; // OPTIONS while (i < argc) { @@ -97,6 +98,9 @@ parse_options(int argc, const char* const* argv, Options *options) else if (len == 2 && s[1] == 'b') { options->failOnParcelable = true; } + else if (s[1] == 'n') { + options->generateNoOpMethods = true; + } else { // s[1] is not known fprintf(stderr, "unknown option (%d): %s\n", i, s); diff --git a/tools/aidl/options.h b/tools/aidl/options.h index 387e37d087322..969cc1cd1ecb1 100644 --- a/tools/aidl/options.h +++ b/tools/aidl/options.h @@ -24,6 +24,7 @@ struct Options string outputBaseFolder; string depFileName; bool autoDepFile; + bool generateNoOpMethods; vector filesToPreprocess; }; diff --git a/tools/layoutlib/.idea/encodings.xml b/tools/layoutlib/.idea/encodings.xml index e206d70d8595e..f758959656c79 100644 --- a/tools/layoutlib/.idea/encodings.xml +++ b/tools/layoutlib/.idea/encodings.xml @@ -1,5 +1,6 @@ - - - + + + + \ No newline at end of file diff --git a/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java b/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java deleted file mode 100644 index 4475fa4830152..0000000000000 --- a/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.animation; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.util.AttributeSet; - -/** - * Delegate providing alternate implementation to static methods in {@link AnimatorInflater}. - */ -public class AnimatorInflater_Delegate { - - @LayoutlibDelegate - /*package*/ static Animator loadAnimator(Context context, int id) - throws NotFoundException { - return loadAnimator(context.getResources(), context.getTheme(), id); - } - - @LayoutlibDelegate - /*package*/ static Animator loadAnimator(Resources resources, Theme theme, int id) - throws NotFoundException { - return loadAnimator(resources, theme, id, 1); - } - - @LayoutlibDelegate - /*package*/ static Animator loadAnimator(Resources resources, Theme theme, int id, - float pathErrorScale) throws NotFoundException { - // This is a temporary fix to http://b.android.com/77865. This skips loading the - // animation altogether. - // TODO: Remove this override when Path.approximate() is supported. - return new FakeAnimator(); - } - - @LayoutlibDelegate - /*package*/ static ValueAnimator loadAnimator(Resources res, Theme theme, - AttributeSet attrs, ValueAnimator anim, float pathErrorScale) - throws NotFoundException { - return AnimatorInflater.loadAnimator_Original(res, theme, attrs, anim, pathErrorScale); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java index 163fbcb7f9004..0e392436d7486 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java @@ -18,6 +18,7 @@ import com.android.SdkConstants; import com.android.ide.common.rendering.api.ArrayResourceValue; +import com.android.ide.common.rendering.api.DensityBasedResourceValue; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.LayoutlibCallback; import com.android.ide.common.rendering.api.ResourceValue; @@ -48,9 +49,6 @@ import java.io.InputStream; import java.util.Iterator; -/** - * - */ public final class BridgeResources extends Resources { private BridgeContext mContext; @@ -278,7 +276,7 @@ public String[] getStringArray(int id) throws NotFoundException { * always Strings. The ideal signature for the method should be <T super String>, but java * generics don't support it. */ - private T[] fillValues(ArrayResourceValue resValue, T[] values) { + T[] fillValues(ArrayResourceValue resValue, T[] values) { int i = 0; for (Iterator iterator = resValue.iterator(); iterator.hasNext(); i++) { @SuppressWarnings("unchecked") @@ -404,7 +402,7 @@ public XmlResourceParser getLayout(int id) throws NotFoundException { if (xml.isFile()) { // we need to create a pull parser around the layout XML file, and then // give that to our XmlBlockParser - parser = ParserFactory.create(xml); + parser = ParserFactory.create(xml, true); } } @@ -664,13 +662,18 @@ public void getValue(int id, TypedValue outValue, boolean resolveRefs) Pair value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getSecond().getValue(); + ResourceValue resVal = value.getSecond(); + String v = resVal.getValue(); if (v != null) { if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue, false /*requireUnit*/)) { return; } + if (resVal instanceof DensityBasedResourceValue) { + outValue.density = + ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue(); + } // else it's a string outValue.type = TypedValue.TYPE_STRING; diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java index 6a61090475736..31dd3d9437693 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java @@ -16,6 +16,7 @@ package android.content.res; +import com.android.ide.common.rendering.api.ArrayResourceValue; import com.android.ide.common.rendering.api.AttrResourceValue; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.RenderResources; @@ -33,6 +34,7 @@ import org.xmlpull.v1.XmlPullParserException; import android.annotation.Nullable; +import android.content.res.Resources.NotFoundException; import android.content.res.Resources.Theme; import android.graphics.drawable.Drawable; import android.util.DisplayMetrics; @@ -740,12 +742,20 @@ public Drawable getDrawable(int index) { */ @Override public CharSequence[] getTextArray(int index) { - String value = getString(index); - if (value != null) { - return new CharSequence[] { value }; + if (!hasValue(index)) { + return null; } - - return null; + ResourceValue resVal = mResourceData[index]; + if (resVal instanceof ArrayResourceValue) { + ArrayResourceValue array = (ArrayResourceValue) resVal; + int count = array.getElementCount(); + return count >= 0 ? mBridgeResources.fillValues(array, new CharSequence[count]) : null; + } + int id = getResourceId(index, 0); + String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : ""; + throw new NotFoundException( + String.format("%1$s in %2$s%3$s is not a valid array resource.", + resVal.getValue(), mNames[index], resIdMessage)); } @Override diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java index d858953b956c8..60514b6586492 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java @@ -59,6 +59,7 @@ if (opts.inPremultiplied) { bitmapCreateFlags.add(BitmapCreateFlags.PREMULTIPLIED); } + opts.inScaled = false; } try { diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index f8b3739b6a89b..64cd5031346e5 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -35,6 +35,8 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; @@ -707,6 +709,12 @@ public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { @Override public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { Shape shape = pathDelegate.getJavaShape(); + Rectangle2D bounds = shape.getBounds2D(); + if (bounds.isEmpty()) { + // Apple JRE 1.6 doesn't like drawing empty shapes. + // http://b.android.com/178278 + return; + } int style = paintDelegate.getStyle(); if (style == Paint.Style.FILL.nativeInt || diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index 857e6d03283e6..c7b24bcb352d4 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -178,7 +178,9 @@ public Font getFont(int desiredWeight, boolean isItalic) { desiredStyle.mIsItalic = isItalic; FontInfo bestFont = null; int bestMatch = Integer.MAX_VALUE; - for (FontInfo font : mFonts) { + //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation) + for (int i = 0, n = mFonts.size(); i < n; i++) { + FontInfo font = mFonts.get(i); int match = computeMatch(font, desiredStyle); if (match < bestMatch) { bestMatch = match; @@ -415,7 +417,9 @@ private boolean addFont(@NonNull FontInfo fontInfo) { boolean isItalic = fontInfo.mIsItalic; // The list is usually just two fonts big. So iterating over all isn't as bad as it looks. // It's biggest for roboto where the size is 12. - for (FontInfo font : mFonts) { + //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation) + for (int i = 0, n = mFonts.size(); i < n; i++) { + FontInfo font = mFonts.get(i); if (font.mWeight == weight && font.mIsItalic == isItalic) { return false; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index 65b65ec759d04..a545283ea0ca0 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -480,8 +480,10 @@ public Rasterizer_Delegate getRasterizer() { return; } - delegate.mTextSize = textSize; - delegate.updateFontObject(); + if (delegate.mTextSize != textSize) { + delegate.mTextSize = textSize; + delegate.updateFontObject(); + } } @LayoutlibDelegate @@ -503,8 +505,10 @@ public Rasterizer_Delegate getRasterizer() { return; } - delegate.mTextScaleX = scaleX; - delegate.updateFontObject(); + if (delegate.mTextScaleX != scaleX) { + delegate.mTextScaleX = scaleX; + delegate.updateFontObject(); + } } @LayoutlibDelegate @@ -526,8 +530,10 @@ public Rasterizer_Delegate getRasterizer() { return; } - delegate.mTextSkewX = skewX; - delegate.updateFontObject(); + if (delegate.mTextSkewX != skewX) { + delegate.mTextSkewX = skewX; + delegate.updateFontObject(); + } } @LayoutlibDelegate @@ -897,9 +903,12 @@ public Rasterizer_Delegate getRasterizer() { return 0; } - delegate.mTypeface = Typeface_Delegate.getDelegate(typeface); - delegate.mNativeTypeface = typeface; - delegate.updateFontObject(); + Typeface_Delegate typefaceDelegate = Typeface_Delegate.getDelegate(typeface); + if (delegate.mTypeface != typefaceDelegate || delegate.mNativeTypeface != typeface) { + delegate.mTypeface = Typeface_Delegate.getDelegate(typeface); + delegate.mNativeTypeface = typeface; + delegate.updateFontObject(); + } return typeface; } @@ -1214,13 +1223,31 @@ private void set(Paint_Delegate paint) { mCap = paint.mCap; mJoin = paint.mJoin; mTextAlign = paint.mTextAlign; - mTypeface = paint.mTypeface; - mNativeTypeface = paint.mNativeTypeface; + + boolean needsFontUpdate = false; + if (mTypeface != paint.mTypeface || mNativeTypeface != paint.mNativeTypeface) { + mTypeface = paint.mTypeface; + mNativeTypeface = paint.mNativeTypeface; + needsFontUpdate = true; + } + + if (mTextSize != paint.mTextSize) { + mTextSize = paint.mTextSize; + needsFontUpdate = true; + } + + if (mTextScaleX != paint.mTextScaleX) { + mTextScaleX = paint.mTextScaleX; + needsFontUpdate = true; + } + + if (mTextSkewX != paint.mTextSkewX) { + mTextSkewX = paint.mTextSkewX; + needsFontUpdate = true; + } + mStrokeWidth = paint.mStrokeWidth; mStrokeMiter = paint.mStrokeMiter; - mTextSize = paint.mTextSize; - mTextScaleX = paint.mTextScaleX; - mTextSkewX = paint.mTextSkewX; mXfermode = paint.mXfermode; mColorFilter = paint.mColorFilter; mShader = paint.mShader; @@ -1228,7 +1255,10 @@ private void set(Paint_Delegate paint) { mMaskFilter = paint.mMaskFilter; mRasterizer = paint.mRasterizer; mHintingMode = paint.mHintingMode; - updateFontObject(); + + if (needsFontUpdate) { + updateFontObject(); + } } private void reset() { @@ -1264,10 +1294,18 @@ private void updateFontObject() { // Get the fonts from the TypeFace object. List fonts = mTypeface.getFonts(mFontVariant); + if (fonts.isEmpty()) { + mFonts = Collections.emptyList(); + return; + } + // create new font objects as well as FontMetrics, based on the current text size // and skew info. - ArrayList infoList = new ArrayList(fonts.size()); - for (Font font : fonts) { + int nFonts = fonts.size(); + ArrayList infoList = new ArrayList(nFonts); + //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation) + for (int i = 0; i < nFonts; i++) { + Font font = fonts.get(i); if (font == null) { // If the font is null, add null to infoList. When rendering the text, if this // null is reached, a warning will be logged. diff --git a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java new file mode 100644 index 0000000000000..dd2978f5c4146 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java @@ -0,0 +1,210 @@ +/* + * 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.graphics; + +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +/** + * Delegate implementing the native methods of {@link android.graphics.PathMeasure} + *

      + * Through the layoutlib_create tool, the original native methods of PathMeasure have been + * replaced by + * calls to methods of the same name in this delegate class. + *

      + * This class behaves like the original native implementation, but in Java, keeping previously + * native data into its own objects and mapping them to int that are sent back and forth between it + * and the original PathMeasure class. + * + * @see DelegateManager + */ +public final class PathMeasure_Delegate { + // ---- delegate manager ---- + private static final DelegateManager sManager = + new DelegateManager(PathMeasure_Delegate.class); + + // ---- delegate data ---- + // This governs how accurate the approximation of the Path is. + private static final float PRECISION = 0.002f; + + /** + * Array containing the path points components. There are three components for each point: + *

        + *
      • Fraction along the length of the path that the point resides
      • + *
      • The x coordinate of the point
      • + *
      • The y coordinate of the point
      • + *
      + */ + private float mPathPoints[]; + private long mNativePath; + + private PathMeasure_Delegate(long native_path, boolean forceClosed) { + mNativePath = native_path; + if (forceClosed && mNativePath != 0) { + // Copy the path and call close + mNativePath = Path_Delegate.init2(native_path); + Path_Delegate.native_close(mNativePath); + } + + mPathPoints = + mNativePath != 0 ? Path_Delegate.native_approximate(mNativePath, PRECISION) : null; + } + + @LayoutlibDelegate + /*package*/ static long native_create(long native_path, boolean forceClosed) { + return sManager.addNewDelegate(new PathMeasure_Delegate(native_path, forceClosed)); + } + + @LayoutlibDelegate + /*package*/ static void native_destroy(long native_instance) { + sManager.removeJavaReferenceFor(native_instance); + } + + @LayoutlibDelegate + /*package*/ static boolean native_getPosTan(long native_instance, float distance, float pos[], + float tan[]) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "PathMeasure.getPostTan is not supported.", null, null); + return false; + } + + @LayoutlibDelegate + /*package*/ static boolean native_getMatrix(long native_instance, float distance, long + native_matrix, int flags) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "PathMeasure.getMatrix is not supported.", null, null); + return false; + } + + @LayoutlibDelegate + /*package*/ static boolean native_nextContour(long native_instance) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "PathMeasure.nextContour is not supported.", null, null); + return false; + } + + @LayoutlibDelegate + /*package*/ static void native_setPath(long native_instance, long native_path, boolean + forceClosed) { + PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); + assert pathMeasure != null; + + if (forceClosed && native_path != 0) { + // Copy the path and call close + native_path = Path_Delegate.init2(native_path); + Path_Delegate.native_close(native_path); + } + pathMeasure.mNativePath = native_path; + pathMeasure.mPathPoints = Path_Delegate.native_approximate(native_path, PRECISION); + } + + @LayoutlibDelegate + /*package*/ static float native_getLength(long native_instance) { + PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); + assert pathMeasure != null; + + if (pathMeasure.mPathPoints == null) { + return 0; + } + + float length = 0; + int nPoints = pathMeasure.mPathPoints.length / 3; + for (int i = 1; i < nPoints; i++) { + length += Point2D.distance( + pathMeasure.mPathPoints[(i - 1) * 3 + 1], + pathMeasure.mPathPoints[(i - 1) * 3 + 2], + pathMeasure.mPathPoints[i*3 + 1], + pathMeasure.mPathPoints[i*3 + 2]); + } + + return length; + } + + @LayoutlibDelegate + /*package*/ static boolean native_isClosed(long native_instance) { + PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); + assert pathMeasure != null; + + Path_Delegate path = Path_Delegate.getDelegate(pathMeasure.mNativePath); + if (path == null) { + return false; + } + + PathIterator pathIterator = path.getJavaShape().getPathIterator(null); + + int type = 0; + float segment[] = new float[6]; + while (!pathIterator.isDone()) { + type = pathIterator.currentSegment(segment); + pathIterator.next(); + } + + // A path is a closed path if the last element is SEG_CLOSE + return type == PathIterator.SEG_CLOSE; + } + + @LayoutlibDelegate + /*package*/ static boolean native_getSegment(long native_instance, float startD, float stopD, + long native_dst_path, boolean startWithMoveTo) { + if (startD < 0) { + startD = 0; + } + + if (startD >= stopD) { + return false; + } + + PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance); + assert pathMeasure != null; + + if (pathMeasure.mPathPoints == null) { + return false; + } + + float accLength = 0; + boolean isZeroLength = true; // Whether the output has zero length or not + int nPoints = pathMeasure.mPathPoints.length / 3; + for (int i = 0; i < nPoints; i++) { + float x = pathMeasure.mPathPoints[i * 3 + 1]; + float y = pathMeasure.mPathPoints[i * 3 + 2]; + if (accLength >= startD && accLength <= stopD) { + if (startWithMoveTo) { + startWithMoveTo = false; + Path_Delegate.native_moveTo(native_dst_path, x, y); + } else { + isZeroLength = false; + Path_Delegate.native_lineTo(native_dst_path, x, y); + } + } + + if (i > 0) { + accLength += Point2D.distance( + pathMeasure.mPathPoints[(i - 1) * 3 + 1], + pathMeasure.mPathPoints[(i - 1) * 3 + 2], + pathMeasure.mPathPoints[i * 3 + 1], + pathMeasure.mPathPoints[i * 3 + 2]); + } + } + + return !isZeroLength; + } +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java index 3c9a062719e27..a2a53fef7f1f6 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java @@ -36,6 +36,7 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; +import java.util.ArrayList; /** * Delegate implementing the native methods of android.graphics.Path @@ -173,11 +174,8 @@ public void setPathIterator(PathIterator iterator) { @LayoutlibDelegate /*package*/ static boolean native_isEmpty(long nPath) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return true; - } + return pathDelegate == null || pathDelegate.isEmpty(); - return pathDelegate.isEmpty(); } @LayoutlibDelegate @@ -488,54 +486,44 @@ public void setPathIterator(PathIterator iterator) { @LayoutlibDelegate /*package*/ static float[] native_approximate(long nPath, float error) { - Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not fully supported", - null); Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return null; } - PathIterator pathIterator = pathDelegate.mPath.getPathIterator(null); - float[] tmp = new float[6]; - float[] coords = new float[6]; - boolean isFirstPoint = true; - while (!pathIterator.isDone()) { - int type = pathIterator.currentSegment(tmp); - switch (type) { - case PathIterator.SEG_MOVETO: - case PathIterator.SEG_LINETO: - store(tmp, coords, 1, isFirstPoint); - break; - case PathIterator.SEG_QUADTO: - store(tmp, coords, 2, isFirstPoint); - break; - case PathIterator.SEG_CUBICTO: - store(tmp, coords, 3, isFirstPoint); - break; - case PathIterator.SEG_CLOSE: - // No points returned. + // Get a FlatteningIterator + PathIterator iterator = pathDelegate.getJavaShape().getPathIterator(null, error); + + float segment[] = new float[6]; + float totalLength = 0; + ArrayList points = new ArrayList(); + Point2D.Float previousPoint = null; + while (!iterator.isDone()) { + int type = iterator.currentSegment(segment); + Point2D.Float currentPoint = new Point2D.Float(segment[0], segment[1]); + // MoveTo shouldn't affect the length + if (previousPoint != null && type != PathIterator.SEG_MOVETO) { + totalLength += currentPoint.distance(previousPoint); } - isFirstPoint = false; - pathIterator.next(); + previousPoint = currentPoint; + points.add(currentPoint); + iterator.next(); } - if (isFirstPoint) { - // No points found - return new float[0]; - } else { - return coords; - } - } - private static void store(float[] src, float[] dst, int count, boolean isFirst) { - if (isFirst) { - dst[0] = 0; // fraction - dst[1] = src[0]; // abscissa - dst[2] = src[1]; // ordinate - } - if (count > 1 || !isFirst) { - dst[3] = 1; - dst[4] = src[2 * count - 2]; - dst[5] = src[2 * count - 1]; + int nPoints = points.size(); + float[] result = new float[nPoints * 3]; + previousPoint = null; + for (int i = 0; i < nPoints; i++) { + Point2D.Float point = points.get(i); + float distance = previousPoint != null ? (float) previousPoint.distance(point) : .0f; + result[i * 3] = distance / totalLength; + result[i * 3 + 1] = point.x; + result[i * 3 + 2] = point.y; + + totalLength += distance; + previousPoint = point; } + + return result; } // ---- Private helper methods ---- @@ -735,6 +723,9 @@ private void rQuadTo(float dx1, float dy1, float dx2, float dy2) { */ private void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) { + if (isEmpty()) { + mPath.moveTo(0, 0); + } mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3); } diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java new file mode 100644 index 0000000000000..a3ad2aac7d3df --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java @@ -0,0 +1,73 @@ +/* + * 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.graphics.drawable; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +import android.graphics.Path; +import android.graphics.drawable.GradientDrawable.GradientState; + +import java.lang.reflect.Field; + +/** + * Delegate implementing the native methods of {@link GradientDrawable} + * + * Through the layoutlib_create tool, the original native methods of GradientDrawable have been + * replaced by calls to methods of the same name in this delegate class. + */ +public class GradientDrawable_Delegate { + + /** + * The ring can be built either by drawing full circles, or by drawing arcs in case the + * circle isn't complete. LayoutLib cannot handle drawing full circles (requires path + * subtraction). So, if we need to draw full circles, we switch to drawing 99% circle. + */ + @LayoutlibDelegate + /*package*/ static Path buildRing(GradientDrawable thisDrawable, GradientState st) { + boolean useLevel = st.mUseLevelForShape; + int level = thisDrawable.getLevel(); + // 10000 is the max level. See android.graphics.drawable.Drawable#getLevel() + float sweep = useLevel ? (360.0f * level / 10000.0f) : 360f; + Field mLevel = null; + if (sweep >= 360 || sweep <= -360) { + st.mUseLevelForShape = true; + // Use reflection to set the value of the field to prevent setting the drawable to + // dirty again. + try { + mLevel = Drawable.class.getDeclaredField("mLevel"); + mLevel.setAccessible(true); + mLevel.setInt(thisDrawable, 9999); // set to one less than max. + } catch (NoSuchFieldException e) { + // The field has been removed in a recent framework change. Fall back to old + // buggy behaviour. + } catch (IllegalAccessException e) { + // We've already set the field to be accessible. + assert false; + } + } + Path path = thisDrawable.buildRing_Original(st); + st.mUseLevelForShape = useLevel; + if (mLevel != null) { + try { + mLevel.setInt(thisDrawable, level); + } catch (IllegalAccessException e) { + assert false; + } + } + return path; + } +} diff --git a/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java b/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java index 49ee6426acae2..2e44a7770aae6 100644 --- a/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java +++ b/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java @@ -29,9 +29,6 @@ import android.view.ViewGroup; import android.widget.ListView; -import java.util.HashMap; -import java.util.Map; - /** * Delegate that provides implementation for native methods in {@link Preference} *

      @@ -59,9 +56,9 @@ public class Preference_Delegate { */ public static View inflatePreference(Context context, XmlPullParser parser, ViewGroup root) { PreferenceManager pm = new PreferenceManager(context); - PreferenceScreen ps = pm.getPreferenceScreen(); PreferenceInflater inflater = new BridgePreferenceInflater(context, pm); - ps = (PreferenceScreen) inflater.inflate(parser, ps, true); + PreferenceScreen ps = (PreferenceScreen) inflater.inflate(parser, null, true); + pm.setPreferences(ps); ListView preferenceView = createContainerView(context, root); ps.bind(preferenceView); return preferenceView; diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java index 5a595970e195d..44ce7311a95cf 100644 --- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java +++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java @@ -20,9 +20,10 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import java.io.File; +import java.nio.ByteBuffer; /** - * Delegate that overrides implementation for certain methods in {@link android.text.StaticLayout} + * Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator} *

      * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced * by calls to methods of the same name in this delegate class. @@ -38,7 +39,7 @@ public class Hyphenator_Delegate { return null; } - /*package*/ static long loadHyphenator(String patternData) { + /*package*/ static long loadHyphenator(ByteBuffer buf, int offset) { return sDelegateManager.addNewDelegate(new Hyphenator_Delegate()); } } diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java index 1b0ba5156acdb..65c0a07bbac4b 100644 --- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java +++ b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java @@ -13,6 +13,7 @@ import android.text.Primitive.PrimitiveType; import android.text.StaticLayout.LineBreaks; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -52,8 +53,8 @@ public class StaticLayout_Delegate { } @LayoutlibDelegate - /*package*/ static long nLoadHyphenator(String patternData) { - return Hyphenator_Delegate.loadHyphenator(patternData); + /*package*/ static long nLoadHyphenator(ByteBuffer buf, int offset) { + return Hyphenator_Delegate.loadHyphenator(buf, offset); } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java index 1e33e3ab2090c..723e8278bcc05 100644 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -23,6 +23,7 @@ import com.android.ide.common.rendering.api.ResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.MockView; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; import com.android.layoutlib.bridge.android.support.DrawerLayoutUtil; @@ -36,6 +37,7 @@ import android.annotation.NonNull; import android.content.Context; +import android.content.res.TypedArray; import android.util.AttributeSet; import java.io.File; @@ -54,6 +56,9 @@ public final class BridgeInflater extends LayoutInflater { private ResourceReference mResourceReference; private Map mOpenDrawerLayouts; + // Keep in sync with the same value in LayoutInflater. + private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme }; + /** * List of class prefixes which are tried first by default. *

      @@ -122,6 +127,9 @@ public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundEx if (view == null) { view = loadCustomView(name, attrs); } + } catch (InflateException e) { + // Don't catch the InflateException below as that results in hiding the real cause. + throw e; } catch (Exception e) { // Wrap the real exception in a ClassNotFoundException, so that the calling method // can deal with it. @@ -135,24 +143,45 @@ public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundEx @Override public View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, - boolean ignoreThemeAttrs) { + boolean ignoreThemeAttr) { View view; try { - view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttrs); + view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttr); } catch (InflateException e) { - // try to load the class from using the custom view loader - try { - view = loadCustomView(name, attrs); - } catch (Exception e2) { - // Wrap the real exception in an InflateException so that the calling - // method can deal with it. - InflateException exception = new InflateException(); - if (!e2.getClass().equals(ClassNotFoundException.class)) { - exception.initCause(e2); - } else { - exception.initCause(e); + // Creation of ContextThemeWrapper code is same as in the super method. + // Apply a theme wrapper, if allowed and one is specified. + if (!ignoreThemeAttr) { + final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME); + final int themeResId = ta.getResourceId(0, 0); + if (themeResId != 0) { + context = new ContextThemeWrapper(context, themeResId); + } + ta.recycle(); + } + if (!(e.getCause() instanceof ClassNotFoundException)) { + // There is some unknown inflation exception in inflating a View that was found. + view = new MockView(context, attrs); + ((MockView) view).setText(name); + Bridge.getLog().error(LayoutLog.TAG_BROKEN, e.getMessage(), e, null); + } else { + final Object lastContext = mConstructorArgs[0]; + mConstructorArgs[0] = context; + // try to load the class from using the custom view loader + try { + view = loadCustomView(name, attrs); + } catch (Exception e2) { + // Wrap the real exception in an InflateException so that the calling + // method can deal with it. + InflateException exception = new InflateException(); + if (!e2.getClass().equals(ClassNotFoundException.class)) { + exception.initCause(e2); + } else { + exception.initCause(e); + } + throw exception; + } finally { + mConstructorArgs[0] = lastContext; } - throw exception; } } @@ -188,7 +217,7 @@ public View inflate(int resource, ViewGroup root) { File f = new File(value.getValue()); if (f.isFile()) { try { - XmlPullParser parser = ParserFactory.create(f); + XmlPullParser parser = ParserFactory.create(f, true); BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( parser, bridgeContext, value.isFramework()); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java index 44a9aad55daaa..d392f213e5c8d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java @@ -17,39 +17,90 @@ package com.android.layoutlib.bridge; import android.content.Context; -import android.graphics.Canvas; import android.util.AttributeSet; import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; import android.widget.TextView; /** * Base class for mocked views. - * - * TODO: implement onDraw and draw a rectangle in a random color with the name of the class - * (or better the id of the view). + *

      + * FrameLayout with a single TextView. Doesn't allow adding any other views to itself. */ -public class MockView extends TextView { +public class MockView extends FrameLayout { + + private final TextView mView; + + public MockView(Context context) { + this(context, null); + } public MockView(Context context, AttributeSet attrs) { this(context, attrs, 0); } - public MockView(Context context, AttributeSet attrs, int defStyle) { - this(context, attrs, defStyle, 0); + public MockView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); } public MockView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - - setText(this.getClass().getSimpleName()); - setTextColor(0xFF000000); + mView = new TextView(context, attrs); + mView.setTextColor(0xFF000000); setGravity(Gravity.CENTER); + setText(getClass().getSimpleName()); + addView(mView); + setBackgroundColor(0xFF7F7F7F); + } + + // Only allow adding one TextView. + @Override + public void addView(View child) { + if (child == mView) { + super.addView(child); + } + } + + @Override + public void addView(View child, int index) { + if (child == mView) { + super.addView(child, index); + } } @Override - public void onDraw(Canvas canvas) { - canvas.drawARGB(0xFF, 0x7F, 0x7F, 0x7F); + public void addView(View child, int width, int height) { + if (child == mView) { + super.addView(child, width, height); + } + } + + @Override + public void addView(View child, ViewGroup.LayoutParams params) { + if (child == mView) { + super.addView(child, params); + } + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (child == mView) { + super.addView(child, index, params); + } + } + + // The following methods are called by the IDE via reflection, and should be considered part + // of the API. + // Historically, MockView used to be a textView and had these methods. Now, we simply delegate + // them to the contained textView. + + public void setText(CharSequence text) { + mView.setText(text); + } - super.onDraw(canvas); + public void setGravity(int gravity) { + mView.setGravity(gravity); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 6366424cb3f9d..2b83675bb7216 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -409,7 +409,7 @@ public Pair inflateView(ResourceReference resource, ViewGroup par pushParser(blockParser); return Pair.of( mBridgeInflater.inflate(blockParser, parent, attachToRoot), - true); + Boolean.TRUE); } finally { popParser(); } @@ -436,7 +436,7 @@ public Pair inflateView(ResourceReference resource, ViewGroup par // we need to create a pull parser around the layout XML file, and then // give that to our XmlBlockParser try { - XmlPullParser parser = ParserFactory.create(xml); + XmlPullParser parser = ParserFactory.create(xml, true); // set the resource ref to have correct view cookies mBridgeInflater.setResourceReference(resource); @@ -447,7 +447,7 @@ public Pair inflateView(ResourceReference resource, ViewGroup par pushParser(blockParser); return Pair.of( mBridgeInflater.inflate(blockParser, parent, attachToRoot), - false); + Boolean.FALSE); } finally { popParser(); } @@ -470,7 +470,7 @@ public Pair inflateView(ResourceReference resource, ViewGroup par resource.getName()), null); } - return Pair.of(null, false); + return Pair.of(null, Boolean.FALSE); } @SuppressWarnings("deprecation") diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java index 868c6d328e8ee..cdcf0ea1ca765 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java @@ -16,10 +16,13 @@ package com.android.layoutlib.bridge.bars; +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.ide.common.rendering.api.LayoutlibCallback; import com.android.ide.common.rendering.api.RenderResources; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.StyleResourceValue; +import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.resources.ResourceType; @@ -45,6 +48,8 @@ public class AppCompatActionBar extends BridgeActionBar { private Object mWindowDecorActionBar; private static final String WINDOW_ACTION_BAR_CLASS = "android.support.v7.internal.app.WindowDecorActionBar"; + // This is used on v23.1.1 and later. + private static final String WINDOW_ACTION_BAR_CLASS_NEW = "android.support.v7.app.WindowDecorActionBar"; private Class mWindowActionBarClass; /** @@ -70,14 +75,25 @@ public AppCompatActionBar(@NonNull BridgeContext context, @NonNull SessionParams try { Class[] constructorParams = {View.class}; Object[] constructorArgs = {getDecorContent()}; - mWindowDecorActionBar = params.getLayoutlibCallback().loadView(WINDOW_ACTION_BAR_CLASS, - constructorParams, constructorArgs); + LayoutlibCallback callback = params.getLayoutlibCallback(); + + // Check if the old action bar class is present. + String actionBarClass = WINDOW_ACTION_BAR_CLASS; + try { + callback.findClass(actionBarClass); + } catch (ClassNotFoundException expected) { + // Failed to find the old class, use the newer one. + actionBarClass = WINDOW_ACTION_BAR_CLASS_NEW; + } + mWindowDecorActionBar = callback.loadView(actionBarClass, + constructorParams, constructorArgs); mWindowActionBarClass = mWindowDecorActionBar == null ? null : mWindowDecorActionBar.getClass(); setupActionBar(); } catch (Exception e) { - e.printStackTrace(); + Bridge.getLog().warning(LayoutLog.TAG_BROKEN, + "Failed to load AppCompat ActionBar with unknown error.", e); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index b76ec1707fcc9..a6e5fb841bff8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -116,11 +116,11 @@ protected void loadIcon(int index, String iconName, Density density, boolean isR density = iconLoader.getDensity(); String path = iconLoader.getPath(); // look for a cached bitmap - Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/); + Bitmap bitmap = Bridge.getCachedBitmap(path, Boolean.TRUE /*isFramework*/); if (bitmap == null) { try { bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density); - Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/); + Bridge.setCachedBitmap(path, bitmap, Boolean.TRUE /*isFramework*/); } catch (IOException e) { return; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java new file mode 100644 index 0000000000000..71e7fd2c5eea6 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.layoutlib.bridge.impl; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.annotation.Nullable; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * A wrapper around XmlPullParser that can peek forward to inspect if the file is a data-binding + * layout and some parts need to be stripped. + */ +public class LayoutParserWrapper implements XmlPullParser { + + // Data binding constants. + private static final String TAG_LAYOUT = "layout"; + private static final String TAG_DATA = "data"; + private static final String DEFAULT = "default="; + + private final XmlPullParser mDelegate; + + // Storage for peeked values. + private boolean mPeeked; + private int mEventType; + private int mDepth; + private int mNext; + private List mAttributes; + private String mText; + private String mName; + + // Used to end the document before the actual parser ends. + private int mFinalDepth = -1; + private boolean mEndNow; + + public LayoutParserWrapper(XmlPullParser delegate) { + mDelegate = delegate; + } + + public LayoutParserWrapper peekTillLayoutStart() throws IOException, XmlPullParserException { + final int STATE_LAYOUT_NOT_STARTED = 0; // tag not encountered yet. + final int STATE_ROOT_NOT_STARTED = 1; // the main view root not found yet. + final int STATE_INSIDE_DATA = 2; // START_TAG for found, but not END_TAG. + + int state = STATE_LAYOUT_NOT_STARTED; + int dataDepth = -1; // depth of the tag. Should be two. + while (true) { + int peekNext = peekNext(); + switch (peekNext) { + case START_TAG: + if (state == STATE_LAYOUT_NOT_STARTED) { + if (mName.equals(TAG_LAYOUT)) { + state = STATE_ROOT_NOT_STARTED; + } else { + return this; // no layout tag in the file. + } + } else if (state == STATE_ROOT_NOT_STARTED) { + if (mName.equals(TAG_DATA)) { + state = STATE_INSIDE_DATA; + dataDepth = mDepth; + } else { + mFinalDepth = mDepth; + return this; + } + } + break; + case END_TAG: + if (state == STATE_INSIDE_DATA) { + if (mDepth <= dataDepth) { + state = STATE_ROOT_NOT_STARTED; + } + } + break; + case END_DOCUMENT: + // No layout start found. + return this; + } + // consume the peeked tag. + next(); + } + } + + private int peekNext() throws IOException, XmlPullParserException { + if (mPeeked) { + return mNext; + } + mEventType = mDelegate.getEventType(); + mNext = mDelegate.next(); + if (mEventType == START_TAG) { + int count = mDelegate.getAttributeCount(); + mAttributes = count > 0 ? new ArrayList(count) : + Collections.emptyList(); + for (int i = 0; i < count; i++) { + mAttributes.add(new Attribute(mDelegate.getAttributeNamespace(i), + mDelegate.getAttributeName(i), mDelegate.getAttributeValue(i))); + } + } + mDepth = mDelegate.getDepth(); + mText = mDelegate.getText(); + mName = mDelegate.getName(); + mPeeked = true; + return mNext; + } + + private void reset() { + mAttributes = null; + mText = null; + mName = null; + mPeeked = false; + } + + @Override + public int next() throws XmlPullParserException, IOException { + int returnValue; + int depth; + if (mPeeked) { + returnValue = mNext; + depth = mDepth; + reset(); + } else if (mEndNow) { + return END_DOCUMENT; + } else { + returnValue = mDelegate.next(); + depth = getDepth(); + } + if (returnValue == END_TAG && depth <= mFinalDepth) { + mEndNow = true; + } + return returnValue; + } + + @Override + public int getEventType() throws XmlPullParserException { + return mPeeked ? mEventType : mDelegate.getEventType(); + } + + @Override + public int getDepth() { + return mPeeked ? mDepth : mDelegate.getDepth(); + } + + @Override + public String getName() { + return mPeeked ? mName : mDelegate.getName(); + } + + @Override + public String getText() { + return mPeeked ? mText : mDelegate.getText(); + } + + @Override + public String getAttributeValue(@Nullable String namespace, String name) { + String returnValue = null; + if (mPeeked) { + if (mAttributes == null) { + if (mEventType != START_TAG) { + throw new IndexOutOfBoundsException("getAttributeValue() called when not at START_TAG."); + } else { + return null; + } + } else { + for (Attribute attribute : mAttributes) { + //noinspection StringEquality for nullness check. + if (attribute.name.equals(name) && (attribute.namespace == namespace || + attribute.namespace != null && attribute.namespace.equals(namespace))) { + returnValue = attribute.value; + break; + } + } + } + } else { + returnValue = mDelegate.getAttributeValue(namespace, name); + } + // Check if the value is bound via data-binding, if yes get the default value. + if (returnValue != null && mFinalDepth >= 0 && returnValue.startsWith("@{")) { + // TODO: Improve the detection of default keyword. + int i = returnValue.lastIndexOf(DEFAULT); + return i > 0 ? returnValue.substring(i + DEFAULT.length(), returnValue.length() - 1) + : null; + } + return returnValue; + } + + private static class Attribute { + @Nullable + public final String namespace; + public final String name; + public final String value; + + public Attribute(@Nullable String namespace, String name, String value) { + this.namespace = namespace; + this.name = name; + this.value = value; + } + } + + // Not affected by peeking. + + @Override + public void setFeature(String s, boolean b) throws XmlPullParserException { + mDelegate.setFeature(s, b); + } + + @Override + public void setProperty(String s, Object o) throws XmlPullParserException { + mDelegate.setProperty(s, o); + } + + @Override + public void setInput(InputStream inputStream, String s) throws XmlPullParserException { + mDelegate.setInput(inputStream, s); + } + + @Override + public void setInput(Reader reader) throws XmlPullParserException { + mDelegate.setInput(reader); + } + + @Override + public String getInputEncoding() { + return mDelegate.getInputEncoding(); + } + + @Override + public String getNamespace(String s) { + return mDelegate.getNamespace(s); + } + + @Override + public String getPositionDescription() { + return mDelegate.getPositionDescription(); + } + + @Override + public int getLineNumber() { + return mDelegate.getLineNumber(); + } + + @Override + public String getNamespace() { + return mDelegate.getNamespace(); + } + + @Override + public int getColumnNumber() { + return mDelegate.getColumnNumber(); + } + + // -- We don't care much about the methods that follow. + + @Override + public void require(int i, String s, String s1) throws XmlPullParserException, IOException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public boolean getFeature(String s) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public void defineEntityReplacementText(String s, String s1) throws XmlPullParserException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public Object getProperty(String s) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public int nextToken() throws XmlPullParserException, IOException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public int getNamespaceCount(int i) throws XmlPullParserException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getNamespacePrefix(int i) throws XmlPullParserException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getNamespaceUri(int i) throws XmlPullParserException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public boolean isWhitespace() throws XmlPullParserException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public char[] getTextCharacters(int[] ints) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getPrefix() { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public boolean isEmptyElementTag() throws XmlPullParserException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public int getAttributeCount() { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getAttributeNamespace(int i) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getAttributeName(int i) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getAttributePrefix(int i) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getAttributeType(int i) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public boolean isAttributeDefault(int i) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String getAttributeValue(int i) { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public String nextText() throws XmlPullParserException, IOException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } + + @Override + public int nextTag() throws XmlPullParserException, IOException { + throw new UnsupportedOperationException("Only few parser methods are supported."); + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java index 6e67f593aa531..e273b2cd75cc9 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java @@ -53,24 +53,35 @@ public static void setParserFactory( @NonNull public static XmlPullParser create(@NonNull File f) throws XmlPullParserException, FileNotFoundException { - InputStream stream = new FileInputStream(f); - return create(stream, f.getName(), f.length()); + return create(f, false); } + public static XmlPullParser create(@NonNull File f, boolean isLayout) + throws XmlPullParserException, FileNotFoundException { + InputStream stream = new FileInputStream(f); + return create(stream, f.getName(), f.length(), isLayout); + } @NonNull public static XmlPullParser create(@NonNull InputStream stream, @Nullable String name) throws XmlPullParserException { - return create(stream, name, -1); + return create(stream, name, -1, false); } @NonNull private static XmlPullParser create(@NonNull InputStream stream, @Nullable String name, - long size) throws XmlPullParserException { + long size, boolean isLayout) throws XmlPullParserException { XmlPullParser parser = instantiateParser(name); stream = readAndClose(stream, name, size); parser.setInput(stream, ENCODING); + if (isLayout) { + try { + return new LayoutParserWrapper(parser).peekTillLayoutStart(); + } catch (IOException e) { + throw new XmlPullParserException(null, parser, e); + } + } return parser; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java index 95880355ada92..80d7c68bcf06b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java @@ -21,6 +21,7 @@ import android.graphics.BlendComposite; import android.graphics.BlendComposite.BlendingMode; +import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter_Delegate; import android.graphics.PorterDuffXfermode_Delegate; @@ -34,6 +35,8 @@ */ public final class PorterDuffUtility { + private static final int MODES_COUNT = Mode.values().length; + // Make the class non-instantiable. private PorterDuffUtility() { } @@ -43,12 +46,11 @@ private PorterDuffUtility() { * {@link Mode#SRC_OVER} for invalid modes. */ public static Mode getPorterDuffMode(int porterDuffMode) { - Mode[] values = Mode.values(); - if (porterDuffMode >= 0 && porterDuffMode < values.length) { - return values[porterDuffMode]; + if (porterDuffMode >= 0 && porterDuffMode < MODES_COUNT) { + return PorterDuff.intToMode(porterDuffMode); } Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null /*data*/); + String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null); assert false; return Mode.SRC_OVER; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index ac7c4097e271f..0ffa357331800 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -1051,11 +1051,7 @@ private void handleScrolling(View view) { } if (scrollPos != 0) { view.scrollBy(0, scrollPos); - } else { - view.scrollBy(0, scrollPos); } - } else { - view.scrollBy(0, scrollPos); } if (!(view instanceof ViewGroup)) { diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/impl/LayoutParserWrapperTest.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/impl/LayoutParserWrapperTest.java new file mode 100644 index 0000000000000..2c338622301b8 --- /dev/null +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/impl/LayoutParserWrapperTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.layoutlib.bridge.impl; + +import org.junit.Test; +import org.kxml2.io.KXmlParser; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.StringReader; + +import static com.android.SdkConstants.NS_RESOURCES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; +import static org.xmlpull.v1.XmlPullParser.END_TAG; +import static org.xmlpull.v1.XmlPullParser.START_TAG; + + +public class LayoutParserWrapperTest { + @Test + @SuppressWarnings("StatementWithEmptyBody") // some for loops need to be empty statements. + public void testDataBindingLayout() throws Exception { + LayoutParserWrapper parser = getParserFromString(sDataBindingLayout); + parser.peekTillLayoutStart(); + assertEquals("Expected START_TAG", START_TAG, parser.next()); + assertEquals("RelativeLayout", parser.getName()); + for (int next = parser.next(); next != START_TAG && next != END_DOCUMENT; + next = parser.next()); + assertEquals("Expected START_TAG", START_TAG, parser.getEventType()); + assertEquals("TextView", parser.getName()); + assertEquals("layout_width incorrect for first text view.", "wrap_content", + parser.getAttributeValue(NS_RESOURCES, "layout_width")); + // Ensure that data-binding part is stripped. + assertEquals("Bound attribute android:text incorrect", "World", + parser.getAttributeValue(NS_RESOURCES, "text")); + assertEquals("resource attribute 'id' for first text view incorrect.", "@+id/first", + parser.getAttributeValue(NS_RESOURCES, "id")); + for (int next = parser.next(); + (next != END_TAG || !"RelativeLayout".equals(parser.getName())) && next != END_DOCUMENT; + next = parser.next()); + assertNotSame("Unexpected end of document", END_DOCUMENT, parser.getEventType()); + assertEquals("Document didn't end when expected.", END_DOCUMENT, parser.next()); + } + + @Test + @SuppressWarnings("StatementWithEmptyBody") + public void testNonDataBindingLayout() throws Exception { + LayoutParserWrapper parser = getParserFromString(sNonDataBindingLayout); + parser.peekTillLayoutStart(); + assertEquals("Expected START_TAG", START_TAG, parser.next()); + assertEquals("RelativeLayout", parser.getName()); + for (int next = parser.next(); next != START_TAG && next != END_DOCUMENT; + next = parser.next()); + assertEquals("Expected START_TAG", START_TAG, parser.getEventType()); + assertEquals("TextView", parser.getName()); + assertEquals("layout_width incorrect for first text view.", "wrap_content", + parser.getAttributeValue(NS_RESOURCES, "layout_width")); + // Ensure that value isn't modified. + assertEquals("Bound attribute android:text incorrect", "@{user.firstName,default=World}", + parser.getAttributeValue(NS_RESOURCES, "text")); + assertEquals("resource attribute 'id' for first text view incorrect.", "@+id/first", + parser.getAttributeValue(NS_RESOURCES, "id")); + for (int next = parser.next(); + (next != END_TAG || !"RelativeLayout".equals(parser.getName())) && next != END_DOCUMENT; + next = parser.next()); + assertNotSame("Unexpected end of document", END_DOCUMENT, parser.getEventType()); + assertEquals("Document didn't end when expected.", END_DOCUMENT, parser.next()); + } + + private static LayoutParserWrapper getParserFromString(String layoutContent) throws + XmlPullParserException { + XmlPullParser parser = new KXmlParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + parser.setInput(new StringReader(layoutContent)); + return new LayoutParserWrapper(parser); + } + + private static final String sDataBindingLayout = + //language=XML + "\n" + + "\n" + + "\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + "\n" + + " \n" + + "\n" + + " \n" + + "\n" + + " \n" + + " \n" + + ""; + + private static final String sNonDataBindingLayout = + //language=XML + "\n" + + "\n" + + " \n" + + "\n" + + " \n" + + "\n" + + " \n" + + ""; +} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 484240f49b200..c9bc62ec3bcb1 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -157,7 +157,6 @@ public Map getInjectedMethodsMap() { * The list of methods to rewrite as delegates. */ public final static String[] DELEGATE_METHODS = new String[] { - "android.animation.AnimatorInflater#loadAnimator", // TODO: remove when Path.approximate() is supported. "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;", "android.content.res.Resources$Theme#obtainStyledAttributes", "android.content.res.Resources$Theme#resolveAttribute", @@ -167,6 +166,7 @@ public Map getInjectedMethodsMap() { "android.content.res.TypedArray#getValueAt", "android.content.res.TypedArray#obtain", "android.graphics.BitmapFactory#finishDecode", + "android.graphics.drawable.GradientDrawable#buildRing", "android.graphics.Typeface#getSystemFontConfigLocation", "android.os.Handler#sendMessageAtTime", "android.os.HandlerThread#run", @@ -235,6 +235,7 @@ public Map getInjectedMethodsMap() { "android.graphics.Path", "android.graphics.PathDashPathEffect", "android.graphics.PathEffect", + "android.graphics.PathMeasure", "android.graphics.PixelXorXfermode", "android.graphics.PorterDuffColorFilter", "android.graphics.PorterDuffXfermode", diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java index ae4a57d8eea4e..7ef75662aad4f 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java @@ -17,6 +17,7 @@ package com.android.tools.layoutlib.create; import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -40,6 +41,7 @@ public class DelegateClassAdapter extends ClassVisitor { private final String mClassName; private final Set mDelegateMethods; private final Log mLog; + private boolean mIsStaticInnerClass; /** * Creates a new {@link DelegateClassAdapter} that can transform some methods @@ -62,16 +64,30 @@ public DelegateClassAdapter(Log log, mLog = log; mClassName = className; mDelegateMethods = delegateMethods; + // If this is an inner class, by default, we assume it's static. If it's not we will detect + // by looking at the fields (see visitField) + mIsStaticInnerClass = className.contains("$"); } //---------------------------------- // Methods from the ClassAdapter + @Override + public FieldVisitor visitField(int access, String name, String desc, String signature, + Object value) { + if (mIsStaticInnerClass && "this$0".equals(name)) { + // Having a "this$0" field, proves that this class is not a static inner class. + mIsStaticInnerClass = false; + } + + return super.visitField(access, name, desc, signature, value); + } + @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; + boolean isStaticMethod = (access & Opcodes.ACC_STATIC) != 0; boolean isNative = (access & Opcodes.ACC_NATIVE) != 0; boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) || @@ -96,7 +112,8 @@ public MethodVisitor visitMethod(int access, String name, String desc, MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions); DelegateMethodAdapter a = new DelegateMethodAdapter( - mLog, null, mwDelegate, mClassName, name, desc, isStatic); + mLog, null, mwDelegate, mClassName, name, desc, isStaticMethod, + mIsStaticInnerClass); // A native has no code to visit, so we need to generate it directly. a.generateDelegateCode(); @@ -120,6 +137,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, desc, signature, exceptions); return new DelegateMethodAdapter( - mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStatic); + mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStaticMethod, + mIsStaticInnerClass); } } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java index 12690db547a98..cca9e574b7ea2 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java @@ -85,6 +85,8 @@ class DelegateMethodAdapter extends MethodVisitor { private String mDesc; /** True if the original method is static. */ private final boolean mIsStatic; + /** True if the method is contained in a static inner class */ + private final boolean mIsStaticInnerClass; /** The internal class name (e.g. com/android/SomeClass$InnerClass.) */ private final String mClassName; /** The method name. */ @@ -120,7 +122,8 @@ public DelegateMethodAdapter(Log log, String className, String methodName, String desc, - boolean isStatic) { + boolean isStatic, + boolean isStaticClass) { super(Opcodes.ASM4); mLog = log; mOrgWriter = mvOriginal; @@ -129,6 +132,7 @@ public DelegateMethodAdapter(Log log, mMethodName = methodName; mDesc = desc; mIsStatic = isStatic; + mIsStaticInnerClass = isStaticClass; } /** @@ -206,7 +210,7 @@ public void generateDelegateCode() { // by the 'this' of any outer class, if any. if (!mIsStatic) { - if (outerType != null) { + if (outerType != null && !mIsStaticInnerClass) { // The first-level inner class has a package-protected member called 'this$0' // that points to the outer class. diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java index 648cea430de22..e37a09b348b89 100644 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java +++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java @@ -27,6 +27,7 @@ import com.android.tools.layoutlib.create.dataclass.ClassWithNative; import com.android.tools.layoutlib.create.dataclass.OuterClass; import com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass; +import com.android.tools.layoutlib.create.dataclass.OuterClass.StaticInnerClass; import org.junit.Before; import org.junit.Test; @@ -56,6 +57,8 @@ public class DelegateClassAdapterTest { private static final String OUTER_CLASS_NAME = OuterClass.class.getCanonicalName(); private static final String INNER_CLASS_NAME = OuterClass.class.getCanonicalName() + "$" + InnerClass.class.getSimpleName(); + private static final String STATIC_INNER_CLASS_NAME = + OuterClass.class.getCanonicalName() + "$" + StaticInnerClass.class.getSimpleName(); @Before public void setUp() throws Exception { @@ -294,6 +297,61 @@ public void testModifiedInstance() throws Exception { } } + @Test + public void testDelegateStaticInner() throws Throwable { + // We'll delegate the "get" method of both the inner and outer class. + HashSet delegateMethods = new HashSet(); + delegateMethods.add("get"); + + // Generate the delegate for the outer class. + ClassWriter cwOuter = new ClassWriter(0 /*flags*/); + String outerClassName = OUTER_CLASS_NAME.replace('.', '/'); + DelegateClassAdapter cvOuter = new DelegateClassAdapter( + mLog, cwOuter, outerClassName, delegateMethods); + ClassReader cr = new ClassReader(OUTER_CLASS_NAME); + cr.accept(cvOuter, 0 /* flags */); + + // Generate the delegate for the static inner class. + ClassWriter cwInner = new ClassWriter(0 /*flags*/); + String innerClassName = STATIC_INNER_CLASS_NAME.replace('.', '/'); + DelegateClassAdapter cvInner = new DelegateClassAdapter( + mLog, cwInner, innerClassName, delegateMethods); + cr = new ClassReader(STATIC_INNER_CLASS_NAME); + cr.accept(cvInner, 0 /* flags */); + + // Load the generated classes in a different class loader and try them + ClassLoader2 cl2 = null; + try { + cl2 = new ClassLoader2() { + @Override + public void testModifiedInstance() throws Exception { + + // Check the outer class + Class outerClazz2 = loadClass(OUTER_CLASS_NAME); + Object o2 = outerClazz2.newInstance(); + assertNotNull(o2); + + // Check the inner class. Since it's not a static inner class, we need + // to use the hidden constructor that takes the outer class as first parameter. + Class innerClazz2 = loadClass(STATIC_INNER_CLASS_NAME); + Constructor innerCons = innerClazz2.getConstructor(); + Object i2 = innerCons.newInstance(); + assertNotNull(i2); + + // The original StaticInner.get returns 100+10+20, + // but the delegate makes it return 6+10+20 + assertEquals(6+10+20, callGet(i2, 10, 20)); + assertEquals(100+10+20, callGet_Original(i2, 10, 20)); + } + }; + cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray()); + cl2.add(STATIC_INNER_CLASS_NAME, cwInner.toByteArray()); + cl2.testModifiedInstance(); + } catch (Throwable t) { + throw dumpGeneratedClass(t, cl2); + } + } + //------- /** diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java index f083e76d995c6..6dfb81662e405 100644 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java +++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java @@ -45,6 +45,16 @@ public int get(int a, long b) { } } + public static class StaticInnerClass { + public StaticInnerClass() { + } + + // StaticInnerClass.get returns 100 + a + b + public int get(int a, long b) { + return 100 + a + (int) b; + } + } + @SuppressWarnings("unused") private String privateMethod() { return "outerPrivateMethod"; diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_StaticInnerClass_Delegate.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_StaticInnerClass_Delegate.java new file mode 100644 index 0000000000000..a29439ee3feeb --- /dev/null +++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_StaticInnerClass_Delegate.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.tools.layoutlib.create.dataclass; + +import com.android.tools.layoutlib.create.DelegateClassAdapterTest; +import com.android.tools.layoutlib.create.dataclass.OuterClass.StaticInnerClass; + +/** + * Used by {@link DelegateClassAdapterTest}. + */ +public class OuterClass_StaticInnerClass_Delegate { + // The delegate override of Inner.get return 6 + a + b + public static int get(StaticInnerClass inner, int a, long b) { + return 6 + a + (int) b; + } +} diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk index d9ddf08862b3a..54f0a1fad2906 100644 --- a/tools/split-select/Android.mk +++ b/tools/split-select/Android.mk @@ -48,8 +48,8 @@ hostStaticLibs := \ libaapt \ libandroidfw \ libpng \ - liblog \ libutils \ + liblog \ libcutils \ libexpat \ libziparchive-host \ diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 9d4f6e20b3657..35d6d9ee481af 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -456,6 +456,13 @@ private Status() { } */ public int userApproved = USER_UNSPECIFIED; + /** + * @hide + * Inactivity time before wifi tethering is disabled. Here inactivity means no clients + * connected. A value of 0 means the AP will not be disabled when there is no activity + */ + public long wifiApInactivityTimeout; + /** The Below RSSI thresholds are used to configure AutoJoin * - GOOD/LOW/BAD thresholds are used so as to calculate link score * - UNWANTED_SOFT are used by the blacklisting logic so as to handle @@ -1556,6 +1563,7 @@ public WifiConfiguration(WifiConfiguration source) { creationTime = source.creationTime; updateTime = source.updateTime; SIMNum = source.SIMNum; + wifiApInactivityTimeout = source.wifiApInactivityTimeout; } } @@ -1638,6 +1646,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeInt(numNoInternetAccessReports); dest.writeInt(noInternetAccessExpected ? 1 : 0); dest.writeInt(SIMNum); + dest.writeLong(wifiApInactivityTimeout); } /** Implement the Parcelable interface {@hide} */ @@ -1717,6 +1726,7 @@ public WifiConfiguration createFromParcel(Parcel in) { config.numNoInternetAccessReports = in.readInt(); config.noInternetAccessExpected = in.readInt() != 0; config.SIMNum = in.readInt(); + config.wifiApInactivityTimeout = in.readLong(); return config; } diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 59b22bda08335..a33775579bf30 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -768,7 +768,9 @@ public void setFieldValue(String key, String value) { public String toString() { StringBuffer sb = new StringBuffer(); for (String key : mFields.keySet()) { - sb.append(key).append(" ").append(mFields.get(key)).append("\n"); + // Don't display password in toString(). + String value = PASSWORD_KEY.equals(key) ? "" : mFields.get(key); + sb.append(key).append(" ").append(value).append("\n"); } return sb.toString(); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 056ede1ae2473..a832c934daaa8 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -187,6 +187,14 @@ public class WifiManager { */ public static final int WIFI_STATE_UNKNOWN = 4; + /** + * Wi-Fi is in failed state. This state will occur when load driver failed or start + * supplicant failed. + * + * @hide + */ + public static final int WIFI_STATE_FAILED = 5; + /** * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, * enabling, disabling, or failed.

    + * Formula defined + * here. */ - private static double calculateContrast(int foreground, int background) { + public static double calculateContrast(int foreground, int background) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent"); } @@ -81,18 +99,23 @@ private static double calculateContrast(int foreground, int background) { } /** - * Finds the minimum alpha value which can be applied to {@code foreground} so that is has a - * contrast value of at least {@code minContrastRatio} when compared to background. + * Calculates the minimum alpha value which can be applied to {@code foreground} so that would + * have a contrast value of at least {@code minContrastRatio} when compared to + * {@code background}. * - * @return the alpha value in the range 0-255. + * @param foreground the foreground color. + * @param background the background color. Should be opaque. + * @param minContrastRatio the minimum contrast ratio. + * @return the alpha value in the range 0-255, or -1 if no value could be calculated. */ - private static int findMinimumAlpha(int foreground, int background, double minContrastRatio) { + public static int calculateMinimumAlpha(int foreground, int background, + float minContrastRatio) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent"); } // First lets check that a fully opaque foreground has sufficient contrast - int testForeground = modifyAlpha(foreground, 255); + int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { // Fully opaque foreground does not have sufficient contrast, return error @@ -108,7 +131,7 @@ private static int findMinimumAlpha(int foreground, int background, double minCo (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { final int testAlpha = (minAlpha + maxAlpha) / 2; - testForeground = modifyAlpha(foreground, testAlpha); + testForeground = setAlphaComponent(foreground, testAlpha); testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { @@ -124,19 +147,20 @@ private static int findMinimumAlpha(int foreground, int background, double minCo return maxAlpha; } - static int getTextColorForBackground(int backgroundColor, int textColor, float minContrastRatio) { - final int minAlpha = ColorUtils - .findMinimumAlpha(textColor, backgroundColor, minContrastRatio); - - if (minAlpha >= 0) { - return ColorUtils.modifyAlpha(textColor, minAlpha); - } - - // Didn't find an opacity which provided enough contrast - return -1; - } - - static void RGBtoHSL(int r, int g, int b, float[] hsl) { + /** + * Convert RGB components to HSL (hue-saturation-lightness). + *