diff options
291 files changed, 9010 insertions, 4020 deletions
diff --git a/api/current.txt b/api/current.txt index 7c78c06..4997ae6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -207,6 +207,7 @@ package android { field public static final int actionModeCutDrawable = 16843537; // 0x1010311 field public static final int actionModePasteDrawable = 16843539; // 0x1010313 field public static final int actionModeSelectAllDrawable = 16843647; // 0x101037f + field public static final int actionModeStyle = 16843688; // 0x10103a8 field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6 field public static final int actionProviderClass = 16843677; // 0x101039d field public static final int actionViewClass = 16843516; // 0x10102fc @@ -1823,6 +1824,7 @@ package android.accessibilityservice { method public static java.lang.String feedbackTypeToString(int); method public static java.lang.String flagToString(int); method public boolean getCanRetrieveWindowContent(); + method public java.lang.String getDescription(); method public java.lang.String getId(); method public android.content.pm.ResolveInfo getResolveInfo(); method public java.lang.String getSettingsActivityName(); @@ -13927,6 +13929,10 @@ package android.os { public static class Debug.MemoryInfo implements android.os.Parcelable { ctor public Debug.MemoryInfo(); method public int describeContents(); + method public static java.lang.String getOtherLabel(int); + method public int getOtherPrivateDirty(int); + method public int getOtherPss(int); + method public int getOtherSharedDirty(int); method public int getTotalPrivateDirty(); method public int getTotalPss(); method public int getTotalSharedDirty(); @@ -15869,6 +15875,7 @@ package android.provider { method public static android.net.Uri getLookupUri(long, java.lang.String); method public static android.net.Uri lookupContact(android.content.ContentResolver, android.net.Uri); method public static void markAsContacted(android.content.ContentResolver, long); + method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean); method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri); field public static final android.net.Uri CONTENT_FILTER_URI; field public static final android.net.Uri CONTENT_GROUP_URI; @@ -16697,6 +16704,7 @@ package android.provider { field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype"; field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname"; field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version"; + field public static final java.lang.String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested"; field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country"; field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang"; field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch"; @@ -20487,6 +20495,14 @@ package android.util { ctor public Base64OutputStream(java.io.OutputStream, int); } + public final deprecated class Config { + field public static final deprecated boolean DEBUG = false; + field public static final deprecated boolean LOGD = true; + field public static final deprecated boolean LOGV = false; + field public static final deprecated boolean PROFILE = false; + field public static final deprecated boolean RELEASE = true; + } + public class DebugUtils { method public static boolean isObjectSelected(java.lang.Object); } @@ -20726,11 +20742,12 @@ package android.util { method public void set(T, V); } - public class SparseArray { + public class SparseArray implements java.lang.Cloneable { ctor public SparseArray(); ctor public SparseArray(int); method public void append(int, E); method public void clear(); + method public android.util.SparseArray<E> clone(); method public void delete(int); method public E get(int); method public E get(int, E); @@ -20745,11 +20762,12 @@ package android.util { method public E valueAt(int); } - public class SparseBooleanArray { + public class SparseBooleanArray implements java.lang.Cloneable { ctor public SparseBooleanArray(); ctor public SparseBooleanArray(int); method public void append(int, boolean); method public void clear(); + method public android.util.SparseBooleanArray clone(); method public void delete(int); method public boolean get(int); method public boolean get(int, boolean); @@ -20761,11 +20779,12 @@ package android.util { method public boolean valueAt(int); } - public class SparseIntArray { + public class SparseIntArray implements java.lang.Cloneable { ctor public SparseIntArray(); ctor public SparseIntArray(int); method public void append(int, int); method public void clear(); + method public android.util.SparseIntArray clone(); method public void delete(int); method public int get(int); method public int get(int, int); @@ -20912,11 +20931,13 @@ package android.view { method public abstract android.view.Menu getMenu(); method public abstract android.view.MenuInflater getMenuInflater(); method public abstract java.lang.CharSequence getSubtitle(); + method public java.lang.Object getTag(); method public abstract java.lang.CharSequence getTitle(); method public abstract void invalidate(); method public abstract void setCustomView(android.view.View); method public abstract void setSubtitle(java.lang.CharSequence); method public abstract void setSubtitle(int); + method public void setTag(java.lang.Object); method public abstract void setTitle(java.lang.CharSequence); method public abstract void setTitle(int); } @@ -22029,9 +22050,12 @@ package android.view { method public android.graphics.SurfaceTexture getSurfaceTexture(); method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener(); method public boolean isAvailable(); + method public android.graphics.Canvas lockCanvas(); + method public android.graphics.Canvas lockCanvas(android.graphics.Rect); method protected final void onDraw(android.graphics.Canvas); method public void setOpaque(boolean); method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener); + method public void unlockCanvasAndPost(android.graphics.Canvas); } public static abstract interface TextureView.SurfaceTextureListener { @@ -23260,6 +23284,7 @@ package android.view.accessibility { method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); method public void interrupt(); method public boolean isEnabled(); + method public boolean isTouchExplorationEnabled(); method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent); } @@ -23296,6 +23321,7 @@ package android.view.accessibility { method public boolean isSelected(); method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View); method public static android.view.accessibility.AccessibilityNodeInfo obtain(); + method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo); method public boolean performAction(int); method public void recycle(); method public void setBoundsInParent(android.graphics.Rect); @@ -23882,7 +23908,7 @@ package android.view.inputmethod { method public boolean isWatchingCursor(android.view.View); method public void restartInput(android.view.View); method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle); - method public boolean setAdditionalInputMethodSubtypes(android.os.IBinder, android.view.inputmethod.InputMethodSubtype[]); + method public boolean setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]); method public boolean setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype); method public void setInputMethod(android.os.IBinder, java.lang.String); method public void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype); diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index dd1c275..b42f1c5 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -805,6 +805,7 @@ int main(int argc, char **argv) { Vector<CodecCapabilities> results; CHECK_EQ(QueryCodecs(omx, kMimeTypes[k], true, // queryDecoders + false, // hwCodecOnly &results), (status_t)OK); for (size_t i = 0; i < results.size(); ++i) { @@ -844,7 +845,12 @@ int main(int argc, char **argv) { for (List<IOMX::ComponentInfo>::iterator it = list.begin(); it != list.end(); ++it) { - printf("%s\n", (*it).mName.string()); + printf("%s\t Roles: ", (*it).mName.string()); + for (List<String8>::iterator itRoles = (*it).mRoles.begin() ; + itRoles != (*it).mRoles.end() ; ++itRoles) { + printf("%s\t", (*itRoles).string()); + } + printf("\n"); } } diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index ef4adca..a09607a 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -171,6 +171,11 @@ public class AccessibilityServiceInfo implements Parcelable { private boolean mCanRetrieveWindowContent; /** + * Description of the accessibility service. + */ + private String mDescription; + + /** * Creates a new instance. */ public AccessibilityServiceInfo() { @@ -193,8 +198,6 @@ public class AccessibilityServiceInfo implements Parcelable { mId = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToShortString(); mResolveInfo = resolveInfo; - String settingsActivityName = null; - boolean retrieveScreenContent = false; XmlResourceParser parser = null; try { @@ -242,6 +245,8 @@ public class AccessibilityServiceInfo implements Parcelable { mCanRetrieveWindowContent = asAttributes.getBoolean( com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent, false); + mDescription = asAttributes.getString( + com.android.internal.R.styleable.AccessibilityService_description); asAttributes.recycle(); } catch (NameNotFoundException e) { throw new XmlPullParserException( "Unable to create context for: " @@ -315,6 +320,18 @@ public class AccessibilityServiceInfo implements Parcelable { } /** + * Description of the accessibility service. + * <p> + * <strong>Statically set from + * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> + * </p> + * @return The description. + */ + public String getDescription() { + return mDescription; + } + + /** * {@inheritDoc} */ public int describeContents() { @@ -331,6 +348,7 @@ public class AccessibilityServiceInfo implements Parcelable { parcel.writeParcelable(mResolveInfo, 0); parcel.writeString(mSettingsActivityName); parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0); + parcel.writeString(mDescription); } private void initFromParcel(Parcel parcel) { @@ -343,6 +361,7 @@ public class AccessibilityServiceInfo implements Parcelable { mResolveInfo = parcel.readParcelable(null); mSettingsActivityName = parcel.readString(); mCanRetrieveWindowContent = (parcel.readInt() == 1); + mDescription = parcel.readString(); } @Override diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index d25de97..06d18ec 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java @@ -25,6 +25,7 @@ import android.view.animation.DecelerateInterpolator; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; /** @@ -178,14 +179,17 @@ public class LayoutTransition { * the transition. The reason for this is that a further layout event should cause * existing animations to stop where they are prior to starting new animations. So * we cache all of the current animations in this map for possible cancellation on - * another layout event. + * another layout event. LinkedHashMaps are used to preserve the order in which animations + * are inserted, so that we process events (such as setting up start values) in the same order. */ - private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>(); - private final HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>(); - private final HashMap<View, Animator> currentAppearingAnimations = - new HashMap<View, Animator>(); - private final HashMap<View, Animator> currentDisappearingAnimations = + private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>(); + private final LinkedHashMap<View, Animator> currentChangingAnimations = + new LinkedHashMap<View, Animator>(); + private final LinkedHashMap<View, Animator> currentAppearingAnimations = + new LinkedHashMap<View, Animator>(); + private final LinkedHashMap<View, Animator> currentDisappearingAnimations = + new LinkedHashMap<View, Animator>(); /** * This hashmap is used to track the listeners that have been added to the children of @@ -235,7 +239,7 @@ public class LayoutTransition { PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1); PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1); - defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder(this, + defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder((Object)null, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY); defaultChangeIn.setDuration(DEFAULT_DURATION); defaultChangeIn.setStartDelay(mChangingAppearingDelay); @@ -244,11 +248,11 @@ public class LayoutTransition { defaultChangeOut.setStartDelay(mChangingDisappearingDelay); defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator); - defaultFadeIn = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f); + defaultFadeIn = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f); defaultFadeIn.setDuration(DEFAULT_DURATION); defaultFadeIn.setStartDelay(mAppearingDelay); defaultFadeIn.setInterpolator(mAppearingInterpolator); - defaultFadeOut = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f); + defaultFadeOut = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f); defaultFadeOut.setDuration(DEFAULT_DURATION); defaultFadeOut.setStartDelay(mDisappearingDelay); defaultFadeOut.setInterpolator(mDisappearingInterpolator); @@ -547,7 +551,7 @@ public class LayoutTransition { } /** - * This function sets up runs animations on all of the views that change during layout. + * This function sets up animations on all of the views that change during layout. * For every child in the parent, we create a change animation of the appropriate * type (appearing or disappearing) and ask it to populate its start values from its * target view. We add layout listeners to all child views and listen for changes. For @@ -821,24 +825,24 @@ public class LayoutTransition { */ public void cancel() { if (currentChangingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentChangingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.cancel(); } currentChangingAnimations.clear(); } if (currentAppearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentAppearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } currentAppearingAnimations.clear(); } if (currentDisappearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentDisappearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } @@ -859,8 +863,8 @@ public class LayoutTransition { case CHANGE_APPEARING: case CHANGE_DISAPPEARING: if (currentChangingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentChangingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentChangingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.cancel(); } @@ -869,8 +873,8 @@ public class LayoutTransition { break; case APPEARING: if (currentAppearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentAppearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentAppearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } @@ -879,8 +883,8 @@ public class LayoutTransition { break; case DISAPPEARING: if (currentDisappearingAnimations.size() > 0) { - HashMap<View, Animator> currentAnimCopy = - (HashMap<View, Animator>) currentDisappearingAnimations.clone(); + LinkedHashMap<View, Animator> currentAnimCopy = + (LinkedHashMap<View, Animator>) currentDisappearingAnimations.clone(); for (Animator anim : currentAnimCopy.values()) { anim.end(); } @@ -1113,4 +1117,4 @@ public class LayoutTransition { View view, int transitionType); } -}
\ No newline at end of file +} diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 8994b17..f6cd866 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -70,7 +70,7 @@ import android.view.HardwareRenderer; import android.view.View; import android.view.ViewDebug; import android.view.ViewManager; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerImpl; @@ -413,10 +413,10 @@ public final class ActivityThread { native private void dumpGraphicsInfo(FileDescriptor fd); private final class ApplicationThread extends ApplicationThreadNative { - private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s"; - private static final String ONE_COUNT_COLUMN = "%17s %8d"; - private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d"; - private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d"; + private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s"; + private static final String ONE_COUNT_COLUMN = "%21s %8d"; + private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d"; + private static final String TWO_COUNT_COLUMNS_DB = "%21s %8d %21s %8d"; private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s"; // Formatting for checkin service - update version if row format changes @@ -729,12 +729,17 @@ public final class ActivityThread { } @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (args != null && args.length == 1 && args[0].equals("graphics")) { + public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) { + FileOutputStream fout = new FileOutputStream(fd); + PrintWriter pw = new PrintWriter(fout); + try { + return dumpMemInfo(fd, pw, args); + } finally { pw.flush(); - dumpGraphicsInfo(fd); - return; } + } + + private Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, PrintWriter pw, String[] args) { long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; long nativeFree = Debug.getNativeHeapFreeSize() / 1024; @@ -742,14 +747,6 @@ public final class ActivityThread { Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); - final int nativeShared = memInfo.nativeSharedDirty; - final int dalvikShared = memInfo.dalvikSharedDirty; - final int otherShared = memInfo.otherSharedDirty; - - final int nativePrivate = memInfo.nativePrivateDirty; - final int dalvikPrivate = memInfo.dalvikPrivateDirty; - final int otherPrivate = memInfo.otherPrivateDirty; - Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.totalMemory() / 1024; @@ -813,16 +810,18 @@ public final class ActivityThread { pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); // Heap info - shared - pw.print(nativeShared); pw.print(','); - pw.print(dalvikShared); pw.print(','); - pw.print(otherShared); pw.print(','); - pw.print(nativeShared + dalvikShared + otherShared); pw.print(','); + pw.print(memInfo.nativeSharedDirty); pw.print(','); + pw.print(memInfo.dalvikSharedDirty); pw.print(','); + pw.print(memInfo.otherSharedDirty); pw.print(','); + pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty + + memInfo.otherSharedDirty); pw.print(','); // Heap info - private - pw.print(nativePrivate); pw.print(','); - pw.print(dalvikPrivate); pw.print(','); - pw.print(otherPrivate); pw.print(','); - pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(','); + pw.print(memInfo.nativePrivateDirty); pw.print(','); + pw.print(memInfo.dalvikPrivateDirty); pw.print(','); + pw.print(memInfo.otherPrivateDirty); pw.print(','); + pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty + + memInfo.otherPrivateDirty); pw.print(','); // Object counts pw.print(viewInstanceCount); pw.print(','); @@ -850,24 +849,38 @@ public final class ActivityThread { pw.print(','); } - return; + return memInfo; } // otherwise, show human-readable format - printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total"); - printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax); - printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A", - nativeAllocated + dalvikAllocated); - printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A", - nativeFree + dalvikFree); - - printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss, - memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); - - printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared, - nativeShared + dalvikShared + otherShared); - printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate, - nativePrivate + dalvikPrivate + otherPrivate); + printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap"); + printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free"); + printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------", + "------"); + printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty, + memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree); + printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty, + memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree); + + int otherPss = memInfo.otherPss; + int otherSharedDirty = memInfo.otherSharedDirty; + int otherPrivateDirty = memInfo.otherPrivateDirty; + + for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { + printRow(pw, HEAP_COLUMN, memInfo.getOtherLabel(i), + memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i), + memInfo.getOtherPrivateDirty(i), "", "", ""); + otherPss -= memInfo.getOtherPss(i); + otherSharedDirty -= memInfo.getOtherSharedDirty(i); + otherPrivateDirty -= memInfo.getOtherPrivateDirty(i); + } + + printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty, + otherPrivateDirty, "", "", ""); + printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(), + memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(), + nativeMax+dalvikMax, nativeAllocated+dalvikAllocated, + nativeFree+dalvikFree); pw.println(" "); pw.println(" Objects"); @@ -916,6 +929,13 @@ public final class ActivityThread { pw.println(" Asset Allocations"); pw.print(assetAlloc); } + + return memInfo; + } + + @Override + public void dumpGfxInfo(FileDescriptor fd, String[] args) { + dumpGraphicsInfo(fd); } private void printRow(PrintWriter pw, String format, Object...objs) { @@ -3538,6 +3558,7 @@ public final class ActivityThread { } final void handleTrimMemory(int level) { + WindowManagerImpl.getDefault().trimMemory(level); } private final void handleBindApplication(AppBindData data) { @@ -4051,7 +4072,7 @@ public final class ActivityThread { sThreadLocal.set(this); mSystemThread = system; if (!system) { - ViewAncestor.addFirstDrawHandler(new Runnable() { + ViewRootImpl.addFirstDrawHandler(new Runnable() { public void run() { ensureJitEnabled(); } @@ -4081,7 +4102,7 @@ public final class ActivityThread { } } - ViewAncestor.addConfigCallback(new ComponentCallbacks() { + ViewRootImpl.addConfigCallback(new ComponentCallbacks() { public void onConfigurationChanged(Configuration newConfig) { synchronized (mPackages) { // We need to apply this change to the resources diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 16181e0..942f245 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -485,6 +485,48 @@ public abstract class ApplicationThreadNative extends Binder scheduleTrimMemory(level); return true; } + + case DUMP_MEM_INFO_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + ParcelFileDescriptor fd = data.readFileDescriptor(); + String[] args = data.readStringArray(); + Debug.MemoryInfo mi = null; + if (fd != null) { + try { + mi = dumpMemInfo(fd.getFileDescriptor(), args); + } finally { + try { + fd.close(); + } catch (IOException e) { + // swallowed, not propagated back to the caller + } + } + } + reply.writeNoException(); + mi.writeToParcel(reply, 0); + return true; + } + + case DUMP_GFX_INFO_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + ParcelFileDescriptor fd = data.readFileDescriptor(); + String[] args = data.readStringArray(); + if (fd != null) { + try { + dumpGfxInfo(fd.getFileDescriptor(), args); + } finally { + try { + fd.close(); + } catch (IOException e) { + // swallowed, not propagated back to the caller + } + } + } + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -1004,4 +1046,28 @@ class ApplicationThreadProxy implements IApplicationThread { mRemote.transact(SCHEDULE_TRIM_MEMORY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); } + + public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeFileDescriptor(fd); + data.writeStringArray(args); + mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0); + reply.readException(); + Debug.MemoryInfo info = new Debug.MemoryInfo(); + info.readFromParcel(reply); + data.recycle(); + reply.recycle(); + return info; + } + + public void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeFileDescriptor(fd); + data.writeStringArray(args); + mRemote.transact(DUMP_GFX_INFO_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 285f1c1..c82c9ec 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1307,6 +1307,7 @@ final class FragmentManagerImpl extends FragmentManager { mExecutingActions = true; for (int i=0; i<numActions; i++) { mTmpActions[i].run(); + mTmpActions[i] = null; } mExecutingActions = false; didSomething = true; diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 94c2c86..9de0bf4 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -120,6 +120,8 @@ public interface IApplicationThread extends IInterface { void setCoreSettings(Bundle coreSettings) throws RemoteException; void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException; void scheduleTrimMemory(int level) throws RemoteException; + Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException; + void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -164,4 +166,6 @@ public interface IApplicationThread extends IInterface { int SET_CORE_SETTINGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+39; int UPDATE_PACKAGE_COMPATIBILITY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+40; int SCHEDULE_TRIM_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+41; + int DUMP_MEM_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+42; + int DUMP_GFX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+43; } diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 42eda02..8e2d360 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -168,6 +168,7 @@ public class SearchDialog extends Dialog { SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar); searchBar.setSearchDialog(this); mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view); + mSearchView.setIconified(false); mSearchView.setOnCloseListener(mOnCloseListener); mSearchView.setOnQueryTextListener(mOnQueryChangeListener); mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener); @@ -633,31 +634,6 @@ public class SearchDialog extends Dialog { } /** - * Overrides the handling of the back key to move back to the previous - * sources or dismiss the search dialog, instead of dismissing the input - * method. - */ - @Override - public boolean dispatchKeyEventPreIme(KeyEvent event) { - if (DBG) - Log.d(LOG_TAG, "onKeyPreIme(" + event + ")"); - if (mSearchDialog != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { - KeyEvent.DispatcherState state = getKeyDispatcherState(); - if (state != null) { - if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - state.startTracking(event, this); - return true; - } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() - && state.isTracking(event)) { - mSearchDialog.onBackPressed(); - return true; - } - } - } - return super.dispatchKeyEventPreIme(event); - } - - /** * Don't allow action modes in a SearchBar, it looks silly. */ @Override diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index c179b35..4c21d04 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -662,12 +662,6 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { writer.println("nothing to dump"); } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - //Log.i("Service", "Finalizing Service: " + this); - } // ------------------ Internal API ------------------ diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 7fd5a7d..8472b31 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -40,7 +40,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.DisplayMetrics; import android.util.Log; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import java.io.FileOutputStream; import java.io.IOException; @@ -592,7 +592,7 @@ public class WallpaperManager { public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) { try { //Log.v(TAG, "Sending new wallpaper offsets from app..."); - ViewAncestor.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( + ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep); //Log.v(TAG, "...app returning after sending offsets!"); } catch (RemoteException e) { @@ -630,7 +630,7 @@ public class WallpaperManager { int x, int y, int z, Bundle extras) { try { //Log.v(TAG, "Sending new wallpaper offsets from app..."); - ViewAncestor.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand( + ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand( windowToken, action, x, y, z, extras, false); //Log.v(TAG, "...app returning after sending offsets!"); } catch (RemoteException e) { @@ -650,7 +650,7 @@ public class WallpaperManager { */ public void clearWallpaperOffsets(IBinder windowToken) { try { - ViewAncestor.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( + ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( windowToken, -1, -1, -1, -1); } catch (RemoteException e) { // Ignore. diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java index a2af558..0e83dc0 100644 --- a/core/java/android/content/ContentService.java +++ b/core/java/android/content/ContentService.java @@ -20,17 +20,21 @@ import android.accounts.Account; import android.database.IContentObserver; import android.database.sqlite.SQLiteException; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import android.util.SparseIntArray; import android.Manifest; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; /** @@ -70,6 +74,40 @@ public final class ContentService extends IContentService.Stub { } else { mSyncManager.dump(fd, pw); } + pw.println(); + pw.println("Observer tree:"); + synchronized (mRootNode) { + int[] counts = new int[2]; + final SparseIntArray pidCounts = new SparseIntArray(); + mRootNode.dumpLocked(fd, pw, args, "", " ", counts, pidCounts); + pw.println(); + ArrayList<Integer> sorted = new ArrayList<Integer>(); + for (int i=0; i<pidCounts.size(); i++) { + sorted.add(pidCounts.keyAt(i)); + } + Collections.sort(sorted, new Comparator<Integer>() { + @Override + public int compare(Integer lhs, Integer rhs) { + int lc = pidCounts.get(lhs); + int rc = pidCounts.get(rhs); + if (lc < rc) { + return 1; + } else if (lc > rc) { + return -1; + } + return 0; + } + + }); + for (int i=0; i<sorted.size(); i++) { + int pid = sorted.get(i); + pw.print(" pid "); pw.print(pid); pw.print(": "); + pw.print(pidCounts.get(pid)); pw.println(" observers"); + } + pw.println(); + pw.print(" Total number of nodes: "); pw.println(counts[0]); + pw.print(" Total number of observers: "); pw.println(counts[1]); + } } finally { restoreCallingIdentity(identityToken); } @@ -102,7 +140,8 @@ public final class ContentService extends IContentService.Stub { throw new IllegalArgumentException("You must pass a valid uri and observer"); } synchronized (mRootNode) { - mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode); + mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode, + Binder.getCallingUid(), Binder.getCallingPid()); if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + " with notifyForDescendents " + notifyForDescendents); } @@ -465,12 +504,17 @@ public final class ContentService extends IContentService.Stub { public static final class ObserverNode { private class ObserverEntry implements IBinder.DeathRecipient { public final IContentObserver observer; + public final int uid; + public final int pid; public final boolean notifyForDescendents; private final Object observersLock; - public ObserverEntry(IContentObserver o, boolean n, Object observersLock) { + public ObserverEntry(IContentObserver o, boolean n, Object observersLock, + int _uid, int _pid) { this.observersLock = observersLock; observer = o; + uid = _uid; + pid = _pid; notifyForDescendents = n; try { observer.asBinder().linkToDeath(this, 0); @@ -484,6 +528,16 @@ public final class ContentService extends IContentService.Stub { removeObserverLocked(observer); } } + + public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, + String name, String prefix, SparseIntArray pidCounts) { + pidCounts.put(pid, pidCounts.get(pid)+1); + pw.print(prefix); pw.print(name); pw.print(": pid="); + pw.print(pid); pw.print(" uid="); + pw.print(uid); pw.print(" target="); + pw.println(Integer.toHexString(System.identityHashCode( + observer != null ? observer.asBinder() : null))); + } } public static final int INSERT_TYPE = 0; @@ -498,6 +552,37 @@ public final class ContentService extends IContentService.Stub { mName = name; } + public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, + String name, String prefix, int[] counts, SparseIntArray pidCounts) { + String innerName = null; + if (mObservers.size() > 0) { + if ("".equals(name)) { + innerName = mName; + } else { + innerName = name + "/" + mName; + } + for (int i=0; i<mObservers.size(); i++) { + counts[1]++; + mObservers.get(i).dumpLocked(fd, pw, args, innerName, prefix, + pidCounts); + } + } + if (mChildren.size() > 0) { + if (innerName == null) { + if ("".equals(name)) { + innerName = mName; + } else { + innerName = name + "/" + mName; + } + } + for (int i=0; i<mChildren.size(); i++) { + counts[0]++; + mChildren.get(i).dumpLocked(fd, pw, args, innerName, prefix, + counts, pidCounts); + } + } + } + private String getUriSegment(Uri uri, int index) { if (uri != null) { if (index == 0) { @@ -518,15 +603,16 @@ public final class ContentService extends IContentService.Stub { } public void addObserverLocked(Uri uri, IContentObserver observer, - boolean notifyForDescendents, Object observersLock) { - addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock); + boolean notifyForDescendents, Object observersLock, int uid, int pid) { + addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock, uid, pid); } private void addObserverLocked(Uri uri, int index, IContentObserver observer, - boolean notifyForDescendents, Object observersLock) { + boolean notifyForDescendents, Object observersLock, int uid, int pid) { // If this is the leaf node add the observer if (index == countUriSegments(uri)) { - mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock)); + mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock, + uid, pid)); return; } @@ -539,7 +625,8 @@ public final class ContentService extends IContentService.Stub { for (int i = 0; i < N; i++) { ObserverNode node = mChildren.get(i); if (node.mName.equals(segment)) { - node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock); + node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, + observersLock, uid, pid); return; } } @@ -547,7 +634,8 @@ public final class ContentService extends IContentService.Stub { // No child found, create one ObserverNode node = new ObserverNode(segment); mChildren.add(node); - node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock); + node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, + observersLock, uid, pid); } public boolean removeObserverLocked(IContentObserver observer) { diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java index 3d89e92..e1a8d21 100644 --- a/core/java/android/content/SearchRecentSuggestionsProvider.java +++ b/core/java/android/content/SearchRecentSuggestionsProvider.java @@ -186,6 +186,9 @@ public class SearchRecentSuggestionsProvider extends ContentProvider { mSuggestionProjection = new String [] { "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT, + "'android.resource://system/" + + com.android.internal.R.drawable.ic_menu_recent_history + "' AS " + + SearchManager.SUGGEST_COLUMN_ICON_1, "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1, "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2, "query AS " + SearchManager.SUGGEST_COLUMN_QUERY, @@ -196,6 +199,9 @@ public class SearchRecentSuggestionsProvider extends ContentProvider { mSuggestionProjection = new String [] { "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT, + "'android.resource://system/" + + com.android.internal.R.drawable.ic_menu_recent_history + "' AS " + + SearchManager.SUGGEST_COLUMN_ICON_1, "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1, "query AS " + SearchManager.SUGGEST_COLUMN_QUERY, "_id" diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 67d200c..b548623 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -409,9 +409,10 @@ public class UsbManager { /** * Sets the current USB function. + * If function is null, then the current function is set to the default function. * - * @param function name of the USB function - * @param makeDefault true if this should be set as the default + * @param function name of the USB function, or null to restore the default function + * @param makeDefault true if the function should be set as the new default function * * {@hide} */ diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index ccef122..aa6400b 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -19,6 +19,7 @@ package android.net; import static android.net.ConnectivityManager.isNetworkTypeMobile; import android.content.Context; +import android.os.Build; import android.telephony.TelephonyManager; import com.android.internal.util.Objects; @@ -68,7 +69,7 @@ public class NetworkIdentity { subTypeName = Integer.toString(mSubType); } - final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null"; + final String scrubSubscriberId = scrubSubscriberId(mSubscriberId); final String roaming = mRoaming ? ", ROAMING" : ""; return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId=" + scrubSubscriberId + roaming + "]"; @@ -91,6 +92,17 @@ public class NetworkIdentity { } /** + * Scrub given IMSI on production builds. + */ + public static String scrubSubscriberId(String subscriberId) { + if ("eng".equals(Build.TYPE)) { + return subscriberId; + } else { + return subscriberId != null ? "valid" : "null"; + } + } + + /** * Build a {@link NetworkIdentity} from the given {@link NetworkState}, * assuming that any mobile networks are using the current IMSI. */ diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 1ef0d9d..cd49023 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -16,10 +16,11 @@ package android.net; +import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIMAX; -import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkIdentity.scrubSubscriberId; import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G; @@ -119,7 +120,7 @@ public class NetworkTemplate implements Parcelable { @Override public String toString() { - final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null"; + final String scrubSubscriberId = scrubSubscriberId(mSubscriberId); return "NetworkTemplate: matchRule=" + getMatchRuleName(mMatchRule) + ", subscriberId=" + scrubSubscriberId; } @@ -150,7 +151,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Test if this network matches the given template and IMEI. + * Test if this network matches the given template and IMSI. */ public boolean matches(NetworkIdentity ident) { switch (mMatchRule) { @@ -170,7 +171,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Check if mobile network with matching IMEI. Also matches + * Check if mobile network with matching IMSI. Also matches * {@link #TYPE_WIMAX}. */ private boolean matchesMobile(NetworkIdentity ident) { @@ -183,7 +184,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Check if mobile network classified 3G or lower with matching IMEI. + * Check if mobile network classified 3G or lower with matching IMSI. */ private boolean matchesMobile3gLower(NetworkIdentity ident) { if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) { @@ -198,7 +199,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Check if mobile network classified 4G with matching IMEI. Also matches + * Check if mobile network classified 4G with matching IMSI. Also matches * {@link #TYPE_WIMAX}. */ private boolean matchesMobile4g(NetworkIdentity ident) { diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index ba69246..da2afb6 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -129,6 +129,11 @@ public final class Debug /** The shared dirty pages used by everything else. */ public int otherSharedDirty; + /** @hide */ + public static final int NUM_OTHER_STATS = 9; + + private int[] otherStats = new int[NUM_OTHER_STATS*3]; + public MemoryInfo() { } @@ -153,6 +158,38 @@ public final class Debug return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty; } + /* @hide */ + public int getOtherPss(int which) { + return otherStats[which*3]; + } + + /* @hide */ + public int getOtherPrivateDirty(int which) { + return otherStats[which*3 + 1]; + } + + /* @hide */ + public int getOtherSharedDirty(int which) { + return otherStats[which*3 + 2]; + } + + + /* @hide */ + public static String getOtherLabel(int which) { + switch (which) { + case 0: return "Cursor"; + case 1: return "Ashmem"; + case 2: return "Other dev"; + case 3: return ".so mmap"; + case 4: return ".jar mmap"; + case 5: return ".apk mmap"; + case 6: return ".ttf mmap"; + case 7: return ".dex mmap"; + case 8: return "Other mmap"; + default: return "????"; + } + } + public int describeContents() { return 0; } @@ -167,6 +204,7 @@ public final class Debug dest.writeInt(otherPss); dest.writeInt(otherPrivateDirty); dest.writeInt(otherSharedDirty); + dest.writeIntArray(otherStats); } public void readFromParcel(Parcel source) { @@ -179,6 +217,7 @@ public final class Debug otherPss = source.readInt(); otherPrivateDirty = source.readInt(); otherSharedDirty = source.readInt(); + otherStats = source.createIntArray(); } public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() { diff --git a/core/java/android/pim/ContactsAsyncHelper.java b/core/java/android/pim/ContactsAsyncHelper.java index 7c78a81..21fc594 100644 --- a/core/java/android/pim/ContactsAsyncHelper.java +++ b/core/java/android/pim/ContactsAsyncHelper.java @@ -186,7 +186,7 @@ public class ContactsAsyncHelper extends Handler { InputStream inputStream = null; try { inputStream = Contacts.openContactPhotoInputStream( - args.context.getContentResolver(), args.uri); + args.context.getContentResolver(), args.uri, true); } catch (Exception e) { Log.e(LOG_TAG, "Error opening photo input stream", e); } diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java index b8919c2..7133d3a 100644 --- a/core/java/android/preference/SeekBarPreference.java +++ b/core/java/android/preference/SeekBarPreference.java @@ -77,6 +77,11 @@ public class SeekBarPreference extends Preference } @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getInt(index, 0); + } + + @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() != KeyEvent.ACTION_UP) { if (keyCode == KeyEvent.KEYCODE_PLUS diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 0dd9a4d..76f198c 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -28,6 +28,7 @@ import android.content.CursorEntityIterator; import android.content.Entity; import android.content.EntityIterator; import android.content.Intent; +import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.database.Cursor; import android.database.DatabaseUtils; @@ -40,6 +41,7 @@ import android.util.Pair; import android.view.View; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -1757,8 +1759,8 @@ public final class ContactsContract { * * </p> * <p>You may also consider using the convenience method - * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)} - * to retrieve the raw photo contents of the thumbnail-sized photo. + * {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri, boolean)} + * to retrieve the raw photo contents of either the thumbnail-sized or the full-sized photo. * </p> * <p> * This directory can be used either with a {@link #CONTENT_URI} or @@ -1799,22 +1801,37 @@ public final class ContactsContract { } /** - * Opens an InputStream for the contacts's default photo and returns the - * photo as a byte stream. If there is not photo null will be returned. - * + * Opens an InputStream for the contacts's photo and returns the + * photo as a byte stream. + * @param cr The content resolver to use for querying * @param contactUri the contact whose photo should be used. This can be used with * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI. - * </p> - + * @param preferHighres If this is true and the contact has a higher resolution photo + * available, it is returned. If false, this function always tries to get the thumbnail * @return an InputStream of the photo, or null if no photo is present */ - public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri, + boolean preferHighres) { + if (preferHighres) { + final Uri displayPhotoUri = Uri.withAppendedPath(contactUri, + Contacts.Photo.DISPLAY_PHOTO); + InputStream inputStream; + try { + AssetFileDescriptor fd = cr.openAssetFileDescriptor(displayPhotoUri, "r"); + return fd.createInputStream(); + } catch (IOException e) { + // fallback to the thumbnail code + } + } + Uri photoUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY); if (photoUri == null) { return null; } Cursor cursor = cr.query(photoUri, - new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); + new String[] { + ContactsContract.CommonDataKinds.Photo.PHOTO + }, null, null, null); try { if (cursor == null || !cursor.moveToNext()) { return null; @@ -1830,6 +1847,20 @@ public final class ContactsContract { } } } + + /** + * Opens an InputStream for the contacts's thumbnail photo and returns the + * photo as a byte stream. + * @param cr The content resolver to use for querying + * @param contactUri the contact whose photo should be used. This can be used with + * either a {@link #CONTENT_URI} or a {@link #CONTENT_LOOKUP_URI} URI. + * @return an InputStream of the photo, or null if no photo is present + * @see #openContactPhotoInputStream(ContentResolver, Uri, boolean), if instead + * of the thumbnail the high-res picture is preferred + */ + public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + return openContactPhotoInputStream(cr, contactUri, false); + } } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 23b53ae..34699e2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2683,6 +2683,13 @@ public final class Settings { public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled"; /** + * If touch exploration is requested. Touch exploration is enabled if it is + * requested by this setting, accessibility is enabled and there is at least + * one enabled accessibility serivce that provides spoken feedback. + */ + public static final String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested"; + + /** * List of the enabled accessibility providers. */ public static final String ENABLED_ACCESSIBILITY_SERVICES = diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 8fc8b9d..c51ba2a 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -51,7 +51,7 @@ import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.view.WindowManagerPolicy; @@ -650,7 +650,7 @@ public abstract class WallpaperService extends Service { mWindowToken = wrapper.mWindowToken; mSurfaceHolder.setSizeFromLayout(); mInitializing = true; - mSession = ViewAncestor.getWindowSession(getMainLooper()); + mSession = ViewRootImpl.getWindowSession(getMainLooper()); mWindow.setSession(mSession); diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index dea708a..255b333 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -17,6 +17,7 @@ package android.speech.tts; import android.media.AudioFormat; import android.media.AudioTrack; +import android.text.TextUtils; import android.util.Log; import java.util.Iterator; @@ -25,6 +26,7 @@ import java.util.concurrent.atomic.AtomicLong; class AudioPlaybackHandler { private static final String TAG = "TTS.AudioPlaybackHandler"; + private static final boolean DBG_THREADING = false; private static final boolean DBG = false; private static final int MIN_AUDIO_BUFFER_SIZE = 8192; @@ -64,70 +66,105 @@ class AudioPlaybackHandler { * Stops all synthesis for a given {@code token}. If the current token * is currently being processed, an effort will be made to stop it but * that is not guaranteed. + * + * NOTE: This assumes that all other messages in the queue with {@code token} + * have been removed already. + * + * NOTE: Must be called synchronized on {@code AudioPlaybackHandler.this}. */ - synchronized public void stop(MessageParams token) { + private void stop(MessageParams token) { if (token == null) { return; } - removeMessages(token); + if (DBG) Log.d(TAG, "Stopping token : " + token); if (token.getType() == MessageParams.TYPE_SYNTHESIS) { AudioTrack current = ((SynthesisMessageParams) token).getAudioTrack(); if (current != null) { // Stop the current audio track if it's still playing. - // The audio track is thread safe in this regard. + // The audio track is thread safe in this regard. The current + // handleSynthesisDataAvailable call will return soon after this + // call. current.stop(); } + // This is safe because PlaybackSynthesisCallback#stop would have + // been called before this method, and will no longer enqueue any + // audio for this token. + // + // (Even if it did, all it would result in is a warning message). mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY)); - } else { - final MessageParams current = getCurrentParams(); - - if (current != null) { - if (token.getType() == MessageParams.TYPE_AUDIO) { - ((AudioMessageParams) current).getPlayer().stop(); - } else if (token.getType() == MessageParams.TYPE_SILENCE) { - ((SilenceMessageParams) current).getConditionVariable().open(); - } - } + } else if (token.getType() == MessageParams.TYPE_AUDIO) { + ((AudioMessageParams) token).getPlayer().stop(); + // No cleanup required for audio messages. + } else if (token.getType() == MessageParams.TYPE_SILENCE) { + ((SilenceMessageParams) token).getConditionVariable().open(); + // No cleanup required for silence messages. } } + // ----------------------------------------------------- + // Methods that add and remove elements from the queue. These do not + // need to be synchronized strictly speaking, but they make the behaviour + // a lot more predictable. (though it would still be correct without + // synchronization). + // ----------------------------------------------------- + synchronized public void removePlaybackItems(String callingApp) { + if (DBG_THREADING) Log.d(TAG, "Removing all callback items for : " + callingApp); removeMessages(callingApp); - stop(getCurrentParams()); + + final MessageParams current = getCurrentParams(); + if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) { + stop(current); + } } synchronized public void removeAllItems() { + if (DBG_THREADING) Log.d(TAG, "Removing all items"); removeAllMessages(); stop(getCurrentParams()); } /** + * @return false iff the queue is empty and no queue item is currently + * being handled, true otherwise. + */ + public boolean isSpeaking() { + return (mQueue.peek() != null) || (mCurrentParams != null); + } + + /** * Shut down the audio playback thread. */ synchronized public void quit() { + removeAllMessages(); stop(getCurrentParams()); mQueue.add(new ListEntry(SHUTDOWN, null, HIGH_PRIORITY)); } - void enqueueSynthesisStart(SynthesisMessageParams token) { + synchronized void enqueueSynthesisStart(SynthesisMessageParams token) { + if (DBG_THREADING) Log.d(TAG, "Enqueuing synthesis start : " + token); mQueue.add(new ListEntry(SYNTHESIS_START, token)); } - void enqueueSynthesisDataAvailable(SynthesisMessageParams token) { + synchronized void enqueueSynthesisDataAvailable(SynthesisMessageParams token) { + if (DBG_THREADING) Log.d(TAG, "Enqueuing synthesis data available : " + token); mQueue.add(new ListEntry(SYNTHESIS_DATA_AVAILABLE, token)); } - void enqueueSynthesisDone(SynthesisMessageParams token) { + synchronized void enqueueSynthesisDone(SynthesisMessageParams token) { + if (DBG_THREADING) Log.d(TAG, "Enqueuing synthesis done : " + token); mQueue.add(new ListEntry(SYNTHESIS_DONE, token)); } - void enqueueAudio(AudioMessageParams token) { + synchronized void enqueueAudio(AudioMessageParams token) { + if (DBG_THREADING) Log.d(TAG, "Enqueuing audio : " + token); mQueue.add(new ListEntry(PLAY_AUDIO, token)); } - void enqueueSilence(SilenceMessageParams token) { + synchronized void enqueueSilence(SilenceMessageParams token) { + if (DBG_THREADING) Log.d(TAG, "Enqueuing silence : " + token); mQueue.add(new ListEntry(PLAY_SILENCE, token)); } @@ -172,26 +209,6 @@ class AudioPlaybackHandler { } /* - * Remove all messages from the queue that contain the supplied token. - * Note that the Iterator is thread safe, and other methods can safely - * continue adding to the queue at this point. - */ - synchronized private void removeMessages(MessageParams token) { - if (token == null) { - return; - } - - Iterator<ListEntry> it = mQueue.iterator(); - - while (it.hasNext()) { - final ListEntry current = it.next(); - if (current.mMessage == token) { - it.remove(); - } - } - } - - /* * Atomically clear the queue of all messages. */ synchronized private void removeAllMessages() { @@ -255,6 +272,13 @@ class AudioPlaybackHandler { } private void setCurrentParams(MessageParams p) { + if (DBG_THREADING) { + if (p != null) { + Log.d(TAG, "Started handling :" + p); + } else { + Log.d(TAG, "End handling : " + mCurrentParams); + } + } mCurrentParams = p; } @@ -345,7 +369,7 @@ class AudioPlaybackHandler { private void handleSynthesisDataAvailable(MessageParams msg) { final SynthesisMessageParams param = (SynthesisMessageParams) msg; if (param.getAudioTrack() == null) { - Log.w(TAG, "Error : null audio track in handleDataAvailable."); + Log.w(TAG, "Error : null audio track in handleDataAvailable : " + param); return; } @@ -394,22 +418,30 @@ class AudioPlaybackHandler { if (DBG) Log.d(TAG, "handleSynthesisDone()"); final AudioTrack audioTrack = params.getAudioTrack(); - try { - if (audioTrack != null) { - if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + - audioTrack.hashCode()); - blockUntilDone(params); - if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); - // The last call to AudioTrack.write( ) will return only after - // all data from the audioTrack has been sent to the mixer, so - // it's safe to release at this point. - audioTrack.release(); - } - } finally { + if (audioTrack == null) { + return; + } + + if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + + audioTrack.hashCode()); + blockUntilDone(params); + if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); + + // The last call to AudioTrack.write( ) will return only after + // all data from the audioTrack has been sent to the mixer, so + // it's safe to release at this point. Make sure release() and the call + // that set the audio track to null are performed atomically. + synchronized (this) { + // Never allow the audioTrack to be observed in a state where + // it is released but non null. The only case this might happen + // is in the various stopFoo methods that call AudioTrack#stop from + // different threads, but they are synchronized on AudioPlayBackHandler#this + // too. + audioTrack.release(); params.setAudioTrack(null); - params.getDispatcher().dispatchUtteranceCompleted(); - mLastSynthesisRequest = null; } + params.getDispatcher().dispatchUtteranceCompleted(); + mLastSynthesisRequest = null; } private static void blockUntilDone(SynthesisMessageParams params) { diff --git a/core/java/android/speech/tts/MessageParams.java b/core/java/android/speech/tts/MessageParams.java index 4c1b6d2..e7d6da3 100644 --- a/core/java/android/speech/tts/MessageParams.java +++ b/core/java/android/speech/tts/MessageParams.java @@ -38,5 +38,10 @@ abstract class MessageParams { return mCallingApp; } + @Override + public String toString() { + return "MessageParams[" + hashCode() + "]"; + } + abstract int getType(); } diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java index 04bd745..7dbf1ac 100644 --- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java +++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java @@ -90,12 +90,10 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { Log.w(TAG, "stop() called twice"); return; } + // mToken will be null if the engine encounters // an error before it called start(). - if (mToken != null) { - mAudioTrackHandler.stop(mToken); - mToken = null; - } else { + if (mToken == null) { // In all other cases, mAudioTrackHandler.stop() will // result in onComplete being called. mLogger.onWriteData(); @@ -158,7 +156,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { } synchronized (mStateLock) { - if (mToken == null) { + if (mToken == null || mStopped) { return TextToSpeech.ERROR; } diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 32ca226..5126e48 100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -109,6 +109,11 @@ public class TextToSpeech { /** * Broadcast Action: The TextToSpeech synthesizer has completed processing * of all the text in the speech queue. + * + * Note that this notifies callers when the <b>engine</b> has finished has + * processing text data. Audio playback might not have completed (or even started) + * at this point. If you wish to be notified when this happens, see + * {@link OnUtteranceCompletedListener}. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = @@ -576,6 +581,14 @@ public class TextToSpeech { service.setCallback(getPackageName(), null); service.stop(getPackageName()); mServiceConnection.disconnect(); + // Context#unbindService does not result in a call to + // ServiceConnection#onServiceDisconnected. As a result, the + // service ends up being destroyed (if there are no other open + // connections to it) but the process lives on and the + // ServiceConnection continues to refer to the destroyed service. + // + // This leads to tons of log spam about SynthThread being dead. + mServiceConnection = null; mCurrentEngine = null; return null; } @@ -796,7 +809,10 @@ public class TextToSpeech { } /** - * Checks whether the TTS engine is busy speaking. + * Checks whether the TTS engine is busy speaking. Note that a speech item is + * considered complete once it's audio data has been sent to the audio mixer, or + * written to a file. There might be a finite lag between this point, and when + * the audio hardware completes playback. * * @return {@code true} if the TTS engine is speaking. */ diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 010c155..1926c92 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -282,6 +282,8 @@ public abstract class TextToSpeechService extends Service { if (current != null) { current.stop(); } + + // The AudioPlaybackHandler will be destroyed by the caller. } /** @@ -337,6 +339,8 @@ public abstract class TextToSpeechService extends Service { } removeCallbacksAndMessages(callingApp); + // This stops writing data to the file / or publishing + // items to the audio playback handler. SpeechItem current = setCurrentSpeechItem(null); if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) { current.stop(); @@ -628,9 +632,7 @@ public abstract class TextToSpeechService extends Service { @Override protected void stopImpl() { - if (mToken != null) { - mAudioPlaybackHandler.stop(mToken); - } + // Do nothing. } } @@ -657,9 +659,7 @@ public abstract class TextToSpeechService extends Service { @Override protected void stopImpl() { - if (mToken != null) { - mAudioPlaybackHandler.stop(mToken); - } + // Do nothing. } } @@ -719,7 +719,7 @@ public abstract class TextToSpeechService extends Service { } public boolean isSpeaking() { - return mSynthHandler.isSpeaking(); + return mSynthHandler.isSpeaking() || mAudioPlaybackHandler.isSpeaking(); } public int stop(String callingApp) { @@ -767,10 +767,6 @@ public abstract class TextToSpeechService extends Service { mCallbacks.setCallback(packageName, cb); } - private boolean isDefault(String lang, String country, String variant) { - return Locale.getDefault().equals(new Locale(lang, country, variant)); - } - private String intern(String in) { // The input parameter will be non null. return in.intern(); diff --git a/core/java/android/util/Config.java b/core/java/android/util/Config.java new file mode 100644 index 0000000..70dc9aa --- /dev/null +++ b/core/java/android/util/Config.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2006 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.util; + +/** + * @deprecated This class is not useful, it just returns the same value for + * all constants, and has always done this. Do not use it. + */ +@Deprecated +public final class Config { + /** @hide */ public Config() {} + + /** + * @deprecated Always false. + */ + @Deprecated + public static final boolean DEBUG = false; + + /** + * @deprecated Always true. + */ + @Deprecated + public static final boolean RELEASE = true; + + /** + * @deprecated Always false. + */ + @Deprecated + public static final boolean PROFILE = false; + + /** + * @deprecated Always false. + */ + @Deprecated + public static final boolean LOGV = false; + + /** + * @deprecated Always true. + */ + @Deprecated + public static final boolean LOGD = true; +} diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index 132b595..09ce8e4 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -196,6 +196,12 @@ public final class JsonReader implements Closeable { private int pos = 0; private int limit = 0; + /* + * The offset of the first character in the buffer. + */ + private int bufferStartLine = 1; + private int bufferStartColumn = 1; + private final List<JsonScope> stack = new ArrayList<JsonScope>(); { push(JsonScope.EMPTY_DOCUMENT); @@ -711,6 +717,16 @@ public final class JsonReader implements Closeable { * false. */ private boolean fillBuffer(int minimum) throws IOException { + // Before clobbering the old characters, update where buffer starts + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + bufferStartLine++; + bufferStartColumn = 1; + } else { + bufferStartColumn++; + } + } + if (limit != pos) { limit -= pos; System.arraycopy(buffer, pos, buffer, 0, limit); @@ -729,6 +745,28 @@ public final class JsonReader implements Closeable { return false; } + private int getLineNumber() { + int result = bufferStartLine; + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + result++; + } + } + return result; + } + + private int getColumnNumber() { + int result = bufferStartColumn; + for (int i = 0; i < pos; i++) { + if (buffer[i] == '\n') { + result = 1; + } else { + result++; + } + } + return result; + } + private int nextNonWhitespace() throws IOException { while (pos < limit || fillBuffer(1)) { int c = buffer[pos++]; @@ -1107,7 +1145,8 @@ public final class JsonReader implements Closeable { * with this reader's content. */ private IOException syntaxError(String message) throws IOException { - throw new MalformedJsonException(message + " near " + getSnippet()); + throw new MalformedJsonException(message + + " at line " + getLineNumber() + " column " + getColumnNumber()); } private CharSequence getSnippet() { diff --git a/core/java/android/util/JsonWriter.java b/core/java/android/util/JsonWriter.java index 47e84c5..c1e6e40 100644 --- a/core/java/android/util/JsonWriter.java +++ b/core/java/android/util/JsonWriter.java @@ -407,6 +407,11 @@ public final class JsonWriter implements Closeable { * quotation marks except for the characters that must be escaped: * quotation mark, reverse solidus, and the control characters * (U+0000 through U+001F)." + * + * We also escape '\u2028' and '\u2029', which JavaScript interprets + * as newline characters. This prevents eval() from failing with a + * syntax error. + * http://code.google.com/p/google-gson/issues/detail?id=341 */ switch (c) { case '"': @@ -435,6 +440,11 @@ public final class JsonWriter implements Closeable { out.write("\\f"); break; + case '\u2028': + case '\u2029': + out.write(String.format("\\u%04x", (int) c)); + break; + default: if (c <= 0x1F) { out.write(String.format("\\u%04x", (int) c)); diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java index 7fc43b9..7cf4579 100644 --- a/core/java/android/util/SparseArray.java +++ b/core/java/android/util/SparseArray.java @@ -23,10 +23,14 @@ import com.android.internal.util.ArrayUtils; * there can be gaps in the indices. It is intended to be more efficient * than using a HashMap to map Integers to Objects. */ -public class SparseArray<E> { +public class SparseArray<E> implements Cloneable { private static final Object DELETED = new Object(); private boolean mGarbage = false; + private int[] mKeys; + private Object[] mValues; + private int mSize; + /** * Creates a new SparseArray containing no mappings. */ @@ -47,6 +51,20 @@ public class SparseArray<E> { mSize = 0; } + @Override + @SuppressWarnings("unchecked") + public SparseArray<E> clone() { + SparseArray<E> clone = null; + try { + clone = (SparseArray<E>) super.clone(); + clone.mKeys = mKeys.clone(); + clone.mValues = mValues.clone(); + } catch (CloneNotSupportedException cnse) { + /* ignore */ + } + return clone; + } + /** * Gets the Object mapped from the specified key, or <code>null</code> * if no such mapping has been made. @@ -59,6 +77,7 @@ public class SparseArray<E> { * Gets the Object mapped from the specified key, or the specified Object * if no such mapping has been made. */ + @SuppressWarnings("unchecked") public E get(int key, E valueIfKeyNotFound) { int i = binarySearch(mKeys, 0, mSize, key); @@ -209,6 +228,7 @@ public class SparseArray<E> { * the value from the <code>index</code>th key-value mapping that this * SparseArray stores. */ + @SuppressWarnings("unchecked") public E valueAt(int index) { if (mGarbage) { gc(); @@ -331,20 +351,4 @@ public class SparseArray<E> { else return ~high; } - - private void checkIntegrity() { - for (int i = 1; i < mSize; i++) { - if (mKeys[i] <= mKeys[i - 1]) { - for (int j = 0; j < mSize; j++) { - Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); - } - - throw new RuntimeException(); - } - } - } - - private int[] mKeys; - private Object[] mValues; - private int mSize; } diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java index f7799de..76c47c6 100644 --- a/core/java/android/util/SparseBooleanArray.java +++ b/core/java/android/util/SparseBooleanArray.java @@ -24,7 +24,7 @@ import com.android.internal.util.ArrayUtils; * there can be gaps in the indices. It is intended to be more efficient * than using a HashMap to map Integers to Booleans. */ -public class SparseBooleanArray { +public class SparseBooleanArray implements Cloneable { /** * Creates a new SparseBooleanArray containing no mappings. */ @@ -45,6 +45,19 @@ public class SparseBooleanArray { mSize = 0; } + @Override + public SparseBooleanArray clone() { + SparseBooleanArray clone = null; + try { + clone = (SparseBooleanArray) super.clone(); + clone.mKeys = mKeys.clone(); + clone.mValues = mValues.clone(); + } catch (CloneNotSupportedException cnse) { + /* ignore */ + } + return clone; + } + /** * Gets the boolean mapped from the specified key, or <code>false</code> * if no such mapping has been made. @@ -227,18 +240,6 @@ public class SparseBooleanArray { return ~high; } - private void checkIntegrity() { - for (int i = 1; i < mSize; i++) { - if (mKeys[i] <= mKeys[i - 1]) { - for (int j = 0; j < mSize; j++) { - Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); - } - - throw new RuntimeException(); - } - } - } - private int[] mKeys; private boolean[] mValues; private int mSize; diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java index 9ab3b53..8d11177 100644 --- a/core/java/android/util/SparseIntArray.java +++ b/core/java/android/util/SparseIntArray.java @@ -23,7 +23,12 @@ import com.android.internal.util.ArrayUtils; * there can be gaps in the indices. It is intended to be more efficient * than using a HashMap to map Integers to Integers. */ -public class SparseIntArray { +public class SparseIntArray implements Cloneable { + + private int[] mKeys; + private int[] mValues; + private int mSize; + /** * Creates a new SparseIntArray containing no mappings. */ @@ -44,6 +49,19 @@ public class SparseIntArray { mSize = 0; } + @Override + public SparseIntArray clone() { + SparseIntArray clone = null; + try { + clone = (SparseIntArray) super.clone(); + clone.mKeys = mKeys.clone(); + clone.mValues = mValues.clone(); + } catch (CloneNotSupportedException cnse) { + /* ignore */ + } + return clone; + } + /** * Gets the int mapped from the specified key, or <code>0</code> * if no such mapping has been made. @@ -232,20 +250,4 @@ public class SparseIntArray { else return ~high; } - - private void checkIntegrity() { - for (int i = 1; i < mSize; i++) { - if (mKeys[i] <= mKeys[i - 1]) { - for (int j = 0; j < mSize; j++) { - Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]); - } - - throw new RuntimeException(); - } - } - } - - private int[] mKeys; - private int[] mValues; - private int mSize; } diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java index bfafa98..e954983 100644 --- a/core/java/android/view/ActionMode.java +++ b/core/java/android/view/ActionMode.java @@ -23,6 +23,36 @@ package android.view; * Examples of good action modes include selection modes, search, content editing, etc. */ public abstract class ActionMode { + private Object mTag; + + /** + * Set a tag object associated with this ActionMode. + * + * <p>Like the tag available to views, this allows applications to associate arbitrary + * data with an ActionMode for later reference. + * + * @param tag Tag to associate with this ActionMode + * + * @see #getTag() + */ + public void setTag(Object tag) { + mTag = tag; + } + + /** + * Retrieve the tag object associated with this ActionMode. + * + * <p>Like the tag available to views, this allows applications to associate arbitrary + * data with an ActionMode for later reference. + * + * @return Tag associated with this ActionMode + * + * @see #setTag(Object) + */ + public Object getTag() { + return mTag; + } + /** * Set the title of the action mode. This method will have no visible effect if * a custom view has been set. diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 4987e2f..80244bb 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -286,6 +286,38 @@ class GLES20Canvas extends HardwareCanvas { private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction); + + /////////////////////////////////////////////////////////////////////////// + // Memory + /////////////////////////////////////////////////////////////////////////// + + /** + * @see #flushCaches(int) + */ + public static final int FLUSH_CACHES_MODERATE = 0; + + /** + * @see #flushCaches(int) + */ + public static final int FLUSH_CACHES_FULL = 1; + + /** + * Flush caches to reclaim as much memory as possible. The amount of memory + * to reclaim is indicate by the level parameter. + * + * The level can be one of {@link #FLUSH_CACHES_MODERATE} or + * {@link #FLUSH_CACHES_FULL}. + * + * @param level Hint about the amount of memory to reclaim + * + * @hide + */ + public static void flushCaches(int level) { + nFlushCaches(level); + } + + private static native void nFlushCaches(int level); + /////////////////////////////////////////////////////////////////////////// // Display list /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 011e44c..9a2564f 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -17,6 +17,7 @@ package android.view; +import android.content.ComponentCallbacks; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; @@ -263,6 +264,18 @@ public abstract class HardwareRenderer { } /** + * Invoke this method when the system is running out of memory. This + * method will attempt to recover as much memory as possible, based on + * the specified hint. + * + * @param level Hint about the amount of memory that should be trimmed, + * see {@link android.content.ComponentCallbacks} + */ + static void trimMemory(int level) { + Gl20Renderer.flushCaches(level); + } + + /** * Indicates whether hardware acceleration is currently enabled. * * @return True if hardware acceleration is in use, false otherwise. @@ -858,5 +871,16 @@ public abstract class HardwareRenderer { } return null; } + + static void flushCaches(int level) { + switch (level) { + case ComponentCallbacks.TRIM_MEMORY_MODERATE: + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE); + break; + case ComponentCallbacks.TRIM_MEMORY_COMPLETE: + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL); + break; + } + } } } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 764899f..cbdb38e 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -426,7 +426,7 @@ public class SurfaceView extends View { if (!mHaveFrame) { return; } - ViewAncestor viewRoot = (ViewAncestor) getRootView().getParent(); + ViewRootImpl viewRoot = (ViewRootImpl) getRootView().getParent(); if (viewRoot != null) { mTranslator = viewRoot.mTranslator; } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index d656f31..96d6f09 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.util.AttributeSet; import android.util.Log; @@ -107,6 +108,14 @@ public class TextureView extends View { private SurfaceTexture.OnFrameAvailableListener mUpdateListener; + private Canvas mCanvas; + private int mSaveCount; + + private final Object[] mNativeWindowLock = new Object[0]; + // Used from native code, do not write! + @SuppressWarnings({"UnusedDeclaration"}) + private int mNativeWindow; + /** * Creates a new TextureView. * @@ -190,7 +199,11 @@ public class TextureView extends View { mListener.onSurfaceTextureDestroyed(mSurface); } - mLayer.destroy(); + synchronized (mNativeWindowLock) { + nDestroyNativeWindow(); + } + + mLayer.destroy(); mSurface = null; mLayer = null; } @@ -274,6 +287,7 @@ public class TextureView extends View { mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque); mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer); nSetDefaultBufferSize(mSurface, getWidth(), getHeight()); + nCreateNativeWindow(mSurface); mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() { @Override @@ -431,6 +445,79 @@ public class TextureView extends View { } /** + * <p>Start editing the pixels in the surface. The returned Canvas can be used + * to draw into the surface's bitmap. A null is returned if the surface has + * not been created or otherwise cannot be edited. You will usually need + * to implement + * {@link SurfaceTextureListener#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int)} + * to find out when the Surface is available for use.</p> + * + * <p>The content of the Surface is never preserved between unlockCanvas() + * and lockCanvas(), for this reason, every pixel within the Surface area + * must be written. The only exception to this rule is when a dirty + * rectangle is specified, in which case, non-dirty pixels will be + * preserved.</p> + * + * @return A Canvas used to draw into the surface. + * + * @see #lockCanvas(android.graphics.Rect) + * @see #unlockCanvasAndPost(android.graphics.Canvas) + */ + public Canvas lockCanvas() { + return lockCanvas(null); + } + + /** + * Just like {@link #lockCanvas()} but allows specification of a dirty + * rectangle. Every pixel within that rectangle must be written; however + * pixels outside the dirty rectangle will be preserved by the next call + * to lockCanvas(). + * + * @param dirty Area of the surface that will be modified. + + * @return A Canvas used to draw into the surface. + * + * @see #lockCanvas() + * @see #unlockCanvasAndPost(android.graphics.Canvas) + */ + public Canvas lockCanvas(Rect dirty) { + if (!isAvailable()) return null; + + if (mCanvas == null) { + mCanvas = new Canvas(); + } + + synchronized (mNativeWindowLock) { + nLockCanvas(mNativeWindow, mCanvas, dirty); + } + mSaveCount = mCanvas.save(); + + return mCanvas; + } + + /** + * Finish editing pixels in the surface. After this call, the surface's + * current pixels will be shown on the screen, but its content is lost, + * in particular there is no guarantee that the content of the Surface + * will remain unchanged when lockCanvas() is called again. + * + * @param canvas The Canvas previously returned by lockCanvas() + * + * @see #lockCanvas() + * @see #lockCanvas(android.graphics.Rect) + */ + public void unlockCanvasAndPost(Canvas canvas) { + if (mCanvas != null && canvas == mCanvas) { + canvas.restoreToCount(mSaveCount); + mSaveCount = 0; + + synchronized (mNativeWindowLock) { + nUnlockCanvasAndPost(mNativeWindow, mCanvas); + } + } + } + + /** * Returns the {@link SurfaceTexture} used by this view. This method * may return null if the view is not attached to a window or if the surface * texture has not been initialized yet. @@ -506,6 +593,12 @@ public class TextureView extends View { public void onSurfaceTextureUpdated(SurfaceTexture surface); } + private native void nCreateNativeWindow(SurfaceTexture surface); + private native void nDestroyNativeWindow(); + private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture, int width, int height); + + private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty); + private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c8ff37a..59cb216 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2167,21 +2167,27 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit /** * Cache the paddingRight set by the user to append to the scrollbar's size. + * + * @hide */ @ViewDebug.ExportedProperty(category = "padding") - int mUserPaddingRight; + protected int mUserPaddingRight; /** * Cache the paddingBottom set by the user to append to the scrollbar's size. + * + * @hide */ @ViewDebug.ExportedProperty(category = "padding") - int mUserPaddingBottom; + protected int mUserPaddingBottom; /** * Cache the paddingLeft set by the user to append to the scrollbar's size. + * + * @hide */ @ViewDebug.ExportedProperty(category = "padding") - int mUserPaddingLeft; + protected int mUserPaddingLeft; /** * Cache if the user padding is relative. @@ -5037,9 +5043,9 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit } /** Gets the ViewAncestor, or null if not attached. */ - /*package*/ ViewAncestor getViewAncestor() { + /*package*/ ViewRootImpl getViewRootImpl() { View root = getRootView(); - return root != null ? (ViewAncestor)root.getParent() : null; + return root != null ? (ViewRootImpl)root.getParent() : null; } /** @@ -5055,7 +5061,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit public final boolean requestFocusFromTouch() { // Leave touch mode if we need to if (isInTouchMode()) { - ViewAncestor viewRoot = getViewAncestor(); + ViewRootImpl viewRoot = getViewRootImpl(); if (viewRoot != null) { viewRoot.ensureTouchMode(false); } @@ -5647,7 +5653,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit if (mAttachInfo != null) { return mAttachInfo.mInTouchMode; } else { - return ViewAncestor.isInTouchMode(); + return ViewRootImpl.isInTouchMode(); } } @@ -8248,7 +8254,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit handler = attachInfo.mHandler; } else { // Assume that post will succeed later - ViewAncestor.getRunQueue().post(action); + ViewRootImpl.getRunQueue().post(action); return true; } @@ -8278,7 +8284,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit handler = attachInfo.mHandler; } else { // Assume that post will succeed later - ViewAncestor.getRunQueue().postDelayed(action, delayMillis); + ViewRootImpl.getRunQueue().postDelayed(action, delayMillis); return true; } @@ -8302,7 +8308,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit handler = attachInfo.mHandler; } else { // Assume that post will succeed later - ViewAncestor.getRunQueue().removeCallbacks(action); + ViewRootImpl.getRunQueue().removeCallbacks(action); return true; } @@ -9121,12 +9127,12 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // Start user padding override Left user padding. Otherwise, if Left user // padding is not defined, use the default left padding. If Left user padding // is defined, just use it. - if (mUserPaddingStart > 0) { + if (mUserPaddingStart >= 0) { mUserPaddingLeft = mUserPaddingStart; } else if (mUserPaddingLeft < 0) { mUserPaddingLeft = mPaddingLeft; } - if (mUserPaddingEnd > 0) { + if (mUserPaddingEnd >= 0) { mUserPaddingRight = mUserPaddingEnd; } else if (mUserPaddingRight < 0) { mUserPaddingRight = mPaddingRight; @@ -10750,12 +10756,14 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // Remember our drawn bit int drawn = mPrivateFlags & DRAWN; - // Invalidate our old position - invalidate(true); - - int oldWidth = mRight - mLeft; int oldHeight = mBottom - mTop; + int newWidth = right - left; + int newHeight = bottom - top; + boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); + + // Invalidate our old position + invalidate(sizeChanged); mLeft = left; mTop = top; @@ -10764,10 +10772,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit mPrivateFlags |= HAS_BOUNDS; - int newWidth = right - left; - int newHeight = bottom - top; - if (newWidth != oldWidth || newHeight != oldHeight) { + if (sizeChanged) { if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { // A change in dimension means an auto-centered pivot point changes, too mMatrixDirty = true; @@ -10782,7 +10788,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // before this call to setFrame came in, thereby clearing // the DRAWN bit. mPrivateFlags |= DRAWN; - invalidate(true); + invalidate(sizeChanged); // parent display list may need to be recreated based on a change in the bounds // of any child invalidateParentCaches(); @@ -11116,6 +11122,10 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit * background */ public void setBackgroundDrawable(Drawable d) { + if (d == mBGDrawable) { + return; + } + boolean requestLayout = false; mBackgroundResource = 0; @@ -11570,9 +11580,9 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit viewParent = view.mParent; } - if (viewParent instanceof ViewAncestor) { + if (viewParent instanceof ViewRootImpl) { // *cough* - final ViewAncestor vr = (ViewAncestor)viewParent; + final ViewRootImpl vr = (ViewRootImpl)viewParent; location[1] -= vr.mCurScrollY; } } @@ -12699,7 +12709,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit surface.unlockCanvasAndPost(canvas); } - final ViewAncestor root = getViewAncestor(); + final ViewRootImpl root = getViewRootImpl(); // Cache the local state object for delivery with DragEvents root.setLocalDragState(myLocalState); @@ -13906,7 +13916,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit Canvas mCanvas; /** - * A Handler supplied by a view's {@link android.view.ViewAncestor}. This + * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This * handler can be used to pump events in the UI events queue. */ final Handler mHandler; diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index f7f5a21..b85159b 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -366,7 +366,7 @@ public class ViewDebug { } private static BufferedWriter sHierarchyTraces; - private static ViewAncestor sHierarhcyRoot; + private static ViewRootImpl sHierarhcyRoot; private static String sHierarchyTracePrefix; /** @@ -415,7 +415,7 @@ public class ViewDebug { * @hide */ public static long getViewAncestorInstanceCount() { - return Debug.countInstancesOfClass(ViewAncestor.class); + return Debug.countInstancesOfClass(ViewRootImpl.class); } /** @@ -748,7 +748,7 @@ public class ViewDebug { return; } - sHierarhcyRoot = (ViewAncestor) view.getRootView().getParent(); + sHierarhcyRoot = (ViewRootImpl) view.getRootView().getParent(); } /** @@ -1100,7 +1100,7 @@ public class ViewDebug { private static void outputDisplayList(View root, String parameter) throws IOException { final View view = findView(root, parameter); - view.getViewAncestor().outputDisplayList(view); + view.getViewRootImpl().outputDisplayList(view); } private static void capture(View root, final OutputStream clientStream, String parameter) diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index cb3e9c6..a6c158d 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -954,7 +954,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final float tx = event.mX; final float ty = event.mY; - ViewAncestor root = getViewAncestor(); + ViewRootImpl root = getViewRootImpl(); // Dispatch down the view hierarchy switch (event.mAction) { @@ -3183,6 +3183,24 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** + * @hide + */ + protected void onViewAdded(View child) { + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewAdded(this, child); + } + } + + /** + * @hide + */ + protected void onViewRemoved(View child) { + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewRemoved(this, child); + } + } + + /** * Adds a view during layout. This is useful if in your onLayout() method, * you need to add more views (as does the list view for example). * @@ -3283,9 +3301,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager ai.mKeepScreenOn = lastKeepOn; } - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewAdded(this, child); - } + onViewAdded(child); if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) { mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE; @@ -3486,9 +3502,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager view.dispatchDetachedFromWindow(); } - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(this, view); - } + onViewRemoved(view); needGlobalAttributesUpdate(false); @@ -3533,8 +3547,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } private void removeViewsInternal(int start, int count) { - final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener; - final boolean notifyListener = onHierarchyChangeListener != null; final View focused = mFocused; final boolean detach = mAttachInfo != null; View clearChildFocus = null; @@ -3563,9 +3575,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager needGlobalAttributesUpdate(false); - if (notifyListener) { - onHierarchyChangeListener.onChildViewRemoved(this, view); - } + onViewRemoved(view); } removeFromArray(start, count); @@ -3603,8 +3613,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final View[] children = mChildren; mChildrenCount = 0; - final OnHierarchyChangeListener listener = mOnHierarchyChangeListener; - final boolean notify = listener != null; final View focused = mFocused; final boolean detach = mAttachInfo != null; View clearChildFocus = null; @@ -3630,9 +3638,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager view.dispatchDetachedFromWindow(); } - if (notify) { - listener.onChildViewRemoved(this, view); - } + onViewRemoved(view); view.mParent = null; children[i] = null; @@ -3672,9 +3678,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager child.dispatchDetachedFromWindow(); } - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(this, child); - } + onViewRemoved(child); } /** @@ -3839,13 +3843,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (drawAnimation) { if (view != null) { view.mPrivateFlags |= DRAW_ANIMATION; - } else if (parent instanceof ViewAncestor) { - ((ViewAncestor) parent).mIsAnimating = true; + } else if (parent instanceof ViewRootImpl) { + ((ViewRootImpl) parent).mIsAnimating = true; } } - if (parent instanceof ViewAncestor) { - ((ViewAncestor) parent).invalidate(); + if (parent instanceof ViewRootImpl) { + ((ViewRootImpl) parent).invalidate(); parent = null; } else if (view != null) { if ((view.mPrivateFlags & DRAWN) == DRAWN || @@ -3902,8 +3906,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (drawAnimation) { if (view != null) { view.mPrivateFlags |= DRAW_ANIMATION; - } else if (parent instanceof ViewAncestor) { - ((ViewAncestor) parent).mIsAnimating = true; + } else if (parent instanceof ViewRootImpl) { + ((ViewRootImpl) parent).mIsAnimating = true; } } @@ -4426,7 +4430,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // If this group is dirty, check that the parent is dirty as well if ((mPrivateFlags & DIRTY_MASK) != 0) { final ViewParent parent = getParent(); - if (parent != null && !(parent instanceof ViewAncestor)) { + if (parent != null && !(parent instanceof ViewRootImpl)) { if ((((View) parent).mPrivateFlags & DIRTY_MASK) == 0) { result = false; android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG, @@ -4995,7 +4999,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * @hide */ public void requestTransitionStart(LayoutTransition transition) { - ViewAncestor viewAncestor = getViewAncestor(); + ViewRootImpl viewAncestor = getViewRootImpl(); viewAncestor.requestTransitionStart(transition); } diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewRootImpl.java index ac73611..470493d 100644 --- a/core/java/android/view/ViewAncestor.java +++ b/core/java/android/view/ViewRootImpl.java @@ -92,7 +92,7 @@ import java.util.List; * {@hide} */ @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) -public final class ViewAncestor extends Handler implements ViewParent, +public final class ViewRootImpl extends Handler implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { private static final String TAG = "ViewAncestor"; private static final boolean DBG = false; @@ -303,7 +303,7 @@ public final class ViewAncestor extends Handler implements ViewParent, } } - public ViewAncestor(Context context) { + public ViewRootImpl(Context context) { super(); if (MEASURE_LATENCY) { @@ -3807,14 +3807,14 @@ public final class ViewAncestor extends Handler implements ViewParent, } static class InputMethodCallback extends IInputMethodCallback.Stub { - private WeakReference<ViewAncestor> mViewAncestor; + private WeakReference<ViewRootImpl> mViewAncestor; - public InputMethodCallback(ViewAncestor viewAncestor) { - mViewAncestor = new WeakReference<ViewAncestor>(viewAncestor); + public InputMethodCallback(ViewRootImpl viewAncestor) { + mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor); } public void finishedEvent(int seq, boolean handled) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchFinishedEvent(seq, handled); } @@ -3826,15 +3826,15 @@ public final class ViewAncestor extends Handler implements ViewParent, } static class W extends IWindow.Stub { - private final WeakReference<ViewAncestor> mViewAncestor; + private final WeakReference<ViewRootImpl> mViewAncestor; - W(ViewAncestor viewAncestor) { - mViewAncestor = new WeakReference<ViewAncestor>(viewAncestor); + W(ViewRootImpl viewAncestor) { + mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor); } public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw, Configuration newConfig) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(w, h, coveredInsets, visibleInsets, reportDraw, newConfig); @@ -3842,21 +3842,21 @@ public final class ViewAncestor extends Handler implements ViewParent, } public void dispatchAppVisibility(boolean visible) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchAppVisibility(visible); } } public void dispatchGetNewSurface() { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchGetNewSurface(); } } public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.windowFocusChanged(hasFocus, inTouchMode); } @@ -3872,7 +3872,7 @@ public final class ViewAncestor extends Handler implements ViewParent, } public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { final View view = viewAncestor.mView; if (view != null) { @@ -3903,7 +3903,7 @@ public final class ViewAncestor extends Handler implements ViewParent, } public void closeSystemDialogs(String reason) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchCloseSystemDialogs(reason); } @@ -3931,14 +3931,14 @@ public final class ViewAncestor extends Handler implements ViewParent, /* Drag/drop */ public void dispatchDragEvent(DragEvent event) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchDragEvent(event); } } public void dispatchSystemUiVisibilityChanged(int visibility) { - final ViewAncestor viewAncestor = mViewAncestor.get(); + final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchSystemUiVisibilityChanged(visibility); } @@ -4269,7 +4269,7 @@ public final class ViewAncestor extends Handler implements ViewParent, if (!registered) { mAttachInfo.mAccessibilityWindowId = mAccessibilityManager.addAccessibilityInteractionConnection(mWindow, - new AccessibilityInteractionConnection(ViewAncestor.this)); + new AccessibilityInteractionConnection(ViewRootImpl.this)); } } @@ -4289,10 +4289,10 @@ public final class ViewAncestor extends Handler implements ViewParent, */ final class AccessibilityInteractionConnection extends IAccessibilityInteractionConnection.Stub { - private final WeakReference<ViewAncestor> mViewAncestor; + private final WeakReference<ViewRootImpl> mViewAncestor; - AccessibilityInteractionConnection(ViewAncestor viewAncestor) { - mViewAncestor = new WeakReference<ViewAncestor>(viewAncestor); + AccessibilityInteractionConnection(ViewRootImpl viewAncestor) { + mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor); } public void findAccessibilityNodeInfoByAccessibilityId(int accessibilityId, @@ -4421,7 +4421,7 @@ public final class ViewAncestor extends Handler implements ViewParent, try { FindByAccessibilitytIdPredicate predicate = mFindByAccessibilityIdPredicate; predicate.init(accessibilityId); - View root = ViewAncestor.this.mView; + View root = ViewRootImpl.this.mView; View target = root.findViewByPredicate(predicate); if (target != null && target.isShown()) { info = target.createAccessibilityNodeInfo(); @@ -4453,7 +4453,7 @@ public final class ViewAncestor extends Handler implements ViewParent, AccessibilityNodeInfo info = null; try { - View root = ViewAncestor.this.mView; + View root = ViewRootImpl.this.mView; View target = root.findViewById(viewId); if (target != null && target.isShown()) { info = target.createAccessibilityNodeInfo(); @@ -4499,7 +4499,7 @@ public final class ViewAncestor extends Handler implements ViewParent, if (accessibilityViewId != View.NO_ID) { root = findViewByAccessibilityId(accessibilityViewId); } else { - root = ViewAncestor.this.mView; + root = ViewRootImpl.this.mView; } if (root == null || !root.isShown()) { @@ -4624,7 +4624,7 @@ public final class ViewAncestor extends Handler implements ViewParent, } private View findViewByAccessibilityId(int accessibilityId) { - View root = ViewAncestor.this.mView; + View root = ViewRootImpl.this.mView; if (root == null) { return null; } diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 54e7c04..a451bb5 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -16,18 +16,16 @@ package android.view; -import java.util.HashMap; - import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.IBinder; import android.util.AndroidRuntimeException; import android.util.Log; -import android.util.Slog; -import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import java.util.HashMap; + final class WindowLeaked extends AndroidRuntimeException { public WindowLeaked(String msg) { super(msg); @@ -80,7 +78,7 @@ public class WindowManagerImpl implements WindowManager { public static final int ADD_PERMISSION_DENIED = -8; private View[] mViews; - private ViewAncestor[] mRoots; + private ViewRootImpl[] mRoots; private WindowManager.LayoutParams[] mParams; private final static Object sLock = new Object(); @@ -204,7 +202,7 @@ public class WindowManagerImpl implements WindowManager { final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; - ViewAncestor root; + ViewRootImpl root; View panelParentView = null; synchronized (this) { @@ -241,7 +239,7 @@ public class WindowManagerImpl implements WindowManager { } } - root = new ViewAncestor(view.getContext()); + root = new ViewRootImpl(view.getContext()); root.mAddNesting = 1; if (cih == null) { root.mCompatibilityInfo = new CompatibilityInfoHolder(); @@ -254,7 +252,7 @@ public class WindowManagerImpl implements WindowManager { if (mViews == null) { index = 1; mViews = new View[1]; - mRoots = new ViewAncestor[1]; + mRoots = new ViewRootImpl[1]; mParams = new WindowManager.LayoutParams[1]; } else { index = mViews.length + 1; @@ -262,7 +260,7 @@ public class WindowManagerImpl implements WindowManager { mViews = new View[index]; System.arraycopy(old, 0, mViews, 0, index-1); old = mRoots; - mRoots = new ViewAncestor[index]; + mRoots = new ViewRootImpl[index]; System.arraycopy(old, 0, mRoots, 0, index-1); old = mParams; mParams = new WindowManager.LayoutParams[index]; @@ -290,7 +288,7 @@ public class WindowManagerImpl implements WindowManager { synchronized (this) { int index = findViewLocked(view, true); - ViewAncestor root = mRoots[index]; + ViewRootImpl root = mRoots[index]; mParams[index] = wparams; root.setLayoutParams(wparams, false); } @@ -312,7 +310,7 @@ public class WindowManagerImpl implements WindowManager { public void removeViewImmediate(View view) { synchronized (this) { int index = findViewLocked(view, true); - ViewAncestor root = mRoots[index]; + ViewRootImpl root = mRoots[index]; View curView = root.getView(); root.mAddNesting = 0; @@ -328,7 +326,7 @@ public class WindowManagerImpl implements WindowManager { } View removeViewLocked(int index) { - ViewAncestor root = mRoots[index]; + ViewRootImpl root = mRoots[index]; View view = root.getView(); // Don't really remove until we have matched all calls to add(). @@ -356,7 +354,7 @@ public class WindowManagerImpl implements WindowManager { removeItem(tmpViews, mViews, index); mViews = tmpViews; - ViewAncestor[] tmpRoots = new ViewAncestor[count-1]; + ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1]; removeItem(tmpRoots, mRoots, index); mRoots = tmpRoots; @@ -383,7 +381,7 @@ public class WindowManagerImpl implements WindowManager { //Log.i("foo", "@ " + i + " token " + mParams[i].token // + " view " + mRoots[i].getView()); if (token == null || mParams[i].token == token) { - ViewAncestor root = mRoots[i]; + ViewRootImpl root = mRoots[i]; root.mAddNesting = 1; //Log.i("foo", "Force closing " + root); @@ -402,7 +400,16 @@ public class WindowManagerImpl implements WindowManager { } } } - + + /** + * @param level See {@link android.content.ComponentCallbacks} + */ + public void trimMemory(int level) { + if (HardwareRenderer.isAvailable()) { + HardwareRenderer.trimMemory(level); + } + } + public void setStoppedState(IBinder token, boolean stopped) { synchronized (this) { if (mViews == null) @@ -410,7 +417,7 @@ public class WindowManagerImpl implements WindowManager { int count = mViews.length; for (int i=0; i<count; i++) { if (token == null || mParams[i].token == token) { - ViewAncestor root = mRoots[i]; + ViewRootImpl root = mRoots[i]; root.setStopped(stopped); } } @@ -422,7 +429,7 @@ public class WindowManagerImpl implements WindowManager { int count = mViews.length; config = new Configuration(config); for (int i=0; i<count; i++) { - ViewAncestor root = mRoots[i]; + ViewRootImpl root = mRoots[i]; root.requestUpdateConfiguration(config); } } @@ -430,13 +437,13 @@ public class WindowManagerImpl implements WindowManager { public WindowManager.LayoutParams getRootViewLayoutParameter(View view) { ViewParent vp = view.getParent(); - while (vp != null && !(vp instanceof ViewAncestor)) { + while (vp != null && !(vp instanceof ViewRootImpl)) { vp = vp.getParent(); } if (vp == null) return null; - ViewAncestor vr = (ViewAncestor)vp; + ViewRootImpl vr = (ViewRootImpl)vp; int N = mRoots.length; for (int i = 0; i < N; ++i) { @@ -456,8 +463,7 @@ public class WindowManagerImpl implements WindowManager { return new Display(Display.DEFAULT_DISPLAY, null); } - private static void removeItem(Object[] dst, Object[] src, int index) - { + private static void removeItem(Object[] dst, Object[] src, int index) { if (dst.length > 0) { if (index > 0) { System.arraycopy(src, 0, dst, 0, index); @@ -468,8 +474,7 @@ public class WindowManagerImpl implements WindowManager { } } - private int findViewLocked(View view, boolean required) - { + private int findViewLocked(View view, boolean required) { synchronized (this) { final int count = mViews != null ? mViews.length : 0; for (int i=0; i<count; i++) { diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index ac86769..9be2a67 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -552,7 +552,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par /** * Returns a cached instance if such is available or a new one is - * initialized with from the given <code>event</code>. + * created. The returned instance is initialized from the given + * <code>event</code>. * * @param event The other event. * @return An instance. diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 314b7ca..83c73cb 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -71,7 +71,9 @@ public final class AccessibilityManager { private static AccessibilityManager sInstance; - private static final int DO_SET_ENABLED = 10; + private static final int DO_SET_ACCESSIBILITY_ENABLED = 10; + + private static final int DO_SET_TOUCH_EXPLORATION_ENABLED = 20; final IAccessibilityManager mService; @@ -79,6 +81,8 @@ public final class AccessibilityManager { boolean mIsEnabled; + boolean mIsTouchExplorationEnabled; + final CopyOnWriteArrayList<AccessibilityStateChangeListener> mAccessibilityStateChangeListeners = new CopyOnWriteArrayList<AccessibilityStateChangeListener>(); @@ -97,7 +101,12 @@ public final class AccessibilityManager { final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { public void setEnabled(boolean enabled) { - mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); + mHandler.obtainMessage(DO_SET_ACCESSIBILITY_ENABLED, enabled ? 1 : 0, 0).sendToTarget(); + } + + public void setTouchExplorationEnabled(boolean enabled) { + mHandler.obtainMessage(DO_SET_TOUCH_EXPLORATION_ENABLED, + enabled ? 1 : 0, 0).sendToTarget(); } }; @@ -110,9 +119,14 @@ public final class AccessibilityManager { @Override public void handleMessage(Message message) { switch (message.what) { - case DO_SET_ENABLED : - final boolean isEnabled = (message.arg1 == 1); - setAccessibilityState(isEnabled); + case DO_SET_ACCESSIBILITY_ENABLED : + final boolean isAccessibilityEnabled = (message.arg1 == 1); + setAccessibilityState(isAccessibilityEnabled); + return; + case DO_SET_TOUCH_EXPLORATION_ENABLED : + synchronized (mHandler) { + mIsTouchExplorationEnabled = (message.arg1 == 1); + } return; default : Log.w(LOG_TAG, "Unknown message type: " + message.what); @@ -168,6 +182,17 @@ public final class AccessibilityManager { } /** + * Returns if the touch exploration in the system is enabled. + * + * @return True if touch exploration is enabled, false otherwise. + */ + public boolean isTouchExplorationEnabled() { + synchronized (mHandler) { + return mIsTouchExplorationEnabled; + } + } + + /** * Returns the client interface this instance registers in * the centralized accessibility manager service. * diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 031c6ae..0e04471 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -120,7 +120,7 @@ public class AccessibilityNodeInfo implements Parcelable { private CharSequence mText; private CharSequence mContentDescription; - private final SparseIntArray mChildAccessibilityIds = new SparseIntArray(); + private SparseIntArray mChildAccessibilityIds = new SparseIntArray(); private int mActions; private IAccessibilityServiceConnection mConnection; @@ -873,6 +873,20 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Returns a cached instance if such is available or a new one is + * create. The returned instance is initialized from the given + * <code>info</code>. + * + * @param info The other info. + * @return An instance. + */ + public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) { + AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain(); + infoClone.init(info); + return infoClone; + } + + /** * Return an instance back to be reused. * <p> * <strong>Note:</strong> You must not touch the object after calling this function. @@ -945,6 +959,28 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Initializes this instance from another one. + * + * @param other The other instance. + */ + private void init(AccessibilityNodeInfo other) { + mSealed = other.mSealed; + mConnection = other.mConnection; + mAccessibilityViewId = other.mAccessibilityViewId; + mParentAccessibilityViewId = other.mParentAccessibilityViewId; + mAccessibilityWindowId = other.mAccessibilityWindowId; + mBoundsInParent.set(other.mBoundsInParent); + mBoundsInScreen.set(other.mBoundsInScreen); + mPackageName = other.mPackageName; + mClassName = other.mClassName; + mText = other.mText; + mContentDescription = other.mContentDescription; + mActions= other.mActions; + mBooleanProperties = other.mBooleanProperties; + mChildAccessibilityIds = other.mChildAccessibilityIds.clone(); + } + + /** * Creates a new instance from a {@link Parcel}. * * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}. @@ -994,6 +1030,7 @@ public class AccessibilityNodeInfo implements Parcelable { mConnection = null; mAccessibilityViewId = View.NO_ID; mParentAccessibilityViewId = View.NO_ID; + mAccessibilityWindowId = View.NO_ID; mChildAccessibilityIds.clear(); mBoundsInParent.set(0, 0, 0, 0); mBoundsInScreen.set(0, 0, 0, 0); diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java index f4d5e89..210106f 100644 --- a/core/java/android/view/accessibility/AccessibilityRecord.java +++ b/core/java/android/view/accessibility/AccessibilityRecord.java @@ -50,7 +50,7 @@ import java.util.List; */ public class AccessibilityRecord { - private static final int INVALID_POSITION = -1; + private static final int UNDEFINED = -1; private static final int PROPERTY_CHECKED = 0x00000001; private static final int PROPERTY_ENABLED = 0x00000002; @@ -68,15 +68,15 @@ public class AccessibilityRecord { boolean mSealed; int mBooleanProperties; - int mCurrentItemIndex; - int mItemCount; - int mFromIndex; - int mToIndex; - int mScrollX; - int mScrollY; - - int mAddedCount; - int mRemovedCount; + int mCurrentItemIndex = UNDEFINED; + int mItemCount = UNDEFINED; + int mFromIndex = UNDEFINED; + int mToIndex = UNDEFINED; + int mScrollX = UNDEFINED; + int mScrollY = UNDEFINED; + + int mAddedCount= UNDEFINED; + int mRemovedCount = UNDEFINED; int mSourceViewId = View.NO_ID; int mSourceWindowId = View.NO_ID; @@ -681,14 +681,14 @@ public class AccessibilityRecord { void clear() { mSealed = false; mBooleanProperties = 0; - mCurrentItemIndex = INVALID_POSITION; - mItemCount = 0; - mFromIndex = 0; - mToIndex = 0; - mScrollX = 0; - mScrollY = 0; - mAddedCount = 0; - mRemovedCount = 0; + mCurrentItemIndex = UNDEFINED; + mItemCount = UNDEFINED; + mFromIndex = UNDEFINED; + mToIndex = UNDEFINED; + mScrollX = UNDEFINED; + mScrollY = UNDEFINED; + mAddedCount = UNDEFINED; + mRemovedCount = UNDEFINED; mClassName = null; mContentDescription = null; mBeforeText = null; diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl index 1eb60fc..4e69692 100644 --- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl @@ -26,4 +26,5 @@ oneway interface IAccessibilityManagerClient { void setEnabled(boolean enabled); + void setTouchExplorationEnabled(boolean enabled); } diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index abe3c2c..5ec1ec3 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -34,7 +34,7 @@ import android.util.LogPrinter; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; class ComposingText implements NoCopySpan { } @@ -502,7 +502,7 @@ public class BaseInputConnection implements InputConnection { } } if (h != null) { - h.sendMessage(h.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME, + h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME, event)); } } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index a1a7281..da5baf8 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -26,6 +26,7 @@ import com.android.internal.view.IInputMethodSession; import com.android.internal.view.InputBindResult; import android.content.Context; +import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; @@ -42,7 +43,7 @@ import android.util.Printer; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -655,7 +656,7 @@ public final class InputMethodManager { if (vh != null) { // This will result in a call to reportFinishInputConnection() // below. - vh.sendMessage(vh.obtainMessage(ViewAncestor.FINISH_INPUT_CONNECTION, + vh.sendMessage(vh.obtainMessage(ViewRootImpl.FINISH_INPUT_CONNECTION, mServedInputConnection)); } } @@ -1112,9 +1113,9 @@ public final class InputMethodManager { void scheduleCheckFocusLocked(View view) { Handler vh = view.getHandler(); - if (vh != null && !vh.hasMessages(ViewAncestor.CHECK_FOCUS)) { + if (vh != null && !vh.hasMessages(ViewRootImpl.CHECK_FOCUS)) { // This will result in a call to checkFocus() below. - vh.sendMessage(vh.obtainMessage(ViewAncestor.CHECK_FOCUS)); + vh.sendMessage(vh.obtainMessage(ViewRootImpl.CHECK_FOCUS)); } } @@ -1580,16 +1581,16 @@ public final class InputMethodManager { } /** - * Set additional input method subtypes. - * @param imeToken Supplies the identifying token given to an input method. + * Set additional input method subtypes. Only a process which shares the same uid with the IME + * can add additional input method subtypes to the IME. + * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to. * @param subtypes subtypes will be added as additional subtypes of the current input method. * @return true if the additional input method subtypes are successfully added. */ - public boolean setAdditionalInputMethodSubtypes( - IBinder imeToken, InputMethodSubtype[] subtypes) { + public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) { synchronized (mH) { try { - return mService.setAdditionalInputMethodSubtypes(imeToken, subtypes); + return mService.setAdditionalInputMethodSubtypes(imiId, subtypes); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); return false; diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 5aa60f4..738bcb9 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -35,7 +35,7 @@ import android.os.Message; import android.util.Log; import android.util.TypedValue; import android.view.Surface; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import android.view.WindowManager; import junit.framework.Assert; @@ -228,7 +228,7 @@ class BrowserFrame extends Handler { sConfigCallback = new ConfigCallback( (WindowManager) appContext.getSystemService( Context.WINDOW_SERVICE)); - ViewAncestor.addConfigCallback(sConfigCallback); + ViewRootImpl.addConfigCallback(sConfigCallback); } sConfigCallback.addHandler(this); diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 761007f..d584acd 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -1783,6 +1783,20 @@ public class WebSettings { } /** + * @hide + */ + public void setProperty(String key, String value) { + mWebView.nativeSetProperty(key, value); + } + + /** + * @hide + */ + public String getProperty(String key) { + return mWebView.nativeGetProperty(key); + } + + /** * Transfer messages from the queue to the new WebCoreThread. Called from * WebCore thread. */ diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 3ae10fe..b22c57b 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -9289,4 +9289,6 @@ public class WebView extends AbsoluteLayout */ private native boolean nativeScrollLayer(int layer, int newX, int newY); private native int nativeGetBackgroundColor(); + native void nativeSetProperty(String key, String value); + native String nativeGetProperty(String key); } diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java index 32c44d8..d7429b3 100644 --- a/core/java/android/widget/ActivityChooserModel.java +++ b/core/java/android/widget/ActivityChooserModel.java @@ -431,7 +431,6 @@ public class ActivityChooserModel extends DataSetObservable { */ public Intent chooseActivity(int index) { ActivityResolveInfo chosenActivity = mActivites.get(index); - ActivityResolveInfo defaultActivity = mActivites.get(0); ComponentName chosenName = new ComponentName( chosenActivity.resolveInfo.activityInfo.packageName, diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java index f500b39..5b69aa8 100644 --- a/core/java/android/widget/ActivityChooserView.java +++ b/core/java/android/widget/ActivityChooserView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Resources; import android.content.res.TypedArray; import android.database.DataSetObserver; import android.graphics.Canvas; @@ -92,6 +93,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod private final ImageButton mDefaultActionButton; /** + * The maximal width of the list popup. + */ + private final int mListPopupMaxWidth; + + /** * Observer for the model data. */ private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { @@ -185,7 +191,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod mExpandActivityOverflowButton = (ImageButton) findViewById(R.id.expand_activities_button); mExpandActivityOverflowButton.setOnClickListener(mCallbacks); - mExpandActivityOverflowButton.setBackgroundDrawable(expandActivityOverflowButtonDrawable); + mExpandActivityOverflowButton.setImageDrawable(expandActivityOverflowButtonDrawable); mAdapter = new ActivityChooserViewAdapter(); mAdapter.registerDataSetObserver(new DataSetObserver() { @@ -195,6 +201,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod updateButtons(); } }); + + Resources resources = context.getResources(); + mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2, + resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth)); } /** @@ -220,7 +230,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod * @param drawable The drawable. */ public void setExpandActivityOverflowButtonDrawable(Drawable drawable) { - mExpandActivityOverflowButton.setBackgroundDrawable(drawable); + mExpandActivityOverflowButton.setImageDrawable(drawable); } /** @@ -264,7 +274,8 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod } else { mAdapter.setShowDefaultActivity(false); } - popupWindow.setContentWidth(mAdapter.measureContentWidth()); + final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth); + popupWindow.setContentWidth(contentWidth); popupWindow.show(); } } @@ -390,7 +401,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod } ResolveInfo activity = mAdapter.getDefaultActivity(); PackageManager packageManager = mContext.getPackageManager(); - mDefaultActionButton.setBackgroundDrawable(activity.loadIcon(packageManager)); + mDefaultActionButton.setImageDrawable(activity.loadIcon(packageManager)); } else { mDefaultActionButton.setVisibility(View.INVISIBLE); mExpandActivityOverflowButton.setEnabled(false); @@ -574,7 +585,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod // Set the icon ImageView iconView = (ImageView) convertView.findViewById(R.id.icon); ResolveInfo activity = (ResolveInfo) getItem(position); - iconView.setBackgroundDrawable(activity.loadIcon(packageManager)); + iconView.setImageDrawable(activity.loadIcon(packageManager)); // Set the title. TextView titleView = (TextView) convertView.findViewById(R.id.title); titleView.setText(activity.loadLabel(packageManager)); diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java index 8d4aaea..49616cc 100644 --- a/core/java/android/widget/CheckedTextView.java +++ b/core/java/android/widget/CheckedTextView.java @@ -130,10 +130,10 @@ public class CheckedTextView extends TextView implements Checkable { setMinHeight(d.getIntrinsicHeight()); mCheckMarkWidth = d.getIntrinsicWidth(); - mPaddingRight = mCheckMarkWidth + mBasePaddingRight; + mUserPaddingRight = mCheckMarkWidth + mBasePaddingRight; d.setState(getDrawableState()); } else { - mPaddingRight = mBasePaddingRight; + mUserPaddingRight = mBasePaddingRight; } mCheckMarkDrawable = d; requestLayout(); @@ -142,7 +142,7 @@ public class CheckedTextView extends TextView implements Checkable { @Override public void setPadding(int left, int top, int right, int bottom) { super.setPadding(left, top, right, bottom); - mBasePaddingRight = mPaddingRight; + mBasePaddingRight = mUserPaddingRight; } @Override @@ -167,9 +167,9 @@ public class CheckedTextView extends TextView implements Checkable { int right = getWidth(); checkMarkDrawable.setBounds( - right - mCheckMarkWidth - mBasePaddingRight, + right - mUserPaddingRight, y, - right - mBasePaddingRight, + right - mUserPaddingRight + mCheckMarkWidth, y + height); checkMarkDrawable.draw(canvas); } diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 2410eb2..d3cdad8 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -217,6 +217,7 @@ public abstract class CompoundButton extends Button implements Checkable { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); + info.setCheckable(true); info.setChecked(mChecked); } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index b9eb5ff..6df8efb 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -28,7 +28,7 @@ import android.util.Pair; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; -import com.android.internal.R.styleable; +import com.android.internal.R; import java.lang.reflect.Array; import java.util.ArrayList; @@ -167,7 +167,7 @@ public class GridLayout extends ViewGroup { // Misc constants private static final String TAG = GridLayout.class.getName(); - static final boolean DEBUG = false; + static boolean DEBUG = false; private static final int PRF = 1; // Defaults @@ -178,19 +178,17 @@ public class GridLayout extends ViewGroup { private static final boolean DEFAULT_ORDER_PRESERVED = false; private static final int DEFAULT_ALIGNMENT_MODE = ALIGN_MARGINS; private static final int DEFAULT_CONTAINER_MARGIN = 0; - private static final int DEFAULT_MARGIN = 8; - private static final int DEFAULT_CONTAINER_PADDING = 16; private static final int MAX_SIZE = 100000; // TypedArray indices - private static final int ORIENTATION = styleable.GridLayout_orientation; - private static final int ROW_COUNT = styleable.GridLayout_rowCount; - private static final int COLUMN_COUNT = styleable.GridLayout_columnCount; - private static final int USE_DEFAULT_MARGINS = styleable.GridLayout_useDefaultMargins; - private static final int ALIGNMENT_MODE = styleable.GridLayout_alignmentMode; - private static final int ROW_ORDER_PRESERVED = styleable.GridLayout_rowOrderPreserved; - private static final int COLUMN_ORDER_PRESERVED = styleable.GridLayout_columnOrderPreserved; + private static final int ORIENTATION = R.styleable.GridLayout_orientation; + private static final int ROW_COUNT = R.styleable.GridLayout_rowCount; + private static final int COLUMN_COUNT = R.styleable.GridLayout_columnCount; + private static final int USE_DEFAULT_MARGINS = R.styleable.GridLayout_useDefaultMargins; + private static final int ALIGNMENT_MODE = R.styleable.GridLayout_alignmentMode; + private static final int ROW_ORDER_PRESERVED = R.styleable.GridLayout_rowOrderPreserved; + private static final int COLUMN_ORDER_PRESERVED = R.styleable.GridLayout_columnOrderPreserved; // Instance variables @@ -201,6 +199,7 @@ public class GridLayout extends ViewGroup { private boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS; private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE; private int mDefaultGravity = Gravity.NO_GRAVITY; + private int mDefaultGap; // Constructors @@ -212,7 +211,8 @@ public class GridLayout extends ViewGroup { if (DEBUG) { setWillNotDraw(false); } - TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout); + mDefaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout); try { setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT)); setColumnCount(a.getInt(COLUMN_COUNT, DEFAULT_COUNT)); @@ -382,7 +382,7 @@ public class GridLayout extends ViewGroup { public void setUseDefaultMargins(boolean useDefaultMargins) { mUseDefaultMargins = useDefaultMargins; if (useDefaultMargins) { - int padding = DEFAULT_CONTAINER_PADDING; + int padding = mDefaultGap; setPadding(padding, padding, padding, padding); } requestLayout(); @@ -538,7 +538,7 @@ public class GridLayout extends ViewGroup { } private int getDefaultMargin(View c, boolean horizontal, boolean leading) { - return DEFAULT_MARGIN; + return mDefaultGap / 2; } private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) { @@ -758,32 +758,14 @@ public class GridLayout extends ViewGroup { // Add/remove @Override - public void addView(View child, int index, ViewGroup.LayoutParams params) { - super.addView(child, index, params); + protected void onViewAdded(View child) { + super.onViewAdded(child); invalidateStructure(); } @Override - public void removeView(View view) { - super.removeView(view); - invalidateStructure(); - } - - @Override - public void removeViewInLayout(View view) { - super.removeViewInLayout(view); - invalidateStructure(); - } - - @Override - public void removeViewsInLayout(int start, int count) { - super.removeViewsInLayout(start, count); - invalidateStructure(); - } - - @Override - public void removeViewAt(int index) { - super.removeViewAt(index); + protected void onViewRemoved(View child) { + super.onViewRemoved(child); invalidateStructure(); } @@ -1596,8 +1578,8 @@ public class GridLayout extends ViewGroup { * each cell group. The fundamental parameters associated with each cell group are * gathered into their vertical and horizontal components and stored * in the {@link #rowSpec} and {@link #columnSpec} layout parameters. - * {@link android.widget.GridLayout.Spec Specs} are immutable structures and may be shared between the layout - * parameters of different children. + * {@link android.widget.GridLayout.Spec Specs} are immutable structures + * and may be shared between the layout parameters of different children. * <p> * The row and column specs contain the leading and trailing indices along each axis * and together specify the four grid indices that delimit the cells of this cell group. @@ -1667,24 +1649,25 @@ public class GridLayout extends ViewGroup { // TypedArray indices - private static final int MARGIN = styleable.ViewGroup_MarginLayout_layout_margin; - private static final int LEFT_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginLeft; - private static final int TOP_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginTop; - private static final int RIGHT_MARGIN = styleable.ViewGroup_MarginLayout_layout_marginRight; + private static final int MARGIN = R.styleable.ViewGroup_MarginLayout_layout_margin; + private static final int LEFT_MARGIN = R.styleable.ViewGroup_MarginLayout_layout_marginLeft; + private static final int TOP_MARGIN = R.styleable.ViewGroup_MarginLayout_layout_marginTop; + private static final int RIGHT_MARGIN = + R.styleable.ViewGroup_MarginLayout_layout_marginRight; private static final int BOTTOM_MARGIN = - styleable.ViewGroup_MarginLayout_layout_marginBottom; + R.styleable.ViewGroup_MarginLayout_layout_marginBottom; - private static final int COLUMN = styleable.GridLayout_Layout_layout_column; - private static final int COLUMN_SPAN = styleable.GridLayout_Layout_layout_columnSpan; + private static final int COLUMN = R.styleable.GridLayout_Layout_layout_column; + private static final int COLUMN_SPAN = R.styleable.GridLayout_Layout_layout_columnSpan; private static final int COLUMN_FLEXIBILITY = - styleable.GridLayout_Layout_layout_columnFlexibility; + R.styleable.GridLayout_Layout_layout_columnFlexibility; - private static final int ROW = styleable.GridLayout_Layout_layout_row; - private static final int ROW_SPAN = styleable.GridLayout_Layout_layout_rowSpan; + private static final int ROW = R.styleable.GridLayout_Layout_layout_row; + private static final int ROW_SPAN = R.styleable.GridLayout_Layout_layout_rowSpan; private static final int ROW_FLEXIBILITY = - styleable.GridLayout_Layout_layout_rowFlexibility; + R.styleable.GridLayout_Layout_layout_rowFlexibility; - private static final int GRAVITY = styleable.GridLayout_Layout_layout_gravity; + private static final int GRAVITY = R.styleable.GridLayout_Layout_layout_gravity; // Instance variables @@ -1804,7 +1787,8 @@ public class GridLayout extends ViewGroup { // This method could be parametrized and moved into MarginLayout. private void reInitSuper(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, styleable.ViewGroup_MarginLayout); + TypedArray a = + context.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout); try { int margin = a.getDimensionPixelSize(MARGIN, DEFAULT_MARGIN); @@ -1840,7 +1824,7 @@ public class GridLayout extends ViewGroup { } private void init(Context context, AttributeSet attrs, int defaultGravity) { - TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout_Layout); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout_Layout); try { int gravity = a.getInt(GRAVITY, defaultGravity); @@ -2293,25 +2277,6 @@ public class GridLayout extends ViewGroup { } /** - * Temporary backward compatibility class for Launcher - to avoid - * dependent multi-project commit. This class will be deleted after - * AppsCustomizePagedView is updated to new API. - * - * @hide - */ - @Deprecated - public static class Group extends Spec { - /** - * @deprecated Please replace with {@link #spec(int, int, Alignment)} - * @hide - */ - @Deprecated - public Group(int start, int size, Alignment alignment) { - super(start, size, alignment, UNDEFINED_FLEXIBILITY); - } - } - - /** * Return a Spec, {@code spec}, where: * <ul> * <li> {@code spec.span = [start, start + size]} </li> diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 5642877..f057d07 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -62,6 +62,7 @@ public class ListPopupWindow { private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT; private int mDropDownHorizontalOffset; private int mDropDownVerticalOffset; + private boolean mDropDownVerticalOffsetSet; private boolean mDropDownAlwaysVisible = false; private boolean mForceIgnoreOutsideTouch = false; @@ -404,6 +405,9 @@ public class ListPopupWindow { * @return The vertical offset of the popup from its anchor in pixels. */ public int getVerticalOffset() { + if (!mDropDownVerticalOffsetSet) { + return 0; + } return mDropDownVerticalOffset; } @@ -414,6 +418,7 @@ public class ListPopupWindow { */ public void setVerticalOffset(int offset) { mDropDownVerticalOffset = offset; + mDropDownVerticalOffsetSet = true; } /** @@ -1061,21 +1066,27 @@ public class ListPopupWindow { } } - // Max height available on the screen for a popup. - boolean ignoreBottomDecorations = - mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; - final int maxHeight = mPopup.getMaxAvailableHeight( - getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations); - - // getMaxAvailableHeight() subtracts the padding, so we put it back, + // getMaxAvailableHeight() subtracts the padding, so we put it back // to get the available height for the whole window int padding = 0; Drawable background = mPopup.getBackground(); if (background != null) { background.getPadding(mTempRect); padding = mTempRect.top + mTempRect.bottom; + + // If we don't have an explicit vertical offset, determine one from the window + // background so that content will line up. + if (!mDropDownVerticalOffsetSet) { + mDropDownVerticalOffset = -mTempRect.top; + } } + // Max height available on the screen for a popup. + boolean ignoreBottomDecorations = + mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; + final int maxHeight = mPopup.getMaxAvailableHeight( + getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations); + if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { return maxHeight + padding; } diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index f3bda43..b2d1a1e 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -18,8 +18,6 @@ package android.widget; import static android.widget.SuggestionsAdapter.getColumnString; -import com.android.internal.R; - import android.app.PendingIntent; import android.app.SearchManager; import android.app.SearchableInfo; @@ -39,10 +37,14 @@ import android.net.Uri; import android.os.Bundle; import android.speech.RecognizerIntent; import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.ImageSpan; import android.util.AttributeSet; import android.util.Log; +import android.util.TypedValue; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; @@ -51,6 +53,8 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.TextView.OnEditorActionListener; +import com.android.internal.R; + import java.util.WeakHashMap; /** @@ -87,6 +91,8 @@ public class SearchView extends LinearLayout { private View mSearchEditFrame; private View mVoiceButton; private SearchAutoComplete mQueryTextView; + private View mDropDownAnchor; + private ImageView mSearchHintIcon; private boolean mSubmitButtonEnabled; private CharSequence mQueryHint; private boolean mQueryRefinement; @@ -195,6 +201,7 @@ public class SearchView extends LinearLayout { mSubmitButton = findViewById(R.id.search_go_btn); mCloseButton = (ImageView) findViewById(R.id.search_close_btn); mVoiceButton = findViewById(R.id.search_voice_btn); + mSearchHintIcon = (ImageView) findViewById(R.id.search_mag_icon); mSearchButton.setOnClickListener(mOnClickListener); mCloseButton.setOnClickListener(mOnClickListener); @@ -244,7 +251,20 @@ public class SearchView extends LinearLayout { mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor()); + if (mDropDownAnchor != null) { + mDropDownAnchor.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) { + adjustDropDownSizeAndPosition(); + } + + }); + } + updateViewsVisibility(mIconifiedByDefault); + updateQueryHint(); } /** @@ -263,7 +283,7 @@ public class SearchView extends LinearLayout { } // Cache the voice search capability mVoiceButtonEnabled = hasVoiceSearch(); - updateViewsVisibility(mIconifiedByDefault); + updateViewsVisibility(isIconified()); } /** @@ -300,7 +320,6 @@ public class SearchView extends LinearLayout { mQueryTextView.clearFocus(); setImeVisibility(false); mClearingFocus = false; - updateViewsVisibility(mIconifiedByDefault); } /** @@ -555,6 +574,7 @@ public class SearchView extends LinearLayout { mSearchButton.setVisibility(visCollapsed); updateSubmitButton(hasText); mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); + mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE); updateCloseButton(); updateVoiceButton(!hasText); updateSubmitArea(); @@ -822,9 +842,29 @@ public class SearchView extends LinearLayout { return result; } + private int getSearchIconId() { + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(com.android.internal.R.attr.searchViewSearchIcon, + outValue, true); + return outValue.resourceId; + } + + private CharSequence getDecoratedHint(CharSequence hintText) { + // If the field is always expanded, then don't add the search icon to the hint + if (!mIconifiedByDefault) return hintText; + + SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon + ssb.append(hintText); + Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId()); + int textSize = (int) (mQueryTextView.getTextSize() * 1.25); + searchIcon.setBounds(0, 0, textSize, textSize); + ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return ssb; + } + private void updateQueryHint() { if (mQueryHint != null) { - mQueryTextView.setHint(mQueryHint); + mQueryTextView.setHint(getDecoratedHint(mQueryHint)); } else if (mSearchable != null) { CharSequence hint = null; int hintId = mSearchable.getHintId(); @@ -832,8 +872,10 @@ public class SearchView extends LinearLayout { hint = getContext().getString(hintId); } if (hint != null) { - mQueryTextView.setHint(hint); + mQueryTextView.setHint(getDecoratedHint(hint)); } + } else { + mQueryTextView.setHint(getDecoratedHint("")); } } @@ -922,9 +964,13 @@ public class SearchView extends LinearLayout { CharSequence text = mQueryTextView.getText(); if (TextUtils.isEmpty(text)) { if (mIconifiedByDefault) { - // query field already empty, hide the keyboard and remove focus - clearFocus(); - setImeVisibility(false); + // If the app doesn't override the close behavior + if (mOnCloseListener == null || !mOnCloseListener.onClose()) { + // hide the keyboard and remove focus + clearFocus(); + // collapse the search field + updateViewsVisibility(true); + } } } else { mQueryTextView.setText(""); @@ -932,10 +978,6 @@ public class SearchView extends LinearLayout { setImeVisibility(true); } - if (mIconifiedByDefault && (mOnCloseListener == null || !mOnCloseListener.onClose())) { - updateViewsVisibility(mIconifiedByDefault); - setImeVisibility(false); - } } private void onSearchClicked() { @@ -975,6 +1017,28 @@ public class SearchView extends LinearLayout { updateFocusedState(mQueryTextView.hasFocus()); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + private void adjustDropDownSizeAndPosition() { + if (mDropDownAnchor.getWidth() > 1) { + Resources res = getContext().getResources(); + int anchorPadding = mSearchPlate.getPaddingLeft(); + Rect dropDownPadding = new Rect(); + int iconOffset = mIconifiedByDefault + ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width) + + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left) + : 0; + mQueryTextView.getDropDownBackground().getPadding(dropDownPadding); + mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset) + + anchorPadding); + mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left + + dropDownPadding.right + iconOffset - (anchorPadding)); + } + } + private boolean onItemClicked(int position, int actionKey, String actionMsg) { if (mOnSuggestionListener == null || !mOnSuggestionListener.onSuggestionClick(position)) { @@ -1393,5 +1457,32 @@ public class SearchView extends LinearLayout { public boolean enoughToFilter() { return mThreshold <= 0 || super.enoughToFilter(); } + + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + // special case for the back key, we do not even try to send it + // to the drop down list but instead, consume it immediately + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } + if (event.isTracking() && !event.isCanceled()) { + mSearchView.clearFocus(); + mSearchView.setImeVisibility(false); + return true; + } + } + } + return super.onKeyPreIme(keyCode, event); + } + } } diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java index 2e0cc62..665109a 100644 --- a/core/java/android/widget/ShareActionProvider.java +++ b/core/java/android/widget/ShareActionProvider.java @@ -162,14 +162,17 @@ public class ShareActionProvider extends ActionProvider { .setOnMenuItemClickListener(mOnMenuItemClickListener); } - // Add a sub-menu for showing all activities as a list item. - SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount, - collapsedActivityCount, mContext.getString(R.string.activity_chooser_view_see_all)); - for (int i = 0; i < expandedActivityCount; i++) { - ResolveInfo activity = dataModel.getActivity(i); - expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager)) - .setIcon(activity.loadIcon(packageManager)) - .setOnMenuItemClickListener(mOnMenuItemClickListener); + if (collapsedActivityCount < expandedActivityCount) { + // Add a sub-menu for showing all activities as a list item. + SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount, + collapsedActivityCount, + mContext.getString(R.string.activity_chooser_view_see_all)); + for (int i = 0; i < expandedActivityCount; i++) { + ResolveInfo activity = dataModel.getActivity(i); + expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager)) + .setIcon(activity.loadIcon(packageManager)) + .setOnMenuItemClickListener(mOnMenuItemClickListener); + } } } diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index 485c678..2fba18b 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -165,10 +165,17 @@ public class Spinner extends AbsSpinner implements OnClickListener { ViewGroup.LayoutParams.WRAP_CONTENT); popup.setBackgroundDrawable(a.getDrawable( com.android.internal.R.styleable.Spinner_popupBackground)); - popup.setVerticalOffset(a.getDimensionPixelOffset( - com.android.internal.R.styleable.Spinner_dropDownVerticalOffset, 0)); - popup.setHorizontalOffset(a.getDimensionPixelOffset( - com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0)); + final int verticalOffset = a.getDimensionPixelOffset( + com.android.internal.R.styleable.Spinner_dropDownVerticalOffset, 0); + if (verticalOffset != 0) { + popup.setVerticalOffset(verticalOffset); + } + + final int horizontalOffset = a.getDimensionPixelOffset( + com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0); + if (horizontalOffset != 0) { + popup.setHorizontalOffset(horizontalOffset); + } mPopup = popup; break; diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java index 2cfc016..9e32c9a 100644 --- a/core/java/android/widget/SuggestionsAdapter.java +++ b/core/java/android/widget/SuggestionsAdapter.java @@ -16,8 +16,6 @@ package android.widget; -import com.android.internal.R; - import android.app.SearchDialog; import android.app.SearchManager; import android.app.SearchableInfo; @@ -47,6 +45,8 @@ import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; +import com.android.internal.R; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -88,8 +88,8 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene private int mIconName2Col = INVALID_INDEX; private int mFlagsCol = INVALID_INDEX; - private final Runnable mStartSpinnerRunnable; - private final Runnable mStopSpinnerRunnable; + // private final Runnable mStartSpinnerRunnable; + // private final Runnable mStopSpinnerRunnable; /** * The amount of time we delay in the filter when the user presses the delete key. @@ -113,17 +113,18 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene mOutsideDrawablesCache = outsideDrawablesCache; - mStartSpinnerRunnable = new Runnable() { - public void run() { - // mSearchView.setWorking(true); // TODO: - } - }; - mStopSpinnerRunnable = new Runnable() { - public void run() { - // mSearchView.setWorking(false); // TODO: - } - }; + // mStartSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(true); // TODO: + // } + // }; + // + // mStopSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(false); // TODO: + // } + // }; // delay 500ms when deleting getFilter().setDelayer(new Filter.Delayer() { @@ -341,10 +342,10 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene } if (views.mIcon1 != null) { - setViewDrawable(views.mIcon1, getIcon1(cursor)); + setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE); } if (views.mIcon2 != null) { - setViewDrawable(views.mIcon2, getIcon2(cursor)); + setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE); } if (mQueryRefinement == REFINE_ALL || (mQueryRefinement == REFINE_BY_ENTRY @@ -414,13 +415,13 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene * Sets the drawable in an image view, makes sure the view is only visible if there * is a drawable. */ - private void setViewDrawable(ImageView v, Drawable drawable) { + private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) { // Set the icon even if the drawable is null, since we need to clear any // previous icon. v.setImageDrawable(drawable); if (drawable == null) { - v.setVisibility(View.GONE); + v.setVisibility(nullVisibility); } else { v.setVisibility(View.VISIBLE); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index ecbd997..66a07d3 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -117,7 +117,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import android.view.ViewConfiguration; import android.view.ViewDebug; import android.view.ViewGroup; @@ -3731,13 +3731,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Handler h = getHandler(); if (h != null) { long eventTime = SystemClock.uptimeMillis(); - h.sendMessage(h.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME, + h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME, new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.FLAG_EDITOR_ACTION))); - h.sendMessage(h.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME, + h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME, new KeyEvent(SystemClock.uptimeMillis(), eventTime, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, @@ -6586,11 +6586,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener scrollx = left; } } - } else if (a == Layout.Alignment.ALIGN_LEFT) { - scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line)); - } else { // a == Layout.Alignment.ALIGN_RIGHT + } else if (a == Layout.Alignment.ALIGN_RIGHT) { int right = (int) FloatMath.ceil(mLayout.getLineRight(line)); scrollx = right - hspace; + } else { // a == Layout.Alignment.ALIGN_LEFT (will also be the default) + scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line)); } if (ht < vspace) { @@ -6618,6 +6618,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public boolean bringPointIntoView(int offset) { boolean changed = false; + if (mLayout == null) return changed; + int line = mLayout.getLineForOffset(offset); // FIXME: Is it okay to truncate this, or should we round? diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index 9e37c7b..f3d891d 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -33,7 +33,7 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.WindowManager.LayoutParams; @@ -501,7 +501,7 @@ public class ZoomButtonsController implements View.OnTouchListener { } else { - ViewAncestor viewRoot = getOwnerViewAncestor(); + ViewRootImpl viewRoot = getOwnerViewRootImpl(); if (viewRoot != null) { viewRoot.dispatchKey(event); } @@ -526,15 +526,15 @@ public class ZoomButtonsController implements View.OnTouchListener { } } - private ViewAncestor getOwnerViewAncestor() { + private ViewRootImpl getOwnerViewRootImpl() { View rootViewOfOwner = mOwnerView.getRootView(); if (rootViewOfOwner == null) { return null; } ViewParent parentOfRootView = rootViewOfOwner.getParent(); - if (parentOfRootView instanceof ViewAncestor) { - return (ViewAncestor) parentOfRootView; + if (parentOfRootView instanceof ViewRootImpl) { + return (ViewRootImpl) parentOfRootView; } else { return null; } diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index cf5666c..f0a9441 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -159,10 +159,8 @@ public class ActionBarImpl extends ActionBar { // Older apps get the home button interaction enabled by default. // Newer apps need to enable it explicitly. - if (mContext.getApplicationInfo().targetSdkVersion < - Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - setHomeButtonEnabled(true); - } + setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion < + Build.VERSION_CODES.ICE_CREAM_SANDWICH); } public void onConfigurationChanged(Configuration newConfig) { diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java index 6039cc2..e1166f1 100755 --- a/core/java/com/android/internal/app/NetInitiatedActivity.java +++ b/core/java/com/android/internal/app/NetInitiatedActivity.java @@ -23,6 +23,8 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; +import android.os.Handler; +import android.os.Message; import android.widget.Toast; import android.util.Log; import android.location.LocationManager; @@ -44,8 +46,12 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE; private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE; + private static final int GPS_NO_RESPONSE_TIME_OUT = 1; // Received ID from intent, -1 when no notification is in progress private int notificationId = -1; + private int timeout = -1; + private int default_response = -1; + private int default_response_timeout = 6; /** Used to detect when NI request is received */ private BroadcastReceiver mNetInitiatedReceiver = new BroadcastReceiver() { @@ -58,6 +64,21 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa } }; + private final Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + switch (msg.what) { + case GPS_NO_RESPONSE_TIME_OUT: { + if (notificationId != -1) { + sendUserResponse(default_response); + } + finish(); + } + break; + default: + } + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -75,8 +96,11 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa p.mNegativeButtonListener = this; notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1); - if (DEBUG) Log.d(TAG, "onCreate, notifId: " + notificationId); + timeout = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TIMEOUT, default_response_timeout); + default_response = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_DEFAULT_RESPONSE, GpsNetInitiatedHandler.GPS_NI_RESPONSE_ACCEPT); + if (DEBUG) Log.d(TAG, "onCreate() : notificationId: " + notificationId + " timeout: " + timeout + " default_response:" + default_response); + mHandler.sendMessageDelayed(mHandler.obtainMessage(GPS_NO_RESPONSE_TIME_OUT), (timeout * 1000)); setupAlert(); } diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index b754d94..69b80d9 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -40,6 +40,7 @@ public class Protocol { /** Non system protocols */ public static final int BASE_WIFI = 0x00020000; + public static final int BASE_WIFI_WATCHDOG = 0x00021000; public static final int BASE_DHCP = 0x00030000; public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION_AC = 0x00041000; diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 812f92b..ce0299c 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -68,5 +68,5 @@ interface IInputMethodManager { boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype); boolean switchToLastInputMethod(in IBinder token); boolean setInputMethodEnabled(String id, boolean enabled); - boolean setAdditionalInputMethodSubtypes(in IBinder token, in InputMethodSubtype[] subtypes); + boolean setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes); } diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 58043c9..678751c 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -370,6 +370,19 @@ public class ActionBarView extends AbsActionBarView { mMenuView = menuView; } + public boolean hasExpandedActionView() { + return mExpandedMenuPresenter != null && + mExpandedMenuPresenter.mCurrentExpandedItem != null; + } + + public void collapseActionView() { + final MenuItemImpl item = mExpandedMenuPresenter == null ? null : + mExpandedMenuPresenter.mCurrentExpandedItem; + if (item != null) { + item.collapseActionView(); + } + } + public void setCustomNavigationView(View view) { final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0; if (mCustomNavView != null && showCustom) { @@ -1272,7 +1285,7 @@ public class ActionBarView extends AbsActionBarView { @Override public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { mExpandedActionView = item.getActionView(); - mExpandedHomeLayout.setIcon(item.getIcon()); + mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources())); mCurrentExpandedItem = item; if (mExpandedActionView.getParent() != ActionBarView.this) { addView(mExpandedActionView); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index d034eab..bbddf29 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -114,6 +114,23 @@ public class LockPatternUtils { private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false); private static FileObserver sPasswordObserver; + private static class PasswordFileObserver extends FileObserver { + public PasswordFileObserver(String path, int mask) { + super(path, mask); + } + + @Override + public void onEvent(int event, String path) { + if (LOCK_PATTERN_FILE.equals(path)) { + Log.d(TAG, "lock pattern file changed"); + sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0); + } else if (LOCK_PASSWORD_FILE.equals(path)) { + Log.d(TAG, "lock password file changed"); + sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0); + } + } + } + public DevicePolicyManager getDevicePolicyManager() { if (mDevicePolicyManager == null) { mDevicePolicyManager = @@ -143,18 +160,7 @@ public class LockPatternUtils { sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0); int fileObserverMask = FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_TO | FileObserver.CREATE; - sPasswordObserver = new FileObserver(dataSystemDirectory, fileObserverMask) { - @Override - public void onEvent(int event, String path) { - if (LOCK_PATTERN_FILE.equals(path)) { - Log.d(TAG, "lock pattern file changed"); - sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0); - } else if (LOCK_PASSWORD_FILE.equals(path)) { - Log.d(TAG, "lock password file changed"); - sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0); - } - } - }; + sPasswordObserver = new PasswordFileObserver(dataSystemDirectory, fileObserverMask); sPasswordObserver.startWatching(); } } diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java index 3070e3e..fb33748 100644 --- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java +++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java @@ -29,7 +29,7 @@ import android.util.Log; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; -import android.view.ViewAncestor; +import android.view.ViewRootImpl; import com.android.internal.R; public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { @@ -150,7 +150,7 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { KeyEvent event = events[i]; event = KeyEvent.changeFlags(event, event.getFlags() | KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE); - handler.sendMessage(handler.obtainMessage(ViewAncestor.DISPATCH_KEY, event)); + handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY, event)); } } } @@ -158,11 +158,11 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { public void sendDownUpKeyEvents(int keyEventCode) { long eventTime = SystemClock.uptimeMillis(); Handler handler = mTargetView.getHandler(); - handler.sendMessage(handler.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME, + handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME, new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE))); - handler.sendMessage(handler.obtainMessage(ViewAncestor.DISPATCH_KEY_FROM_IME, + handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME, new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE))); diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 58e7c8d..514e59d 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -139,13 +139,13 @@ LOCAL_SRC_FILES:= \ android_bluetooth_common.cpp \ android_bluetooth_BluetoothAudioGateway.cpp \ android_bluetooth_BluetoothSocket.cpp \ + android_bluetooth_c.c \ android_server_BluetoothService.cpp \ android_server_BluetoothEventLoop.cpp \ android_server_BluetoothA2dpService.cpp \ android_server_Watchdog.cpp \ android_ddm_DdmHandleNativeHeap.cpp \ com_android_internal_os_ZygoteInit.cpp \ - com_android_internal_graphics_NativeUtils.cpp \ android_backup_BackupDataInput.cpp \ android_backup_BackupDataOutput.cpp \ android_backup_FileBackupHelperBase.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 23c6da7..6ab8fe3 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -115,7 +115,6 @@ extern int register_android_graphics_Region(JNIEnv* env); extern int register_android_graphics_SurfaceTexture(JNIEnv* env); extern int register_android_graphics_Xfermode(JNIEnv* env); extern int register_android_graphics_PixelFormat(JNIEnv* env); -extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env); extern int register_android_view_Display(JNIEnv* env); extern int register_android_view_GLES20Canvas(JNIEnv* env); extern int register_android_view_Surface(JNIEnv* env); @@ -628,15 +627,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y"; mOptions.add(opt); - char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX]; - property_get("dalvik.vm.deadlock-predict", propBuf, ""); - if (strlen(propBuf) > 0) { - strcpy(enableDPBuf, "-Xdeadlockpredict:"); - strcat(enableDPBuf, propBuf); - opt.optionString = enableDPBuf; - mOptions.add(opt); - } - LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF"); if (checkJni) { /* extended JNI checking */ @@ -1147,7 +1137,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_Typeface), REG_JNI(register_android_graphics_Xfermode), REG_JNI(register_android_graphics_YuvImage), - REG_JNI(register_com_android_internal_graphics_NativeUtils), REG_JNI(register_android_database_CursorWindow), REG_JNI(register_android_database_SQLiteCompiledSql), diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index 942aa8a..682c3c4 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -799,24 +799,6 @@ public: x, y, flags, paint); } - static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, - jcharArray text, int index, int count, - jfloat x, jfloat y, int flags, SkPaint* paint) { - jchar* textArray = env->GetCharArrayElements(text, NULL); - drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); - env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); - } - - static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject, - SkCanvas* canvas, jstring text, - int start, int end, - jfloat x, jfloat y, int flags, SkPaint* paint) { - - const jchar* textArray = env->GetStringChars(text, NULL); - drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); - env->ReleaseStringChars(text, textArray); - } - static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { // TODO: need to suppress this code after the GL renderer is modified for not @@ -833,16 +815,6 @@ public: paint->setTextEncoding(oldEncoding); } - static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, - jcharArray glyphs, int index, int count, - jfloat x, jfloat y, int flags, SkPaint* paint) { - jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); - - doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint); - - env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); - } - static void drawTextRun___CIIIIFFIPaint( JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, int contextIndex, int contextCount, @@ -1044,12 +1016,6 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, - {"native_drawTextWithGlyphs","(I[CIIFFII)V", - (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, - {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", - (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, - {"native_drawGlyphs","(I[CIIFFII)V", - (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint}, {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V", diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 6a13876..30fe298 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -323,9 +323,7 @@ size_t TextLayoutCacheValue::getSize() { void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, - size_t contextCount, int dirFlags) { - bool isRTL = dirFlags & 0x1; - + size_t contextCount, bool isRTL) { font->klass = &harfbuzzSkiaClass; font->userData = 0; // The values which harfbuzzSkiaClass returns are already scaled to @@ -374,10 +372,10 @@ void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, - size_t contextCount, int dirFlags) { + size_t contextCount, bool isRTL) { // Setup Harfbuzz Shaper setupShaperItem(shaperItem, font, fontData, paint, chars, start, count, - contextCount, dirFlags); + contextCount, isRTL); // Shape resetGlyphArrays(shaperItem); @@ -430,7 +428,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d", forceLTR, forceRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, + computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); if (forceRTL && *outGlyphsCount > 1) { @@ -451,10 +449,15 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d", dirFlags, rc, paraDir); #endif if (rc == 1 || !U_SUCCESS(status)) { + bool isRTL = (paraDir == 1); +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- processing SINGLE run " + "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); +#endif computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, - dirFlags, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); + isRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); - if (dirFlags == 1 && *outGlyphsCount > 1) { + if (isRTL && *outGlyphsCount > 1) { reverseGlyphArray(*outGlyphs, *outGlyphsCount); } } else { @@ -485,14 +488,14 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar lengthRun = endRun - startRun; - int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR; + bool isRTL = (runDir == UBIDI_RTL); jfloat runTotalAdvance = 0; #if DEBUG_GLYPHS - LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d", - startRun, lengthRun, newFlags); + LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d isRTL=%d", + startRun, lengthRun, isRTL); #endif computeRunValuesWithHarfbuzz(paint, chars, startRun, - lengthRun, contextCount, newFlags, + lengthRun, contextCount, isRTL, outAdvances, &runTotalAdvance, &runGlyphs, &runGlyphsCount); @@ -506,7 +509,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD(" -- glyphs[%d]=%d", j, runGlyphs[j]); } #endif - glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags)); + glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, isRTL)); } *outGlyphs = new jchar[*outGlyphsCount]; @@ -528,13 +531,15 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar ubidi_close(bidi); } else { // Cannot run BiDi, just consider one Run + bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL); #if DEBUG_GLYPHS - LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering only one Run"); + LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run " + "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, + computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); - if (dirFlags == 1 && *outGlyphsCount > 1) { + if (isRTL && *outGlyphsCount > 1) { reverseGlyphArray(*outGlyphs, *outGlyphsCount); } } @@ -545,17 +550,15 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar } void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, - size_t start, size_t count, size_t contextCount, int dirFlags, + size_t start, size_t count, size_t contextCount, bool isRTL, jfloat* outAdvances, jfloat* outTotalAdvance, jchar** outGlyphs, size_t* outGlyphsCount) { - bool isRTL = dirFlags & 0x1; - HB_ShaperItem shaperItem; HB_FontRec font; FontData fontData; shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count, - contextCount, dirFlags); + contextCount, isRTL); #if DEBUG_GLYPHS LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs, diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 690caac..10dee87 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -128,11 +128,11 @@ public: static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, - int dirFlags); + bool isRTL); static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, - int dirFlags); + bool isRTL); static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, @@ -179,7 +179,7 @@ private: static void resetGlyphArrays(HB_ShaperItem* shaperItem); static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags, + size_t count, size_t contextCount, bool isRTL, jfloat* outAdvances, jfloat* outTotalAdvance, jchar** outGlyphs, size_t* outGlyphsCount); }; // TextLayoutCacheValue diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp index cb742a3..29c9c2d 100755 --- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp +++ b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "BluetoothAudioGateway.cpp" #include "android_bluetooth_common.h" +#include "android_bluetooth_c.h" #include "android_runtime/AndroidRuntime.h" #include "JNIHelp.h" #include "jni.h" @@ -491,7 +492,8 @@ static int setup_listening_socket(int dev, int channel) { } laddr.rc_family = AF_BLUETOOTH; - memcpy(&laddr.rc_bdaddr, BDADDR_ANY, sizeof(bdaddr_t)); + bdaddr_t any = android_bluetooth_bdaddr_any(); + memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t)); laddr.rc_channel = channel; if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp index d09c4e9..4c84324 100644 --- a/core/jni/android_bluetooth_BluetoothSocket.cpp +++ b/core/jni/android_bluetooth_BluetoothSocket.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "BluetoothSocket.cpp" #include "android_bluetooth_common.h" +#include "android_bluetooth_c.h" #include "android_runtime/AndroidRuntime.h" #include "JNIHelp.h" #include "utils/Log.h" @@ -245,7 +246,7 @@ static int bindListenNative(JNIEnv *env, jobject obj) { jint type; socklen_t addr_sz; struct sockaddr *addr; - bdaddr_t bdaddr = *BDADDR_ANY; + bdaddr_t bdaddr = android_bluetooth_bdaddr_any(); struct asocket *s = get_socketData(env, obj); if (!s) diff --git a/core/jni/android_bluetooth_c.c b/core/jni/android_bluetooth_c.c new file mode 100755 index 0000000..b4c6727 --- /dev/null +++ b/core/jni/android_bluetooth_c.c @@ -0,0 +1,31 @@ +/* +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifdef HAVE_BLUETOOTH + +#include "android_bluetooth_c.h" + +/* + * A C helper for creating a bdaddr_t object with the value BDADDR_ANY. + * We have to do this in C because the macro BDADDR_ANY in bluetooth.h + * is not valid C++ code. + */ +bdaddr_t android_bluetooth_bdaddr_any(void) +{ + bdaddr_t any = *BDADDR_ANY; + return any; +} +#endif diff --git a/core/jni/android_bluetooth_c.h b/core/jni/android_bluetooth_c.h new file mode 100644 index 0000000..e890244 --- /dev/null +++ b/core/jni/android_bluetooth_c.h @@ -0,0 +1,39 @@ +/* +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_BLUETOOTH_C_H +#define ANDROID_BLUETOOTH_C_H +#ifdef HAVE_BLUETOOTH + +#include <bluetooth/bluetooth.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A C helper for creating a bdaddr_t object with the value BDADDR_ANY. + * We have to do this in C because the macro BDADDR_ANY in bluetooth.h + * is not valid C++ code. + */ +bdaddr_t android_bluetooth_bdaddr_any(void); + +#ifdef __cplusplus +} +#endif + +#endif /*HAVE_BLUETOOTH*/ +#endif /*ANDROID_BLUETOOTH_C_H*/ diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index a4432c3..3a3f07e 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -27,6 +27,7 @@ #include <sys/time.h> #include <errno.h> #include <assert.h> +#include <ctype.h> #ifdef HAVE_MALLOC_H #include <malloc.h> @@ -35,28 +36,50 @@ namespace android { -static jfieldID dalvikPss_field; -static jfieldID dalvikPrivateDirty_field; -static jfieldID dalvikSharedDirty_field; -static jfieldID nativePss_field; -static jfieldID nativePrivateDirty_field; -static jfieldID nativeSharedDirty_field; -static jfieldID otherPss_field; -static jfieldID otherPrivateDirty_field; -static jfieldID otherSharedDirty_field; +enum { + HEAP_UNKNOWN, + HEAP_DALVIK, + HEAP_NATIVE, + HEAP_CURSOR, + HEAP_ASHMEM, + HEAP_UNKNOWN_DEV, + HEAP_SO, + HEAP_JAR, + HEAP_APK, + HEAP_TTF, + HEAP_DEX, + HEAP_UNKNOWN_MAP, + + _NUM_HEAP, + _NUM_CORE_HEAP = HEAP_NATIVE+1 +}; + +struct stat_fields { + jfieldID pss_field; + jfieldID privateDirty_field; + jfieldID sharedDirty_field; +}; + +struct stat_field_names { + const char* pss_name; + const char* privateDirty_name; + const char* sharedDirty_name; +}; + +static stat_fields stat_fields[_NUM_CORE_HEAP]; + +static stat_field_names stat_field_names[_NUM_CORE_HEAP] = { + { "otherPss", "otherPrivateDirty", "otherSharedDirty" }, + { "dalvikPss", "dalvikPrivateDirty", "dalvikSharedDirty" }, + { "nativePss", "nativePrivateDirty", "nativeSharedDirty" } +}; + +jfieldID otherStats_field; struct stats_t { - int dalvikPss; - int dalvikPrivateDirty; - int dalvikSharedDirty; - - int nativePss; - int nativePrivateDirty; - int nativeSharedDirty; - - int otherPss; - int otherPrivateDirty; - int otherSharedDirty; + int pss; + int privateDirty; + int sharedDirty; }; #define BINDER_STATS "/proc/binder/stats" @@ -94,48 +117,71 @@ static jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz) static void read_mapinfo(FILE *fp, stats_t* stats) { char line[1024]; - int len; + int len, nameLen; bool skip, done = false; - unsigned start = 0, size = 0, resident = 0, pss = 0; + unsigned size = 0, resident = 0, pss = 0; unsigned shared_clean = 0, shared_dirty = 0; unsigned private_clean = 0, private_dirty = 0; unsigned referenced = 0; unsigned temp; - int isNativeHeap; - int isDalvikHeap; - int isSqliteHeap; + unsigned long int start; + unsigned long int end = 0; + unsigned long int prevEnd = 0; + char* name; + int name_pos; + + int whichHeap = HEAP_UNKNOWN; + int prevHeap = HEAP_UNKNOWN; - if(fgets(line, 1024, fp) == 0) return; + if(fgets(line, sizeof(line), fp) == 0) return; while (!done) { - isNativeHeap = 0; - isDalvikHeap = 0; - isSqliteHeap = 0; + prevHeap = whichHeap; + prevEnd = end; + whichHeap = HEAP_UNKNOWN; skip = false; len = strlen(line); if (len < 1) return; line[--len] = 0; - /* ignore guard pages */ - if (len > 18 && line[17] == '-') skip = true; - - start = strtoul(line, 0, 16); - - if (strstr(line, "[heap]")) { - isNativeHeap = 1; - } else if (strstr(line, "/dalvik-LinearAlloc")) { - isDalvikHeap = 1; - } else if (strstr(line, "/mspace/dalvik-heap")) { - isDalvikHeap = 1; - } else if (strstr(line, "/dalvik-heap-bitmap/")) { - isDalvikHeap = 1; - } else if (strstr(line, "/data/dalvik-cache/")) { - isDalvikHeap = 1; - } else if (strstr(line, "/tmp/sqlite-heap")) { - isSqliteHeap = 1; + if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) { + skip = true; + } else { + while (isspace(line[name_pos])) { + name_pos += 1; + } + name = line + name_pos; + nameLen = strlen(name); + + if (strstr(name, "[heap]") == name) { + whichHeap = HEAP_NATIVE; + } else if (strstr(name, "/dev/ashmem/dalvik-") == name) { + whichHeap = HEAP_DALVIK; + } else if (strstr(name, "/dev/ashmem/CursorWindow") == name) { + whichHeap = HEAP_CURSOR; + } else if (strstr(name, "/dev/ashmem/") == name) { + whichHeap = HEAP_ASHMEM; + } else if (strstr(name, "/dev/") == name) { + whichHeap = HEAP_UNKNOWN_DEV; + } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) { + whichHeap = HEAP_SO; + } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) { + whichHeap = HEAP_JAR; + } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) { + whichHeap = HEAP_APK; + } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) { + whichHeap = HEAP_TTF; + } else if (nameLen > 4 && strcmp(name+nameLen-4, ".dex") == 0) { + whichHeap = HEAP_DEX; + } else if (nameLen > 0) { + whichHeap = HEAP_UNKNOWN_MAP; + } else if (start == prevEnd && prevHeap == HEAP_SO) { + // bss section of a shared library. + whichHeap = HEAP_SO; + } } //LOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap, @@ -171,21 +217,9 @@ static void read_mapinfo(FILE *fp, stats_t* stats) } if (!skip) { - if (isNativeHeap) { - stats->nativePss += pss; - stats->nativePrivateDirty += private_dirty; - stats->nativeSharedDirty += shared_dirty; - } else if (isDalvikHeap) { - stats->dalvikPss += pss; - stats->dalvikPrivateDirty += private_dirty; - stats->dalvikSharedDirty += shared_dirty; - } else if ( isSqliteHeap) { - // ignore - } else { - stats->otherPss += pss; - stats->otherPrivateDirty += private_dirty; - stats->otherSharedDirty += shared_dirty; - } + stats[whichHeap].pss += pss; + stats[whichHeap].privateDirty += private_dirty; + stats[whichHeap].sharedDirty += shared_dirty; } } } @@ -206,22 +240,38 @@ static void load_maps(int pid, stats_t* stats) static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, jint pid, jobject object) { - stats_t stats; - memset(&stats, 0, sizeof(stats_t)); + stats_t stats[_NUM_HEAP]; + memset(&stats, 0, sizeof(stats)); - load_maps(pid, &stats); + load_maps(pid, stats); + + for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) { + stats[HEAP_UNKNOWN].pss += stats[i].pss; + stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty; + stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty; + } - env->SetIntField(object, dalvikPss_field, stats.dalvikPss); - env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty); - env->SetIntField(object, dalvikSharedDirty_field, stats.dalvikSharedDirty); + for (int i=0; i<_NUM_CORE_HEAP; i++) { + env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss); + env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty); + env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty); + } - env->SetIntField(object, nativePss_field, stats.nativePss); - env->SetIntField(object, nativePrivateDirty_field, stats.nativePrivateDirty); - env->SetIntField(object, nativeSharedDirty_field, stats.nativeSharedDirty); + jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field); - env->SetIntField(object, otherPss_field, stats.otherPss); - env->SetIntField(object, otherPrivateDirty_field, stats.otherPrivateDirty); - env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty); + jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0); + if (otherArray == NULL) { + return; + } + + int j=0; + for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) { + otherArray[j++] = stats[i].pss; + otherArray[j++] = stats[i].privateDirty; + otherArray[j++] = stats[i].sharedDirty; + } + + env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0); } static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object) @@ -487,19 +537,18 @@ static JNINativeMethod gMethods[] = { int register_android_os_Debug(JNIEnv *env) { jclass clazz = env->FindClass("android/os/Debug$MemoryInfo"); - - dalvikPss_field = env->GetFieldID(clazz, "dalvikPss", "I"); - dalvikPrivateDirty_field = env->GetFieldID(clazz, "dalvikPrivateDirty", "I"); - dalvikSharedDirty_field = env->GetFieldID(clazz, "dalvikSharedDirty", "I"); - nativePss_field = env->GetFieldID(clazz, "nativePss", "I"); - nativePrivateDirty_field = env->GetFieldID(clazz, "nativePrivateDirty", "I"); - nativeSharedDirty_field = env->GetFieldID(clazz, "nativeSharedDirty", "I"); - - otherPss_field = env->GetFieldID(clazz, "otherPss", "I"); - otherPrivateDirty_field = env->GetFieldID(clazz, "otherPrivateDirty", "I"); - otherSharedDirty_field = env->GetFieldID(clazz, "otherSharedDirty", "I"); - + for (int i=0; i<_NUM_CORE_HEAP; i++) { + stat_fields[i].pss_field = + env->GetFieldID(clazz, stat_field_names[i].pss_name, "I"); + stat_fields[i].privateDirty_field = + env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I"); + stat_fields[i].sharedDirty_field = + env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I"); + } + + otherStats_field = env->GetFieldID(clazz, "otherStats", "[I"); + return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 681f43f..b0c2f2c 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -127,6 +127,13 @@ static void android_view_GLES20Canvas_disableVsync(JNIEnv* env, jobject clazz) { } } +static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz, + Caches::FlushMode mode) { + if (Caches::hasInstance()) { + Caches::getInstance().flush(mode); + } +} + // ---------------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------------- @@ -735,6 +742,7 @@ static JNINativeMethod gMethods[] = { { "nIsBackBufferPreserved", "()Z", (void*) android_view_GLES20Canvas_isBackBufferPreserved }, { "nPreserveBackBuffer", "()Z", (void*) android_view_GLES20Canvas_preserveBackBuffer }, { "nDisableVsync", "()V", (void*) android_view_GLES20Canvas_disableVsync }, + { "nFlushCaches", "(I)V", (void*) android_view_GLES20Canvas_flushCaches }, { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer }, { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer }, @@ -859,10 +867,8 @@ int register_android_view_GLES20Canvas(JNIEnv* env) { const char* const kActivityThreadPathName = "android/app/ActivityThread"; -int register_android_app_ActivityThread(JNIEnv* env) -{ - return AndroidRuntime::registerNativeMethods( - env, kActivityThreadPathName, +int register_android_app_ActivityThread(JNIEnv* env) { + return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName, gActivityThreadMethods, NELEM(gActivityThreadMethods)); } diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp index b046b23..9484c6b 100644 --- a/core/jni/android_view_TextureView.cpp +++ b/core/jni/android_view_TextureView.cpp @@ -19,11 +19,48 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_graphics_SurfaceTexture.h> +#include <ui/Region.h> +#include <ui/Rect.h> + #include <gui/SurfaceTexture.h> +#include <gui/SurfaceTextureClient.h> + +#include <SkBitmap.h> +#include <SkCanvas.h> namespace android { // ---------------------------------------------------------------------------- +// JNI Glue +// ---------------------------------------------------------------------------- + +static struct { + jmethodID set; + jfieldID left; + jfieldID top; + jfieldID right; + jfieldID bottom; +} gRectClassInfo; + +static struct { + jfieldID nativeCanvas; + jfieldID surfaceFormat; +} gCanvasClassInfo; + +static struct { + jfieldID nativeWindow; +} gTextureViewClassInfo; + +#define GET_INT(object, field) \ + env->GetIntField(object, field) + +#define SET_INT(object, field, value) \ + env->SetIntField(object, field, value) + +#define INVOKEV(object, method, ...) \ + env->CallVoidMethod(object, method, __VA_ARGS__) + +// ---------------------------------------------------------------------------- // Native layer // ---------------------------------------------------------------------------- @@ -34,6 +71,118 @@ static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject, surfaceTexture->setDefaultBufferSize(width, height); } +static inline SkBitmap::Config convertPixelFormat(int32_t format) { + switch (format) { + case WINDOW_FORMAT_RGBA_8888: + return SkBitmap::kARGB_8888_Config; + case WINDOW_FORMAT_RGBX_8888: + return SkBitmap::kARGB_8888_Config; + case WINDOW_FORMAT_RGB_565: + return SkBitmap::kRGB_565_Config; + default: + return SkBitmap::kNo_Config; + } +} + +/** + * This is a private API, and this implementation is also provided in the NDK. + * However, the NDK links against android_runtime, which means that using the + * NDK implementation would create a circular dependency between the libraries. + */ +static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, + Rect* inOutDirtyBounds) { + return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); +} + +static int32_t native_window_unlockAndPost(ANativeWindow* window) { + return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); +} + +static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView, + jobject surface) { + + sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); + sp<ANativeWindow> window = new SurfaceTextureClient(surfaceTexture); + + window->incStrong(0); + SET_INT(textureView, gTextureViewClassInfo.nativeWindow, jint(window.get())); +} + +static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) { + + ANativeWindow* nativeWindow = (ANativeWindow*) + GET_INT(textureView, gTextureViewClassInfo.nativeWindow); + + if (nativeWindow) { + sp<ANativeWindow> window(nativeWindow); + window->decStrong(0); + SET_INT(textureView, gTextureViewClassInfo.nativeWindow, 0); + } +} + +static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject, + jint nativeWindow, jobject canvas, jobject dirtyRect) { + + if (!nativeWindow) { + return; + } + + ANativeWindow_Buffer buffer; + + Rect rect; + if (dirtyRect) { + rect.left = GET_INT(dirtyRect, gRectClassInfo.left); + rect.top = GET_INT(dirtyRect, gRectClassInfo.top); + rect.right = GET_INT(dirtyRect, gRectClassInfo.right); + rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom); + } else { + rect.set(Rect(0x3FFF, 0x3FFF)); + } + + sp<ANativeWindow> window((ANativeWindow*) nativeWindow); + native_window_lock(window.get(), &buffer, &rect); + + ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format); + + SkBitmap bitmap; + bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount); + + if (buffer.format == WINDOW_FORMAT_RGBX_8888) { + bitmap.setIsOpaque(true); + } + + if (buffer.width > 0 && buffer.height > 0) { + bitmap.setPixels(buffer.bits); + } else { + bitmap.setPixels(NULL); + } + + SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format); + SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); + nativeCanvas->setBitmapDevice(bitmap); + + SkRect clipRect; + clipRect.set(rect.left, rect.top, rect.right, rect.bottom); + nativeCanvas->clipRect(clipRect); + + if (dirtyRect) { + INVOKEV(dirtyRect, gRectClassInfo.set, + int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); + } +} + +static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, + jint nativeWindow, jobject canvas) { + + SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); + nativeCanvas->setBitmapDevice(SkBitmap()); + + if (nativeWindow) { + sp<ANativeWindow> window((ANativeWindow*) nativeWindow); + native_window_unlockAndPost(window.get()); + } +} + // ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- @@ -42,10 +191,47 @@ const char* const kClassPathName = "android/view/TextureView"; static JNINativeMethod gMethods[] = { { "nSetDefaultBufferSize", "(Landroid/graphics/SurfaceTexture;II)V", - (void*) android_view_TextureView_setDefaultBufferSize } + (void*) android_view_TextureView_setDefaultBufferSize }, + + { "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V", + (void*) android_view_TextureView_createNativeWindow }, + { "nDestroyNativeWindow", "()V", + (void*) android_view_TextureView_destroyNativeWindow }, + + { "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V", + (void*) android_view_TextureView_lockCanvas }, + { "nUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V", + (void*) android_view_TextureView_unlockCanvasAndPost }, }; +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(!var, "Unable to find class " className); + +#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ + var = env->GetMethodID(clazz, methodName, methodDescriptor); \ + LOG_FATAL_IF(!var, "Unable to find method " methodName); + +#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ + var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ + LOG_FATAL_IF(!var, "Unable to find field" fieldName); + int register_android_view_TextureView(JNIEnv* env) { + jclass clazz; + FIND_CLASS(clazz, "android/graphics/Rect"); + GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V"); + GET_FIELD_ID(gRectClassInfo.left, clazz, "left", "I"); + GET_FIELD_ID(gRectClassInfo.top, clazz, "top", "I"); + GET_FIELD_ID(gRectClassInfo.right, clazz, "right", "I"); + GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I"); + + FIND_CLASS(clazz, "android/graphics/Canvas"); + GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I"); + GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I"); + + FIND_CLASS(clazz, "android/view/TextureView"); + GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I"); + return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/jni/com_android_internal_graphics_NativeUtils.cpp b/core/jni/com_android_internal_graphics_NativeUtils.cpp deleted file mode 100644 index 9cc43606..0000000 --- a/core/jni/com_android_internal_graphics_NativeUtils.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "AWT" - -#include "jni.h" -#include "JNIHelp.h" -#include "GraphicsJNI.h" -#include <android_runtime/AndroidRuntime.h> - -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkPicture.h" -#include "SkTemplates.h" - -namespace android -{ - -static jboolean scrollRect(JNIEnv* env, jobject graphics2D, jobject canvas, jobject rect, int dx, int dy) { - if (canvas == NULL) { - jniThrowNullPointerException(env, NULL); - return false; - } - - SkIRect src, *srcPtr = NULL; - if (NULL != rect) { - GraphicsJNI::jrect_to_irect(env, rect, &src); - srcPtr = &src; - } - SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas); - const SkBitmap& bitmap = c->getDevice()->accessBitmap(true); - return bitmap.scrollRect(srcPtr, dx, dy, NULL); -} - -static JNINativeMethod method_table[] = { - { "nativeScrollRect", - "(Landroid/graphics/Canvas;Landroid/graphics/Rect;II)Z", - (void*)scrollRect} -}; - -int register_com_android_internal_graphics_NativeUtils(JNIEnv *env) { - return AndroidRuntime::registerNativeMethods( - env, "com/android/internal/graphics/NativeUtils", - method_table, NELEM(method_table)); -} - -} diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml index 902b3c0..50b1878 100644 --- a/core/res/res/layout/activity_chooser_view.xml +++ b/core/res/res/layout/activity_chooser_view.xml @@ -23,13 +23,9 @@ style="?android:attr/actionButtonStyle"> <ImageButton android:id="@+id/default_activity_button" - android:layout_width="32dip" - android:layout_height="32dip" - android:layout_marginRight="8dip" /> + style="@style/Widget.ActivityChooserViewButton" /> <ImageButton android:id="@+id/expand_activities_button" - android:layout_width="32dip" - android:layout_height="32dip" - android:layout_marginLeft="8dip" /> + style="@style/Widget.ActivityChooserViewButton" /> </LinearLayout> diff --git a/core/res/res/layout/activity_chooser_view_list_item.xml b/core/res/res/layout/activity_chooser_view_list_item.xml index f90044e..88498d9 100644 --- a/core/res/res/layout/activity_chooser_view_list_item.xml +++ b/core/res/res/layout/activity_chooser_view_list_item.xml @@ -20,6 +20,7 @@ android:layout_height="?android:attr/dropdownListPreferredItemHeight" android:paddingLeft="16dip" android:paddingRight="16dip" + android:minWidth="196dip" android:background="?android:attr/activatedBackgroundIndicator" android:orientation="vertical" > diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml index 790ac6b..f6b5b53 100644 --- a/core/res/res/layout/search_bar.xml +++ b/core/res/res/layout/search_bar.xml @@ -66,7 +66,6 @@ android:layout_height="wrap_content" android:layout_weight="1" android:maxWidth="600dip" - android:iconifiedByDefault="false" android:layout_gravity="center_vertical" /> diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml index 53906f9..acef2cc 100644 --- a/core/res/res/layout/search_dropdown_item_icons_2line.xml +++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml @@ -19,21 +19,21 @@ --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:paddingLeft="4dip" - android:paddingRight="2dip" + android:paddingLeft="@dimen/dropdownitem_text_padding_left" + android:paddingRight="4dip" android:layout_width="match_parent" android:layout_height="?android:attr/searchResultListItemHeight" > <!-- Icons come first in the layout, since their placement doesn't depend on the placement of the text views. --> <ImageView android:id="@android:id/icon1" - android:layout_width="48dip" + android:layout_width="@dimen/dropdownitem_icon_width" android:layout_height="48dip" android:scaleType="centerInside" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" - android:visibility="gone" /> + android:visibility="invisible" /> <ImageView android:id="@+id/edit_query" android:layout_width="48dip" diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml index fee27eb..6b70d8d 100644 --- a/core/res/res/layout/search_view.xml +++ b/core/res/res/layout/search_view.xml @@ -22,6 +22,8 @@ android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingLeft="8dip" + android:paddingRight="8dip" android:orientation="horizontal" > @@ -30,7 +32,7 @@ android:id="@+id/search_badge" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_gravity="center_vertical" + android:gravity="center_vertical" android:layout_marginBottom="2dip" android:drawablePadding="0dip" android:textAppearance="?android:attr/textAppearanceMedium" @@ -54,12 +56,21 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" - android:layout_marginLeft="8dip" - android:layout_marginRight="8dip" android:layout_marginTop="4dip" android:layout_marginBottom="4dip" android:orientation="horizontal"> + <ImageView + android:id="@+id/search_mag_icon" + android:layout_width="@dimen/dropdownitem_icon_width" + android:layout_height="wrap_content" + android:scaleType="centerInside" + android:layout_marginLeft="@dimen/dropdownitem_text_padding_left" + android:layout_gravity="center_vertical" + android:src="?android:attr/searchViewSearchIcon" + android:visibility="gone" + /> + <!-- Inner layout contains the app icon, button(s) and EditText --> <LinearLayout android:id="@+id/search_plate" @@ -70,14 +81,6 @@ android:orientation="horizontal" android:background="?android:attr/searchViewTextField"> - <ImageView - android:id="@+id/search_app_icon" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:src="?android:attr/searchViewSearchIcon" - /> - <view class="android.widget.SearchView$SearchAutoComplete" android:id="@+id/search_src_text" android:layout_height="36dip" @@ -85,8 +88,8 @@ android:layout_weight="1" android:minWidth="@dimen/search_view_text_min_width" android:layout_gravity="bottom" - android:paddingLeft="8dip" - android:paddingRight="6dip" + android:paddingLeft="@dimen/dropdownitem_text_padding_left" + android:paddingRight="@dimen/dropdownitem_text_padding_right" android:singleLine="true" android:ellipsize="end" android:background="@null" @@ -100,7 +103,7 @@ <ImageView android:id="@+id/search_close_btn" - android:layout_width="wrap_content" + android:layout_width="@dimen/dropdownitem_icon_width" android:layout_height="match_parent" android:paddingLeft="8dip" android:paddingRight="8dip" @@ -131,7 +134,7 @@ android:visibility="gone" android:focusable="true" /> - + <ImageView android:id="@+id/search_voice_btn" android:layout_width="wrap_content" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 8a75bd0..6d9f2fe 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -931,6 +931,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lees blaaier se geskiedenis en boekmerke"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Laat die program toe om al die URL\'e te lees wat die blaaier besoek het, asook al die blaaier se boekmerke."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skryf blaaier se geskiedenis en boekmerke"</string> @@ -1437,8 +1461,8 @@ <skip /> <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 52745b9..9fff387 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -931,6 +931,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">"፣ "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"የአሳሽ ታሪኮች እና ዕልባቶች አንብብ።"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ትግበራው ማሰሻው የጎበኛቸውን ሁሉ URL ኦች፣ እና የማሰሻውን ዕልባቶች ሁሉ ለማንበብ ይፈቅዳል።"</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"የአሳሾች ታሪክ እና ዕልባቶች ፃፍ"</string> @@ -1437,8 +1461,8 @@ <skip /> <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index f37410b..70fc500 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"قراءة سجل المتصفح والإشارات"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"للسماح للتطبيق بقراءة جميع عناوين URL التي انتقل إليها المتصفح. وجميع إشارات المتصفح."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"كتابة سجل المتصفح والإشارات"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"إذا شغّلت سعة تخزين USB، فستتوقف بعض التطبيقات التي تستخدمها وربما تصبح غير متاحة لحين إيقاف تشغيل سعة تخزين USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"أخفقت عملية USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"موافق"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"التوصيل كجهاز وسائط"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"التوصيل ككاميرا"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"التوصيل كأداة تثبيت"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"المس للاطلاع على خيارات USB الأخرى"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تهيئة وحدة تخزين USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"تنسيق بطاقة SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"هل تريد تهيئة وحدة تخزين USB، ومحو كل الملفات المخزنة بها؟ لا يمكن عكس هذا الإجراء!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"إمكانية الدخول"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"تم تنشيط الشبكة الظاهرية الخاصة (VPN)."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"تم تنشيط الشبكة الظاهرية الخاصة (VPN) بواسطة <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"انقر لإدارة الشبكة."</string> <string name="vpn_text_long" msgid="4907843483284977618">"تم الاتصال بـ <xliff:g id="SESSION">%s</xliff:g>. انقر لإدارة الشبكة."</string> <string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"الصلاحية:"</string> <string name="issued_on" msgid="5895017404361397232">"تاريخ الإصدار:"</string> <string name="expires_on" msgid="3676242949915959821">"تنتهي الصلاحية في:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"الرقم المسلسل:"</string> + <string name="fingerprints" msgid="4516019619850763049">"بصمات الأصابع:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"بصمة أصبع SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"بصمة أصبع SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"عرض الكل..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 9147fb5..b67812a 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"четене на историята и отметките на браузъра"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешава на приложението да чете всички URL адреси, посетени от браузъра, и всички негови отметки."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис в историята и отметките на браузъра"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако включите работата като USB устройство за съхранение, някои използвани от вас приложения ще спрат и може да бъдат недостъпни, докато не я изключите."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Операцията през USB не бе успешна"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Свързан като медийно устройство"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Свързан като камера"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Свързан като инсталационна програма"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Докоснете за други опции за USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматиране на SD картата"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Да се форматира ли USB хранилището, изтривайки всички файлове в него? Действието не може да бъде отменено!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Достъпност"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN е активирана."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Докоснете за управление на мрежата."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Свързана с/ъс <xliff:g id="SESSION">%s</xliff:g>. Докоснете, за да управлявате мрежата."</string> <string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Валидност:"</string> <string name="issued_on" msgid="5895017404361397232">"Издаден на:"</string> <string name="expires_on" msgid="3676242949915959821">"Изтича на:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Сериен номер:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Пръстови отпечатъци:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Пръстов отпечатък SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Пръстов отпечатък SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Вижте всички..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index b7117b9..c7b1735 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"llegir l\'historial i les adreces d\'interès del navegador"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permet a l\'aplicació llegir tots els URL que ha visitat el navegador i totes les adreces d\'interès del navegador."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escriure l\'historial i les adreces d\'interès del navegador"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activeu l\'emmagatzematge USB, algunes de les aplicacions que utilitzeu s\'aturaran i pot ser que no estiguin disponibles fins que desactiveu l\'emmagatzematge USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Error de l\'operació d\'USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connectat com a dispositiu multimèdia"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connectat com a càmera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connectat com a instal·lador"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Toca per obtenir altres opcions d\'USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formata l\'emmag. USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formata la targeta SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vols formatar l\'emmagatzematge USB i esborrar tots els fitxers que hi ha emmagatzemats? L\'acció no es podrà desfer."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilitat"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Empaperat"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvi de l\'empaperat"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN activada."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"Pica per gestionar la xarxa."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Connectat a <xliff:g id="SESSION">%s</xliff:g>. Pica per gestionar la xarxa."</string> <string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validesa:"</string> <string name="issued_on" msgid="5895017404361397232">"Emès el:"</string> <string name="expires_on" msgid="3676242949915959821">"Caduca el:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Número de sèrie:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Empremtes"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Empremta SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Empremta SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Mostra-ho tot"</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index ecd83dd..944eb2f 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čtení historie a záložek Prohlížeče"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikaci číst všechny navštívené adresy URL a záložky Prohlížeče."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zápis do historie a záložek Prohlížeče"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Pokud zapnete úložiště USB, dojde k zastavení některých používaných aplikací. Tyto aplikace pravděpodobně nebudou k dispozici až do vypnutí úložiště USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operace na rozhraní USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Připojeno jako mediální zařízení"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Připojeno jako fotoaparát"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Připojeno jako instalátor"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Dotykem zobrazíte další možnosti USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formátovat úložiště USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovat kartu SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete úložiště USB zformátovat a tím smazat všechny soubory, které v něm jsou uloženy? Tuto akci nelze vrátit zpět."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Usnadnění"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Síť VPN je aktivována."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"Klepnutím zobrazíte správu sítě."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Připojeno k relaci <xliff:g id="SESSION">%s</xliff:g>. Klepnutím můžete síť spravovat."</string> <string name="upload_file" msgid="2897957172366730416">"Zvolit soubor"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Platnost:"</string> <string name="issued_on" msgid="5895017404361397232">"Datum vydání:"</string> <string name="expires_on" msgid="3676242949915959821">"Platnost vyprší:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Sériové číslo:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Digitální otisky:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Digitální otisk SHA-256"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Digitální otisk SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Zobrazit vše..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 67de2aa..c573322 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"læs browserens oversigt og bogmærker"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader, at applikationen læser alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriv browserens oversigt og bogmærker"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du slår USB-lagring til, vil nogle af de applikationer, som du bruger, stoppe, og de kan være utilgængelige, indtil du slår USB-lagring til igen."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB-handlingen mislykkedes"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilsluttet som en medieenhed"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilsluttet som et kamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilsluttet som et installationsprogram"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Tryk for at se andre valgmuligheder for USB-tilslutning"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater USB-lager"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater SD-kort"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lager og slette alle filer, som er gemt der? Handlingen kan ikke fortrydes!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgængelighed"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapet"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift tapet"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN er aktiveret."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Tryk for at administrere netværket."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string> <string name="upload_file" msgid="2897957172366730416">"Vælg fil"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Gyldighed:"</string> <string name="issued_on" msgid="5895017404361397232">"Udstedt den:"</string> <string name="expires_on" msgid="3676242949915959821">"Udløber den:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Fingeraftryk:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeraftryk:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeraftryk:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Se alle..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index b4203b6..723d0a9 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Browserverlauf und Lesezeichen lesen"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ermöglicht der App, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen"</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Browserverlauf und Lesezeichen schreiben"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendete Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB-Vorgang fehlgeschlagen"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Als Mediengerät angeschlossen"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Als Kamera angeschlossen"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Als Installationsprogramm angeschlossen"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Zum Anzeigen weiterer USB-Optionen tippen"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-Sp. formatieren"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-Karte formatieren"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-Speicher formatieren und alle darin befindlichen Dateien löschen? Diese Aktion kann nicht rückgängig gemacht werden!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Eingabehilfen"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN ist aktiviert."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string> <string name="vpn_text" msgid="1610714069627824309">"Zum Verwalten des Netzwerks tippen"</string> <string name="vpn_text_long" msgid="4907843483284977618">"Verbunden mit <xliff:g id="SESSION">%s</xliff:g>. Zum Verwalten des Netzwerks tippen"</string> <string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Gültigkeit:"</string> <string name="issued_on" msgid="5895017404361397232">"Ausgegeben am:"</string> <string name="expires_on" msgid="3676242949915959821">"Läuft ab am:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Seriennummer:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Fingerabdrücke:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-Fingerabdruck:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-Fingerabdruck:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Alle anzeigen..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index ae72132..22a74b9 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ανάγνωση ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των διευθύνσεων URL που το πρόγραμμα περιήγησης έχει επισκεφθεί και όλων των σελιδοδεικτών του προγράμματος περιήγησης."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"εγγραφή ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Εάν ενεργοποιήσετε τον αποθηκευτικό χώρο USB, ορισμένες από τις εφαρμογές που χρησιμοποιείτε θα σταματήσουν και ενδέχεται να μην είναι διαθέσιμες μέχρι να απενεργοποιήσετε τον αποθηκευτικό χώρο USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Απέτυχε η λειτουργία USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"ΟΚ"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Συνδεδεμένο ως συσκευή πολυμέσων"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Συνδεδεμένο ως φωτογραφική μηχανή"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Συνδεδεμένο ως πρόγραμμα εγκατάστασης"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Αγγίξτε για άλλες επιλογές USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Διαγρ. απ. χώρου USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Να γίνει διαγραφή του αποθηκευτικού χώρου USB, η οποία θα διαγράψει όλα τα αρχεία που έχετε αποθηκεύσει εκεί; Η ενέργεια είναι μη αναστρέψιμη!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Προσβασιμότητα"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Το VPN είναι ενεργοποιημένο."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Πατήστε για να διαχειριστείτε το δίκτυο."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Συνδέθηκε με <xliff:g id="SESSION">%s</xliff:g>. Πατήστε για να διαχειριστείτε το δίκτυο."</string> <string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Ισχύς:"</string> <string name="issued_on" msgid="5895017404361397232">"Εκδόθηκε στις:"</string> <string name="expires_on" msgid="3676242949915959821">"Λήγει στις:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Σειριακός αριθμός:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Αποτυπώματα"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Αποτύπωμα SHA-256"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Αποτύπωμα SHA-1"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Εμφάνιση όλων..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index d26628c..2bf09f6 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -701,6 +701,18 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <string name="autofill_province" msgid="2231806553863422300">"Province"</string> + <string name="autofill_postal_code" msgid="4696430407689377108">"Postcode"</string> + <string name="autofill_state" msgid="6988894195520044613">"State"</string> + <string name="autofill_zip_code" msgid="8697544592627322946">"Zip code"</string> + <string name="autofill_county" msgid="237073771020362891">"County"</string> + <string name="autofill_island" msgid="4020100875984667025">"Island"</string> + <string name="autofill_district" msgid="8400735073392267672">"District"</string> + <string name="autofill_department" msgid="5343279462564453309">"Department"</string> + <string name="autofill_prefecture" msgid="2028499485065800419">"Prefecture"</string> + <string name="autofill_parish" msgid="8202206105468820057">"Parish"</string> + <string name="autofill_area" msgid="3547409050889952423">"Area"</string> + <string name="autofill_emirate" msgid="2893880978835698818">"Emirate"</string> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"read Browser\'s history and bookmarks"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"write Browser\'s history and bookmarks"</string> @@ -944,14 +956,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"If you turn on USB storage, some applications that you are using will stop and may be unavailable until you turn off USB storage."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB operation failed"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connected as a media device"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connected as a camera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connected as an installer"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Touch for other USB options"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format USB storage"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format SD card"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format USB storage, erasing all files stored there? Action cannot be reversed!"</string> @@ -1015,10 +1023,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibility"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN is activated."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Tap to manage the network."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string> <string name="upload_file" msgid="2897957172366730416">"Choose file"</string> @@ -1095,18 +1101,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validity:"</string> <string name="issued_on" msgid="5895017404361397232">"Issued on:"</string> <string name="expires_on" msgid="3676242949915959821">"Expires on:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serial number:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Fingerprints:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 fingerprint"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 fingerprint"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"See all..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 305b131..ea642c9 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer historial y marcadores del navegador"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite a la aplicación leer todas las URL que ha visitado el navegador y todos los marcadores del navegador."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir historial y marcadores del navegador"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, algunas aplicaciones que estás usando se detendrán y es posible que no estén disponibles hasta que desactives el almacenamiento USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Error en el funcionamiento del USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como un instalador"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Toca para otras opciones de USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear almacenamiento USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Deseas formatear el almacenamiento USB y borrar todos los archivos almacenados aquí? ¡Esta acción no se puede cambiar!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN está activado."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Pulsa para gestionar la red."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Pulsa para gestionar la red."</string> <string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validez:"</string> <string name="issued_on" msgid="5895017404361397232">"Emitido:"</string> <string name="expires_on" msgid="3676242949915959821">"Expira el:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Número de serie:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Huellas digitales:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Huella digital SHA-256"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Huella digital SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todas..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index f3d1d66..44e1c94 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -701,6 +701,18 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string> + <string name="autofill_postal_code" msgid="4696430407689377108">"Código postal"</string> + <string name="autofill_state" msgid="6988894195520044613">"Estado"</string> + <string name="autofill_zip_code" msgid="8697544592627322946">"Código postal"</string> + <string name="autofill_county" msgid="237073771020362891">"Condado"</string> + <string name="autofill_island" msgid="4020100875984667025">"Isla"</string> + <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string> + <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string> + <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectura"</string> + <string name="autofill_parish" msgid="8202206105468820057">"Distrito"</string> + <string name="autofill_area" msgid="3547409050889952423">"Área"</string> + <string name="autofill_emirate" msgid="2893880978835698818">"Emirato"</string> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer información de marcadores y del historial del navegador"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que la aplicación lea todas las URL que ha visitado el navegador y todos sus marcadores."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir en marcadores y en el historial del navegador"</string> @@ -944,14 +956,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, se detendrán algunas aplicaciones que estás utilizando y estas no estarán disponibles hasta que lo desactives."</string> <string name="dlg_error_title" msgid="8048999973837339174">"No se ha podido realizar la operación USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como instalador"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Tocar para acceder a otras opciones de USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Quieres formatear el USB y borrar todos los archivos? Esta acción no se puede deshacer."</string> @@ -1015,10 +1023,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN activada"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Toca para administrar la red."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca para administrar la red."</string> <string name="upload_file" msgid="2897957172366730416">"Seleccionar archivo"</string> @@ -1095,18 +1101,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validez:"</string> <string name="issued_on" msgid="5895017404361397232">"Fecha de emisión:"</string> <string name="expires_on" msgid="3676242949915959821">"Fecha de caducidad:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Número de serie:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Huellas digitales:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Huella digital SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Huella digital SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todas..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index aae9760..14943a1 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"خواندن سابقه و نشانک های مرورگر"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"به برنامه کاربردی اجازه می دهد تا تمام URL های بازدید شده توسط مرورگر و تمام نشانک های آن را بخواند."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"نوشتن سابقه مرورگر و نشانک ها"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"در صورت روشن کردن دستگاه ذخیره سازی USB، برخی از برنامه هایی که از آنها استفاده می کنید متوقف می شوند و تا زمانی که دستگاه ذخیره سازی USB را خاموش نکنید امکان استفاده از آنها وجود نخواهد داشت."</string> <string name="dlg_error_title" msgid="8048999973837339174">"عملکرد USB انجام نشد"</string> <string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به عنوان دستگاه رسانه ای"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده به عنوان دوربین"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده به عنوان نصب کننده"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"برای سایر گزینه های USB لمس کنید"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن حافظه USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"فرمت کردن کارت SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"فرمت کردن حافظه USB، همه فایل های ذخیره شده در آنجا پاک شود؟ عملکرد قابل بازگشت نیست!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"قابلیت دسترسی"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN فعال است."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string> <string name="vpn_text" msgid="1610714069627824309">"برای مدیریت شبکه ضربه بزنید."</string> <string name="vpn_text_long" msgid="4907843483284977618">"به <xliff:g id="SESSION">%s</xliff:g> متصل شد. برای مدیریت شبکه ضربه بزنید."</string> <string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string> @@ -1093,20 +1111,15 @@ <string name="org_unit" msgid="7265981890422070383">"واحد سازمانی:"</string> <string name="issued_by" msgid="2647584988057481566">"صادر شده توسط:"</string> <string name="validity_period" msgid="8818886137545983110">"اعتبار:"</string> - <string name="issued_on" msgid="5895017404361397232">"تاریخ صدور:"</string> + <string name="issued_on" msgid="5895017404361397232">"صادر شده در:"</string> <string name="expires_on" msgid="3676242949915959821">"تاریخ انقضا:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"شماره سریال:"</string> + <string name="fingerprints" msgid="4516019619850763049">"اثر انگشت:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"اثر انگشت SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"اثر انگشت SHA-1"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"مشاهده همه..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 962383a..fcae45c 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lue selaimen historiaa ja kirjanmerkkejä"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Antaa sovelluksen lukea kaikki selaimen käyttämät URL-osoitteet ja selaimen kirjanmerkit."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"kirjoita selaimen historiaa ja kirjanmerkkejä"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jos otat USB-tallennustilan käyttöön, osa käyttämistäsi sovelluksista pysähtyy eivätkä ne välttämättä ole käytössä kunnes poistat USB-tallennustilan käytöstä."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB-toiminto epäonnistui"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Kytketty medialaitteena"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kytketty kamerana"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Kytketty asennusohjelmana"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Käytä muita USB-vaihtoehtoja koskettamalla"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Alusta USB-tila"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Alusta SD-kortti"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Haluatko alustaa USB-tilan ja poistaa kaikki siellä olevat tiedostot? Toimintoa ei voi peruuttaa!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Esteettömyys"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN on aktivoitu."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string> <string name="vpn_text" msgid="1610714069627824309">"Napauta, niin voit hallinnoida verkkoa."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Yhdistetty: <xliff:g id="SESSION">%s</xliff:g>. Hallinnoi verkkoa napauttamalla."</string> <string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Voimassa:"</string> <string name="issued_on" msgid="5895017404361397232">"Myönnetty:"</string> <string name="expires_on" msgid="3676242949915959821">"Vanhenee:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Sarjanumero"</string> + <string name="fingerprints" msgid="4516019619850763049">"Tunnistetiedostot:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-tunnistetiedosto"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-tunnistetiedosto"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Näytä kaikki..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index f9aa46e..be75a7e 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lire l\'historique et les favoris du navigateur"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"écrire dans l\'historique et les favoris du navigateur"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si vous activez la mémoire de stockage USB, certaines applications en cours d\'utilisation seront fermées. Elles risquent de rester indisponibles jusqu\'à ce que la mémoire de stockage USB soit désactivée."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Échec du fonctionnement USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'appareil multimédia"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connecté en tant qu\'appareil photo"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connecté en tant que programme d\'installation"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Appuyez pour accéder aux autres options USB."</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater la mémoire USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater la carte SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formater la mémoire de stockage USB en effaçant tous les fichiers ? Cette action est irréversible."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilité"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN activé"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Appuyez ici pour gérer le réseau."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string> <string name="upload_file" msgid="2897957172366730416">"Sélectionner un fichier"</string> @@ -1090,23 +1108,18 @@ <string name="issued_to" msgid="454239480274921032">"Délivré à :"</string> <string name="common_name" msgid="2233209299434172646">"Nom commun :"</string> <string name="org_name" msgid="6973561190762085236">"Organisation :"</string> - <string name="org_unit" msgid="7265981890422070383">"Unité d\'organisation :"</string> + <string name="org_unit" msgid="7265981890422070383">"Unité organisationnelle :"</string> <string name="issued_by" msgid="2647584988057481566">"Émis par :"</string> <string name="validity_period" msgid="8818886137545983110">"Validité :"</string> <string name="issued_on" msgid="5895017404361397232">"Date d\'émission :"</string> <string name="expires_on" msgid="3676242949915959821">"Date d\'expiration :"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Numéro de série :"</string> + <string name="fingerprints" msgid="4516019619850763049">"Empreintes :"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Empreinte SHA-256 :"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte SHA-1 :"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tout afficher..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index acb7f27..cf119d5 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čitanje povijesti i oznaka preglednika"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Aplikaciji omogućuje čitanje svih URL-ova koje je preglednik posjetio i svih oznaka iz preglednika."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje povijesti i oznaka preglednika"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ako uključite USB pohranjivanje, neke aplikacije koje koristite zaustavit će se i možda neće biti dostupne sve dok ne isključite USB pohranjivanje."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Rad USB-a nije uspio"</string> <string name="dlg_ok" msgid="7376953167039865701">"U redu"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Spojen kao medijski uređaj"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Spojen kao fotoaparat"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Spojen kao instalacijski program"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Dodirnite za ostale opcije USB-a"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB memoriju"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj SD karticu"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatirati USB memoriju uz brisanje svih pohranjenih datoteka? Radnja se ne može poništiti!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Dostupnost"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Promjena pozadinske slike"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN je aktiviran."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"Dotaknite za upravljanje mrežom."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Povezan sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dotaknite za upravljanje mrežom."</string> <string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string> @@ -1094,19 +1112,14 @@ <string name="issued_by" msgid="2647584988057481566">"Izdao:"</string> <string name="validity_period" msgid="8818886137545983110">"Vrijedi do:"</string> <string name="issued_on" msgid="5895017404361397232">"Izdano dana:"</string> - <string name="expires_on" msgid="3676242949915959821">"Ističe dana:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="expires_on" msgid="3676242949915959821">"Istječe dana:"</string> + <string name="serial_number" msgid="758814067660862493">"Serijski broj:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Otisci prstiju:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 otisak prsta:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 otisak prsta:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Prikaži sve..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index b27fb83..5fc1c31 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -701,6 +701,18 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <string name="autofill_province" msgid="2231806553863422300">"Tartomány"</string> + <string name="autofill_postal_code" msgid="4696430407689377108">"Irányítószám"</string> + <string name="autofill_state" msgid="6988894195520044613">"Állam"</string> + <string name="autofill_zip_code" msgid="8697544592627322946">"Irányítószám"</string> + <string name="autofill_county" msgid="237073771020362891">"Ország"</string> + <string name="autofill_island" msgid="4020100875984667025">"Sziget"</string> + <string name="autofill_district" msgid="8400735073392267672">"Körzet"</string> + <string name="autofill_department" msgid="5343279462564453309">"Osztály"</string> + <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektúra"</string> + <string name="autofill_parish" msgid="8202206105468820057">"Közösség"</string> + <string name="autofill_area" msgid="3547409050889952423">"Terület"</string> + <string name="autofill_emirate" msgid="2893880978835698818">"Emirátus"</string> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"böngészési előzmények és könyvjelzők olvasása"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lehetővé teszi az alkalmazás számára a böngésző által felkeresett összes URL, valamint az összes könyvjelző olvasását."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"böngészési előzmények és könyvjelzők írása"</string> @@ -944,14 +956,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ha bekapcsolja az USB-tárat, egyes jelenleg használt alkalmazások leállnak és lehet, hogy nem lesznek elérhetők a tár újbóli kikapcsolásáig."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Az USB művelet sikertelen"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Csatlakoztatva médiaeszközként"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Csatlakoztatva kameraként"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Csatlakoztatva telepítőként"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Érintse meg a további USB-opciókért"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Az USB-tár formázása"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kártya formázása"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formázza az USB-tárat, törölve az összes ott tárolt fájlt? A művelet nem vonható vissza!"</string> @@ -1015,10 +1023,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Kisegítő lehetőségek"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Háttérkép"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Háttérkép megváltoztatása"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN aktiválva."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string> <string name="vpn_text" msgid="1610714069627824309">"Érintse meg a hálózat irányításához."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Csatlakozva ide: <xliff:g id="SESSION">%s</xliff:g>. Érintse meg a hálózat kezeléséhez."</string> <string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string> @@ -1095,18 +1101,13 @@ <string name="validity_period" msgid="8818886137545983110">"Érvényesség:"</string> <string name="issued_on" msgid="5895017404361397232">"Kiállítva:"</string> <string name="expires_on" msgid="3676242949915959821">"Lejár:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Sorozatszám:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Ujjlenyomatok:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ujjlenyomat:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ujjlenyomat:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Összes megtekintése..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 2bfb6ce..fa7fefb 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca riwayat dan bookmark Peramban"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Izinkan aplikasi membaca semua URL yang telah dikunjungi Peramban, dam semua bookmark Peramban."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tuliskan riwayat dan bookmark Peramban"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika Anda menghidupkan penyimpanan USB, sebagian aplikasi yang Anda gunakan akan berhenti dan mungkin tidak tersedia sampai Anda mematikan penyimpanan USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Operasi USB gagal"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Terhubung sebagai perangkat media"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Terhubung sebagai kamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Terhubung sebagai pemasang"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Sentuh untuk opsi USB lainnya"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format penyimpanan USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kartu SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format penyimpanan USB, menghapus semua berkas yang disimpan di sana? Tindakan tidak dapat diurungkan!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Aksesibilitas"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Ubah wallpaper"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN diaktifkan."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Ketuk untuk mengelola jaringan."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string> <string name="upload_file" msgid="2897957172366730416">"Pilih berkas"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validitas:"</string> <string name="issued_on" msgid="5895017404361397232">"Diterbitkan pada:"</string> <string name="expires_on" msgid="3676242949915959821">"Kedaluwarsa pada:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Nomor seri:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Sidik jari:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Sidik jari SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Sidik jari SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Lihat semua..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index fcb4e3a..6e19cb5 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -491,8 +491,8 @@ <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Consente a un\'applicazione di leggere dati storici di utilizzo della rete per reti e applicazioni specifiche."</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestione norme rete"</string> <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Consente a un\'applicazione di gestire le norme di rete e definire le regole specifiche delle applicazioni."</string> - <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifica dell\'effetto dell\'utilizzo della rete"</string> - <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Consente la modifica dell\'effetto dell\'utilizzo della rete sulle applicazioni. Da non usare per normali applicazioni."</string> + <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifica calcolo dell\'utilizzo della rete"</string> + <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Consente di modificare le modalità di calcolo dell\'utilizzo della rete da parte delle applicazioni. Da non usare per normali applicazioni."</string> <string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string> <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo"</string> <string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string> @@ -701,6 +701,18 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string> + <string name="autofill_postal_code" msgid="4696430407689377108">"Codice postale"</string> + <string name="autofill_state" msgid="6988894195520044613">"Stato"</string> + <string name="autofill_zip_code" msgid="8697544592627322946">"Codice postale"</string> + <string name="autofill_county" msgid="237073771020362891">"Contea"</string> + <string name="autofill_island" msgid="4020100875984667025">"Isola"</string> + <string name="autofill_district" msgid="8400735073392267672">"Distretto"</string> + <string name="autofill_department" msgid="5343279462564453309">"Reparto"</string> + <string name="autofill_prefecture" msgid="2028499485065800419">"Prefettura"</string> + <string name="autofill_parish" msgid="8202206105468820057">"Parrocchia"</string> + <string name="autofill_area" msgid="3547409050889952423">"Area"</string> + <string name="autofill_emirate" msgid="2893880978835698818">"Emirato"</string> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lettura cronologia e segnalibri del browser"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Consente all\'applicazione di leggere tutti gli URL visitati e tutti i segnalibri del browser."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"creazione cronologia e segnalibri del browser"</string> @@ -944,14 +956,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se attivi l\'archivio USB, alcune applicazioni in uso si bloccheranno e potrebbero risultare non disponibili finché non disattiverai l\'archivio USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Operazione USB non riuscita"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Collegato come dispositivo multimediale"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Collegato come fotocamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Collegato come installer"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Tocca per altre opzioni USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatta archivio USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatta scheda SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formattare l\'archivio USB cancellando tutti i file memorizzati al suo interno? Questa azione è irreversibile."</string> @@ -1015,10 +1023,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilità"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"La VPN è attiva."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Tocca per gestire la rete."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Collegata a <xliff:g id="SESSION">%s</xliff:g>. Tocca per gestire la rete."</string> <string name="upload_file" msgid="2897957172366730416">"Scegli file"</string> @@ -1095,18 +1101,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validità:"</string> <string name="issued_on" msgid="5895017404361397232">"Rilasciato il:"</string> <string name="expires_on" msgid="3676242949915959821">"Scade il:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Numero di serie:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Fingerprint:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Fingerprint SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Fingerprint SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Mostra tutto..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 31ae61f..9c8b81d 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"קרא היסטוריה וסימניות של דפדפן"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"מאפשר ליישום לקרוא את כל כתובות האתרים שבהן ביקר הדפדפן, ואת כל הסימניות של הדפדפן."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"כתיבת היסטוריה וסימניות של דפדפן"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"אם תפעיל אחסון USB, חלק מהיישומים שבהם אתה משתמש יעצרו ולא יהיו זמינים עד שתכבה את אחסון ה-USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"הפעלת ה-USB נכשלה"</string> <string name="dlg_ok" msgid="7376953167039865701">"אישור"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"מחובר כמכשיר מדיה"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"מחובר כמצלמה"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"מחובר כמתקין"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"גע לקבלת אפשרויות USB נוספות"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמט אמצעי אחסון מסוג USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"פרמוט כרטיס SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"לפרמט את אמצעי האחסון מסוג USB, תוך מחיקת כל הקבצים? הפעולה בלתי הפיכה!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"נגישות"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN מופעל."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"הקש כדי לנהל את הרשת."</string> <string name="vpn_text_long" msgid="4907843483284977618">"מחובר אל <xliff:g id="SESSION">%s</xliff:g>. הקש כדי לנהל את הרשת."</string> <string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"חוקיות:"</string> <string name="issued_on" msgid="5895017404361397232">"הונפק בתאריך:"</string> <string name="expires_on" msgid="3676242949915959821">"פג תוקף ב:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"מספר סידורי:"</string> + <string name="fingerprints" msgid="4516019619850763049">"טביעות אצבע:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"טביעת אצבע SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"טביעת אצבע SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"הצג הכל..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 9b7e80e..7614dd1 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">"、 "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ブラウザの履歴とブックマークを読み取る"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ブラウザでアクセスしたすべてのURLおよびブラウザのすべてのブックマークの読み取りをアプリケーションに許可します。"</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"ブラウザの履歴とブックマークを書き込む"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USBストレージをONにすると、使用中のアプリケーションの一部が停止し、USBストレージをOFFにするまで使用できなくなる場合があります。"</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB操作に失敗しました"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"メディアデバイスとして接続"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"カメラとして接続"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"インストーラとして接続"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"他のUSBオプションをタップしてください"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USBストレージのフォーマット"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USBストレージをフォーマットして、保存されているすべてのファイルを消去しますか?この操作は元に戻せません。"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"ユーザー補助"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPNが有効化されました。"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string> <string name="vpn_text" msgid="1610714069627824309">"ネットワークを管理するにはタップしてください。"</string> <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>に接続しました。ネットワークを管理するにはタップしてください。"</string> <string name="upload_file" msgid="2897957172366730416">"ファイルを選択"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"有効期間:"</string> <string name="issued_on" msgid="5895017404361397232">"発行:"</string> <string name="expires_on" msgid="3676242949915959821">"有効期限:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"シリアル番号:"</string> + <string name="fingerprints" msgid="4516019619850763049">"指紋:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256指紋:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1指紋:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"すべて見る..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 15b3240..b47d090 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"브라우저의 기록 및 북마크 읽기"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"애플리케이션이 브라우저로 방문한 모든 URL과 브라우저의 모든 북마크를 읽도록 허용합니다."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"브라우저의 기록 및 북마크 쓰기"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB 저장소를 사용하면 사용 중인 일부 애플리케이션이 중지되어 USB 저장소를 사용 중지할 때까지 사용할 수 없게 됩니다."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB 작업 실패"</string> <string name="dlg_ok" msgid="7376953167039865701">"확인"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"미디어 기기로 연결됨"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"카메라로 연결됨"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"설치 프로그램으로 연결됨"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"다른 USB 옵션을 보려면 터치하세요."</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB 저장소 포맷"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB 저장소를 포맷하여 저장된 파일을 모두 지우시겠습니까? 수행한 후에는 작업을 취소할 수 없습니다."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"접근성"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN이 활성화되어 있습니다."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string> <string name="vpn_text" msgid="1610714069627824309">"네트워크를 관리하려면 누르세요."</string> <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>에 연결되어 있습니다. 네트워크를 관리하려면 누르세요."</string> <string name="upload_file" msgid="2897957172366730416">"파일 선택"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"유효성:"</string> <string name="issued_on" msgid="5895017404361397232">"발급 날짜:"</string> <string name="expires_on" msgid="3676242949915959821">"만료 날짜:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"일련번호:"</string> + <string name="fingerprints" msgid="4516019619850763049">"지문:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 지문:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 지문:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"전체 보기..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index b57455f..44d8dc6 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"skaityti naršyklės istoriją ir žymes"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Leidžia programai skaityti visus URL, kuriuose apsilankė naršyklė, ir visas naršyklės žymas."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rašyti naršyklės istoriją ir žymes"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jei įjungiate USB saugyklą, kai kurios naudojamos programos sustos ir gali būti negalimos, kol išjungsite USB saugyklą."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB operacija nepavyko"</string> <string name="dlg_ok" msgid="7376953167039865701">"Gerai"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Prij. kaip medijos įrenginys"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Prij. kaip fotoap."</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Prij. kaip diegimo programa"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Jei norite matyti kitas USB parinktis, palieskite"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB atmint."</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuoti SD kortelę"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatuoti USB atmintinę ištrinant visus joje saugomus failus? Veiksmo nebus galima atšaukti!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Pasiekiamumas"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Darbalaukio fonas"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Keisti darbalaukio foną"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN suaktyvintas."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string> <string name="vpn_text" msgid="1610714069627824309">"Jei norite valdyti tinklą, palieskite."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Prisijungta prie <xliff:g id="SESSION">%s</xliff:g>. Jei norite valdyti tinklą, palieskite."</string> <string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Galiojimas:"</string> <string name="issued_on" msgid="5895017404361397232">"Išduota:"</string> <string name="expires_on" msgid="3676242949915959821">"Galiojimas baigiasi:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serijos numeris:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Kontroliniai kodai"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 kontrolinis kodas"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 kontrolinis kodas"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Žr. viską..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 6fed017..bc8b64c 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -701,6 +701,18 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <string name="autofill_province" msgid="2231806553863422300">"Province"</string> + <string name="autofill_postal_code" msgid="4696430407689377108">"Pasta indekss"</string> + <string name="autofill_state" msgid="6988894195520044613">"Štats"</string> + <string name="autofill_zip_code" msgid="8697544592627322946">"Pasta indekss"</string> + <string name="autofill_county" msgid="237073771020362891">"Apgabals"</string> + <string name="autofill_island" msgid="4020100875984667025">"Sala"</string> + <string name="autofill_district" msgid="8400735073392267672">"Rajons"</string> + <string name="autofill_department" msgid="5343279462564453309">"Departaments"</string> + <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektūra"</string> + <string name="autofill_parish" msgid="8202206105468820057">"Pagasts"</string> + <string name="autofill_area" msgid="3547409050889952423">"Reģions"</string> + <string name="autofill_emirate" msgid="2893880978835698818">"Emirāts"</string> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lasīt pārlūkprogrammas vēsturi un grāmatzīmes"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ļauj lietojumprogrammai lasīt visus URL, kas ir apmeklēti pārlūkprogrammā, un visas pārlūkprogrammas grāmatzīmes."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rakstīt pārlūkprogrammas vēsturi un grāmatzīmes"</string> @@ -944,14 +956,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ja ieslēgsiet USB krātuvi, dažu joprojām lietoto lietojumprogrammu darbība tiks apturēta un tās, iespējams, nebūs pieejamas līdz brīdim, kad USB krātuve tiks izslēgta."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB darbība neizdevās."</string> <string name="dlg_ok" msgid="7376953167039865701">"Labi"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pievienots kā multivides ierīce"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pievienots kā kamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pievienots kā instalēšanas programma"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Pieskarieties, lai skatītu citas USB opcijas."</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB kr. formatēšana"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartes formatēšana"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vai formatēt USB krātuvi, dzēšot visus tajā saglabātos failus? Šo darbību nevar atcelt."</string> @@ -1015,10 +1023,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Pieejamība"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN ir aktivizēts."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string> <string name="vpn_text" msgid="1610714069627824309">"Pieskarieties, lai pārvaldītu tīklu."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Ir izveidots savienojums ar: <xliff:g id="SESSION">%s</xliff:g>. Pieskarieties, lai pārvaldītu tīklu."</string> <string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string> @@ -1095,18 +1101,13 @@ <string name="validity_period" msgid="8818886137545983110">"Derīgums:"</string> <string name="issued_on" msgid="5895017404361397232">"Izsniegšanas datums:"</string> <string name="expires_on" msgid="3676242949915959821">"Derīguma termiņš:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Sērijas numurs:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Identifikatori"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 identifikators"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 identifikators:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Skatīt visas"</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 87b169d..2cf00e0 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -729,6 +729,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca sejarah dan penanda halaman Penyemak imbas"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Membenarkan aplikasi membaca semua URL yang telah dilawati oleh Penyemak Imbas dan semua penanda halaman Penyemak Imbas."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tulis sejarah dan penanda halaman Penyemak Imbas"</string> @@ -972,14 +996,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika anda menghidupkan storan USB, sesetengah aplikasi yang anda sedang gunakan akan terhenti dan mungkin tidak akan tersedia sehingga anda memadamkan storan USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Pengendalian USB gagal"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Disambungkan sebagai peranti media"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Disambungkan sebagai kamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Disambungkan sebagai pemasang"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Sentuh untuk mendapatkan pilihan USB yang lain"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format storan USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kad SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format storan USB, memadamkan semua fail yang disimpan? Tindakan tidak boleh dibalikkan!"</string> @@ -1043,10 +1063,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Kebolehaksesan"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN diaktifkan."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string> <!-- no translation found for vpn_text (1610714069627824309) --> <skip /> <!-- no translation found for vpn_text_long (4907843483284977618) --> @@ -1146,10 +1164,9 @@ <skip /> <!-- no translation found for sha1_fingerprint (7930330235269404581) --> <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Lihat semua..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index ca40558..67429b5 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lese nettleserens logg og bokmerker"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lar applikasjonen lese alle adresser nettleseren har besøkt, og alle nettleserens bokmerker."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skrive til nettleserens logg og bokmerker"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du aktiverer USB-lagring, virker ikke lenger enkelte av programmene du bruker, og de kan være utilgjengelige inntil du deaktiverer USB-lagringen."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB-operasjonen mislyktes"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilkoblet som medieenhet"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilkoblet som kamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilkoblet som installasjonsprogram"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Berør for andre USB-alternativer"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formaterer USB-lagring"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatere minnekort"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lagring og slette alle lagrede filer? Handlingen kan ikke angres!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgjengelighet"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Velg bakgrunnsbilde"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN er aktivert."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Trykk for å administrere nettverket."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Koblet til <xliff:g id="SESSION">%s</xliff:g>. Trykk for å administrere nettverket."</string> <string name="upload_file" msgid="2897957172366730416">"Velg fil"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Gyldighet:"</string> <string name="issued_on" msgid="5895017404361397232">"Utstedt den:"</string> <string name="expires_on" msgid="3676242949915959821">"Utløper den:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Fingeravtrykk"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeravtrykk"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeravtrykk"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Se alle"</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 757091f..fe21bc8 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"browsergeschiedenis en bladwijzers lezen"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Hiermee kan een app de URL\'s lezen die u via de browser heeft bezocht, evenals alle bladwijzers van de browser."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"browsergeschiedenis en bladwijzers schrijven"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Als u USB-opslag inschakelt, worden bepaalde apps die u gebruikt, gestopt en worden deze mogelijk pas weer beschikbaar wanneer u USB-opslag uitschakelt."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking mislukt"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Gekoppeld als media-apparaat"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Gekoppeld als camera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Gekoppeld als installatieprogramma"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Raak aan voor andere USB-opties"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-opslag formatt."</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kaart formatteren"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-opslag formatteren en alle opgeslagen bestanden wissen? Actie kan niet ongedaan worden gemaakt."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Toegankelijkheid"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN is geactiveerd."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Tik om het netwerk te beheren."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Verbonden met <xliff:g id="SESSION">%s</xliff:g>. Tik om het netwerk te beheren."</string> <string name="upload_file" msgid="2897957172366730416">"Bestand kiezen"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Geldigheid:"</string> <string name="issued_on" msgid="5895017404361397232">"Uitgegeven op:"</string> <string name="expires_on" msgid="3676242949915959821">"Verloopt op:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Vingerafdrukken:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-vingerafdruk"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-vingerafdruk:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Alle bekijken..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 85f2bad..60c9bdb 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"odczyt historii i zakładek przeglądarki"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umożliwia aplikacji odczyt wszystkich adresów URL odwiedzonych przez przeglądarkę, a także wszystkich zakładek przeglądarki."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zapis historii i zakładek przeglądarki"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Po włączeniu nośnika USB niektóre używane aplikacje zostaną zatrzymane i mogą być niedostępne do chwili wyłączenia nośnika USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Operacja USB nie powiodła się"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Podłączono jako urządzenie multimedialne."</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Podłączono jako aparat."</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Podłączono jako nośnik instalacyjny."</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Dotknij, aby wyświetlić inne opcje USB."</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatuj nośnik USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuj kartę SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Czy sformatować nośnik USB i wymazać wszystkie zapisane na nim pliki? Tej czynności nie można cofnąć."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Ułatwienia dostępu"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Obsługa sieci VPN została włączona"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Dotknij, aby zarządzać siecią."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Nawiązano połączenie: <xliff:g id="SESSION">%s</xliff:g>. Dotknij, aby zarządzać siecią."</string> <string name="upload_file" msgid="2897957172366730416">"Wybierz plik"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Ważność:"</string> <string name="issued_on" msgid="5895017404361397232">"Data wystawienia:"</string> <string name="expires_on" msgid="3676242949915959821">"Wygasa:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Numer seryjny:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Odciski cyfrowe:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Odcisk cyfrowy SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Odcisk cyfrowy SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Pokaż wszystkie"</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 9761b71..6af09f3 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e marcadores do browser"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que a aplicação leia todos os URLs visitados pelo browser e todos os marcadores do browser."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e marcadores do browser"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se activar o armazenamento USB, algumas aplicações que estiver a utilizar serão paradas e poderão ficar indisponíveis até desactivar o armazenamento USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Falha na operação USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ligado como um aparelho multimédia"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ligado como uma câmara"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ligado como um instalador"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Toque para outras opções USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar armazenamento USB e apagar todos os ficheiros armazenados? Não é possível reverter a acção!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"A VPN está ativa"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Toque para gerir a rede."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string> <string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validade:"</string> <string name="issued_on" msgid="5895017404361397232">"Emitido em:"</string> <string name="expires_on" msgid="3676242949915959821">"Expira em:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Número de série:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Impressões digitais:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Impressão digital SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Impressão digital SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver tudo..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index a56523f..d762274 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e favoritos do Navegador"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que o aplicativo leia todos os URLs visitados pelo Navegador e todos os favoritos do Navegador."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e favoritos do Navegador"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se você ativar o armazenamento USB, alguns aplicativos que estão em uso serão interrompidos e poderão não estar disponíveis até você desativar o armazenamento USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Falha de operação de USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como um dispositivo de mídia"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectadas como uma câmera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectados como um instalador"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Toque para obter outras opções USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar o armazenamento USB, apagando todos os arquivos armazenados? A ação não pode ser revertida!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"A VPN está ativada."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Toque para gerenciar a rede."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string> <string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validade:"</string> <string name="issued_on" msgid="5895017404361397232">"Emitido em:"</string> <string name="expires_on" msgid="3676242949915959821">"Expira em:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Número de série:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Impressões digitais"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Impressão digital SHA-256"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Impressão digital SHA-1"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todos..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml index 7048c69..5fd5d45 100644 --- a/core/res/res/values-rm/strings.xml +++ b/core/res/res/values-rm/strings.xml @@ -781,6 +781,30 @@ <skip /> <!-- no translation found for autofill_address_summary_format (4874459455786827344) --> <skip /> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leger la cronologia ed ils segnapaginas dal navigatur"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"\"Permetta a l\'applicaziun da leger tut las URLs visitadas, sco era ils segnapaginas dal navigatur.\""</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"scriver en la cronologia ed en ils segnapaginas dal navigatur"</string> @@ -1251,8 +1275,8 @@ <skip /> <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 69b111e..ad3d64d 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"citire istoric şi marcaje în browser"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite aplicaţiei să citească toate adresele URL vizitate din browser şi toate marcajele din acesta."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"citire istoric şi marcaje în browser"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Dacă activaţi stocarea USB, unele aplicaţii pe care le utilizaţi în prezent se vor opri şi ar putea să nu fie disponibile până când dezactivaţi stocarea USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Operaţie USB nereuşită"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectat ca dispozitiv media"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectat ca aparat foto"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectat ca program de instalare"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Atingeţi pentru alte opţiuni USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formataţi stoc. USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formataţi cardul SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formataţi stocarea USB, ştergând toate fişierele stocate aici? Acţiunea nu poate fi anulată!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilitate"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN este activată."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Apăsaţi pentru a gestiona reţeaua."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Apăsaţi pentru a gestiona reţeaua."</string> <string name="upload_file" msgid="2897957172366730416">"Alegeţi un fişier"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Validitate:"</string> <string name="issued_on" msgid="5895017404361397232">"Emis pe:"</string> <string name="expires_on" msgid="3676242949915959821">"Expiră pe:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Număr de serie:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Amprente:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Amprentă SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Amprentă SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Afişaţi-le pe toate..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 95d4077..0bc2f44 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"считывать историю и закладки браузера"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешает приложению считывать все URL, посещенные браузером, и все его закладки."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"записывать историю и закладки браузера"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"При включении USB-накопителя некоторые используемые приложения могут прекратить работу и оставаться недоступными до отключения USB-накопителя."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Сбой операции USB-подключения"</string> <string name="dlg_ok" msgid="7376953167039865701">"ОК"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Подключен как устройство хранения данных"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Подключен как камера"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Подключен как установщик"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Нажмите, чтобы увидеть другие параметры USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирование"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматирование USB-накопителя безвозвратно удалит все файлы на нем! Продолжить?"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Спец. возможности"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Сеть VPN активна."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Нажмите здесь, чтобы изменить настройки сети."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Подключено: \"<xliff:g id="SESSION">%s</xliff:g>\". Нажмите здесь, чтобы изменить настройки сети."</string> <string name="upload_file" msgid="2897957172366730416">"Выбрать файл"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Срок действия:"</string> <string name="issued_on" msgid="5895017404361397232">"Дата выпуска:"</string> <string name="expires_on" msgid="3676242949915959821">"Срок действия:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Серийный номер:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Отпечатки:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Отпечаток SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Отпечаток SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Просмотреть все"</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index e622cf1..d836312 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Čítanie histórie a záložiek prehliadača"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikácii čítať všetky adresy URL navštívené prehliadačom a záložky prehliadača."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Zapisovať históriu a záložky prehliadača"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ak zapnete ukladací priestor USB, dôjde k zastaveniu niektorých používaných aplikácií. Tieto aplikácie pravdepodobne nebudú k dispozícii až do vypnutia ukladacieho priestoru USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operácie na rozhraní USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pripojené ako mediálne zariadenie"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pripojené ako fotoaparát"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pripojené ako inštalátor"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Dotykom zobrazíte ďalšiu možnosť USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formát. ukl. priestor USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovať kartu SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete ukladací priestor USB naformátovať a vymazať tak všetky súbory, ktoré sú v ňom uložené? Túto akciu nie je možné vrátiť späť."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Zjednodušenie"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Sieť VPN je aktivovaná."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"Kliknutím zobrazíte správu siete."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Pripojené k relácii <xliff:g id="SESSION">%s</xliff:g>. Po klepnutí môžete sieť spravovať."</string> <string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Platnosť:"</string> <string name="issued_on" msgid="5895017404361397232">"Dátum vydania:"</string> <string name="expires_on" msgid="3676242949915959821">"Platnosť vyprší:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Sériové číslo:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Digitálne odtlačky:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Digitálny odtlačok SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Digitálny odtlačok SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Zobraziť všetko..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index d68a3a5..9c43047 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -492,7 +492,7 @@ <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"upravljanje pravilnika o omrežju"</string> <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Programu omogoča upravljanje pravilnikov o omrežju in določanje pravil za program."</string> <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"spremeni obračunavanje uporabe omrežja"</string> - <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Omogoča spreminjanje načina obračunavanja uporabe omrežja za posamezne programe. Ni za uporabo za pri navadnih programih."</string> + <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Omogoča spreminjanje načina obračunavanja uporabe omrežja za posamezne programe. Ni za uporabo pri navadnih programih."</string> <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string> <string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona"</string> <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string> @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"branje zgodovine in zaznamkov brskalnika"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Programu dovoljuje branje vseh URL-jev, ki jih je brskalnik obiskal, in vseh brskalnikovih zaznamkov."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje zgodovine in zaznamkov brskalnika"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Če vklopite shrambo USB, bodo nekateri programi, ki jih uporabljate, ustavljeni in morda ne bodo na voljo, dokler je ne izklopite."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Operacija USB ni uspela"</string> <string name="dlg_ok" msgid="7376953167039865701">"V redu"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Povezan kot predstavnostna naprava"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Povezan kot fotoaparat"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Povezan kot namestitveni program"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Dotaknite se, če želite izbrati druge možnosti za USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatiranje pomnilnika USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj kartico SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ali želite formatirati pomnilnik USB in izbrisati vse datoteke, shranjene na njem? Dejanje je dokončno."</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Pripomočki za osebe s posebnimi potrebami"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ozadje"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Spreminjanje ozadja"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN je aktiviran."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktiviral program <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Tapnite za upravljanje omrežja."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Povezan z mestom <xliff:g id="SESSION">%s</xliff:g>. Tapnite za upravljanje omrežja."</string> <string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Veljavnost:"</string> <string name="issued_on" msgid="5895017404361397232">"Izdano:"</string> <string name="expires_on" msgid="3676242949915959821">"Velja do:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serijska številka:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Prstni odtisi:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Prstni odtis SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Prstni odtis SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Prikaži vse ..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 1604a94..ec6470e 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читање историје и обележивача у прегледачу"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Омогућава да апликација чита све URL адресе које су посећене у прегледачу, као и све обележиваче у њему."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"уписивање историје и обележивача из прегледача"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако укључите USB складиште, поједине апликације које користите престаће да раде и могу да постану недоступне док га поново не укључите."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Грешка са USB складиштем"</string> <string name="dlg_ok" msgid="7376953167039865701">"Потврди"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Повезан као медијски уређај"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Повезан као камера"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Повезан као инсталациони програм"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Додирните за друге USB опције"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање USB меморије"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматирање SD картице"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Желите да форматирате USB меморију и избришете све датотеке у њој? Ову радњу није могуће опозвати!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Приступачност"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN је активиран."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"Додирните да бисте управљали мрежом."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Повезано са сесијом <xliff:g id="SESSION">%s</xliff:g>. Додирните да бисте управљали мрежом."</string> <string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Важност:"</string> <string name="issued_on" msgid="5895017404361397232">"Издато:"</string> <string name="expires_on" msgid="3676242949915959821">"Истиче:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Серијски број:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Дигитални отисци:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 дигитални отисак:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 дигитални отисак:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Прикажи све..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index d3e3848..d7bc859 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"läsa webbläsarhistorik och bokmärken"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillåter att program läser alla webbadresser som webbläsaren har öppnat och alla webbläsarens bokmärken."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriva webbläsarhistorik och bokmärken"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Om du aktiverar USB-lagring avbryts några av de appar som körs och de kanske inte blir tillgängliga igen förrän du inaktiverar USB-lagring."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB-åtgärd misslyckades"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ansluten som en mediaenhet"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ansluten som en kamera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ansluten som installationsprogram"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Tryck för andra USB-alternativ"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatera USB-enhet"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatera SD-kort"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatera SD-kort och radera alla filer? Åtgärden kan inte ångras!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Tillgänglighet"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN är aktiverad."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Knacka lätt för att hantera nätverket."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Ansluten till <xliff:g id="SESSION">%s</xliff:g>. Knacka lätt för att hantera nätverket."</string> <string name="upload_file" msgid="2897957172366730416">"Välj fil"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Giltighet:"</string> <string name="issued_on" msgid="5895017404361397232">"Utfärdat den:"</string> <string name="expires_on" msgid="3676242949915959821">"Upphör att gälla:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serienummer:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Fingeravtryck:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeravtryck"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeravtryck:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Visa alla..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 0bf9ddf..6d7de63 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -931,6 +931,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"soma historia na alamisho za Kivinjari"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Huruhusu programu kusoma URL zote ambazo Kivinjari imetembelea, na alamisho zile zingine zote za Kivinjari."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"andika historia ya Kivinjari na alamisho"</string> @@ -1437,8 +1461,8 @@ <skip /> <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 2d5b249..a75929f 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"อ่านประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"อนุญาตให้แอปพลิเคชันอ่าน URL ทั้งหมดที่เบราว์เซอร์เคยเข้าชมและบุ๊กมาร์กของเบราว์เซอร์ทั้งหมด"</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"เขียนประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"หากคุณเปิดที่จัดเก็บข้อมูล USB แอปพลิเคชันบางอย่างที่คุณใช้อยู่จะหยุดและอาจใช้งานไม่ได้จนกว่าคุณจะปิดที่จัดเก็บข้อมูล USB"</string> <string name="dlg_error_title" msgid="8048999973837339174">"การปฏิบัติงานของ USB ล้มเหลว"</string> <string name="dlg_ok" msgid="7376953167039865701">"ตกลง"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"เชื่อมต่อเป็นอุปกรณ์สื่อ"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"เชื่อมต่อเป็นกล้องถ่ายรูป"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"เชื่อมต่อเป็นตัวติดตั้ง"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"แตะสำหรับตัวเลือก USB อื่นๆ"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตที่เก็บข้อมูล USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"ฟอร์แมตการ์ด SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"ฟอร์แมตที่เก็บข้อมูล USB โดยลบไฟล์ทั้งหมดที่จัดเก็บอยู่ในนั้นหรือไม่ การทำงานนี้ไม่สามารถย้อนกลับได้"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"การเข้าถึง"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN เปิดใช้งานแล้ว"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"แตะเพื่อจัดการเครือข่าย"</string> <string name="vpn_text_long" msgid="4907843483284977618">"เชื่อมต่อกับ <xliff:g id="SESSION">%s</xliff:g> แตะเพื่อจัดการเครือข่าย"</string> <string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"อายุการใช้งาน:"</string> <string name="issued_on" msgid="5895017404361397232">"ออกเมื่อ:"</string> <string name="expires_on" msgid="3676242949915959821">"หมดอายุวันที่:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"หมายเลขซีเรียล:"</string> + <string name="fingerprints" msgid="4516019619850763049">"ลายนิ้วมือ"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"ลายนิ้วมือ SHA-256"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"ลายนิ้วมือ SHA-1"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"ดูทั้งหมด..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 5b3eed0..55209f4 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"basahin ang kasaysayan at mga bookmark ng Browser"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Pinapayagan ang application na basahin ang lahat ng URL na binisita ng Browser, at lahat ng bookmark ng Browser."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"isulat ang kasaysayan ng Browser at mga bookmark"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Kung io-on mo ang USB storage, titigil ang ilang application na ginagamit mo at maaaring maging hindi available hanggang sa i-off mo ang USB storage."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Nabigo ang pagpapatakbo ng USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Nakakonekta bilang isang media device"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Nakakonekta bilang isang camera"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Nakakonekta bilang isang installer"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"I-touch para sa mga ibang pagpipilian sa USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"I-format USB storage"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"I-format ang SD card"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"I-format ang imbakan na USB, na binubura ang lahat ng mga file na nakaimbak doon? Hindi maaaring maibalik ang pagkilos!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Kakayahang Ma-access"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Isinaaktibo ang VPN."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Tapikin upang pamahalaan ang network."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Nakakonekta sa <xliff:g id="SESSION">%s</xliff:g>. Tapikin upang pamahalaan ang network."</string> <string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Pagkabisa:"</string> <string name="issued_on" msgid="5895017404361397232">"Ibinigay noong:"</string> <string name="expires_on" msgid="3676242949915959821">"Mag-e-expire sa:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Serial number:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Mga fingerprint:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 na fingerprint:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 na fingerprint:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tingnan lahat..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 8aea16d..b4a6922 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Tarayıcı geçmişini ve favorileri oku"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Uygulamaya Tarayıcının ziyaret etmiş olduğu tüm URL\'leri ve Tarayıcının tüm favorilerini okuma izni verir."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Tarayıcı geçmişini ve favorileri yaz"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB depolama birimini açarsanız, kullanmakta olduğunuz bazı uygulamalar durur ve USB depolama birimi kapatılıncaya kadar kullanılamayabilir."</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB işlemi başarısız oldu"</string> <string name="dlg_ok" msgid="7376953167039865701">"Tamam"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Medya cihazı olarak bağlandı"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kamera olarak bağlandı"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Yükleyici olarak bağlandı"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Diğer USB seçenekleri için dokunun"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB\'yi biçimlendir"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartı biçimlendir"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB depolama birimi biçimlendirilsin mi? Depolama biriminde saklanan tüm dosyalar silinir. İşlem geri alınamaz!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Erişebilirlik"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN etkinleştirildi."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string> <string name="vpn_text" msgid="1610714069627824309">"Ağı yönetmek için hafifçe vurun."</string> <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> oturumuna bağlı. Ağı yönetmek için hafifçe vurun."</string> <string name="upload_file" msgid="2897957172366730416">"Dosya seç"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Geçerlilik:"</string> <string name="issued_on" msgid="5895017404361397232">"Yayınlanma tarihi:"</string> <string name="expires_on" msgid="3676242949915959821">"Sona erme tarihi:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Seri numara:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Parmak izleri:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 parmak izi:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 parmak izi:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tümünü göster..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 5f50208..e813b92 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -701,6 +701,18 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <string name="autofill_province" msgid="2231806553863422300">"Провінція"</string> + <string name="autofill_postal_code" msgid="4696430407689377108">"Поштовий код"</string> + <string name="autofill_state" msgid="6988894195520044613">"Штат"</string> + <string name="autofill_zip_code" msgid="8697544592627322946">"Поштовий індекс"</string> + <string name="autofill_county" msgid="237073771020362891">"Округ"</string> + <string name="autofill_island" msgid="4020100875984667025">"Острів"</string> + <string name="autofill_district" msgid="8400735073392267672">"Район"</string> + <string name="autofill_department" msgid="5343279462564453309">"Відділ"</string> + <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string> + <string name="autofill_parish" msgid="8202206105468820057">"Община"</string> + <string name="autofill_area" msgid="3547409050889952423">"Область"</string> + <string name="autofill_emirate" msgid="2893880978835698818">"Емірат"</string> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читати історію та закладки переглядача"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Дозволяє програмі зчитувати всі URL-адреси, на які заходив переглядач, і всі закладки переглядача."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис. історію та закладки переглядача"</string> @@ -944,14 +956,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Якщо ввімкнути носій USB, деякі програми, які викор., припинять свою роботу та можуть бути недоступними до вимкнення носія USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Помилка операції з USB"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Під’єднано як носій"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Під’єднано як камеру"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Під’єднано як програму встановлення"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Торкніться, щоб побачити інші параметри USB"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматув. носій USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Формат. карти SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматувати носій USB, видаляючи всі збережені файли? Дію не можна скасувати!"</string> @@ -1015,10 +1023,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Доступність"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фон. мал."</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"Мережу VPN активовано."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="1610714069627824309">"Торкніться, щоб керувати мережею."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Під’єднано до <xliff:g id="SESSION">%s</xliff:g>. Торкніться, щоб керувати мережею."</string> <string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string> @@ -1095,18 +1101,13 @@ <string name="validity_period" msgid="8818886137545983110">"Чинність:"</string> <string name="issued_on" msgid="5895017404361397232">"Дата видачі:"</string> <string name="expires_on" msgid="3676242949915959821">"Діє до:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Серійний номер:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Відбитки:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Відбиток SHA-256"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Відбиток SHA-1"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Показати всі..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 38e33e3..dd2c19d 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"đọc lịch sử và dấu trang của Trình duyệt"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Cho phép ứng dụng đọc tất cả các URL mà Trình duyệt đã truy cập và tất cả các dấu trang của Trình duyệt."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"xem lịch sử và dấu trang của Trình duyệt"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Nếu bạn bật bộ lưu trữ USB, một số ứng dụng bạn đang sử dụng sẽ dừng và có thể không khả dụng cho tới khi bạn tắt bộ lưu trữ USB."</string> <string name="dlg_error_title" msgid="8048999973837339174">"Thao tác USB không thành công"</string> <string name="dlg_ok" msgid="7376953167039865701">"OK"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Đã kết nối là thiết bị truyền thông"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Đã kết nối như máy ảnh"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Được kết nối như trình cài đặt"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"Chạm để có các tùy chọn USB khác"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Định dạng b.nhớ USB"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Định dạng thẻ SD"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Định dạng bộ nhớ USB, xóa tất cả tệp được lưu trữ tại đây? Không thể hoàn tác tác vụ!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"Khả năng truy cập"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN được kích hoạt."</string> + <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string> <string name="vpn_text" msgid="1610714069627824309">"Chạm để quản lý mạng."</string> <string name="vpn_text_long" msgid="4907843483284977618">"Đã kết nối với <xliff:g id="SESSION">%s</xliff:g>. Chạm để quản lý mạng."</string> <string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"Tính hợp lệ:"</string> <string name="issued_on" msgid="5895017404361397232">"Cấp vào:"</string> <string name="expires_on" msgid="3676242949915959821">"Hết hạn vào:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"Số sê-ri:"</string> + <string name="fingerprints" msgid="4516019619850763049">"Tệp tham chiếu:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"Tệp tham chiếu SHA-256:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"Tệp tham chiếu SHA-1:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"Xem tất cả..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 863e3fa..0fb0106 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"读取浏览器的历史记录和书签"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允许应用程序读取用浏览器访问过的所有网址,以及浏览器的所有书签。"</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您打开了 USB 存储设备,则您当前使用的某些应用程序会停止,而且在您关闭 USB 存储设备前可能都无法使用。"</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失败"</string> <string name="dlg_ok" msgid="7376953167039865701">"确定"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"作为媒体设备连接"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"作为相机连接"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"作为安装程序连接"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"触摸可显示其他 USB 选项"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 存储设备"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"确定要格式化 USB 存储设备,清除其中存储的全部文件吗?该操作将无法撤消!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"辅助功能"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN 已激活。"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"点按即可管理网络。"</string> <string name="vpn_text_long" msgid="4907843483284977618">"已连接到<xliff:g id="SESSION">%s</xliff:g>。点按即可管理网络。"</string> <string name="upload_file" msgid="2897957172366730416">"选择文件"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"有效期:"</string> <string name="issued_on" msgid="5895017404361397232">"颁发时间:"</string> <string name="expires_on" msgid="3676242949915959821">"有效期至:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"序列号:"</string> + <string name="fingerprints" msgid="4516019619850763049">"指纹:"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 指纹:"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指纹:"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"查看全部..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index a9a6e4e..bf33dbf 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -701,6 +701,30 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"讀取瀏覽器的記錄與書籤"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string> @@ -944,14 +968,10 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您開啟 USB 儲存裝置,則您正在使用的某些應用程式會停止運作,而且可能無法使用,待您將 USB 儲存裝置關閉才會恢復正常。"</string> <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失敗"</string> <string name="dlg_ok" msgid="7376953167039865701">"確定"</string> - <!-- no translation found for usb_mtp_notification_title (3699913097391550394) --> - <skip /> - <!-- no translation found for usb_ptp_notification_title (1960817192216064833) --> - <skip /> - <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) --> - <skip /> - <!-- no translation found for usb_notification_message (4447869605109736382) --> - <skip /> + <string name="usb_mtp_notification_title" msgid="3699913097391550394">"已視為媒體裝置連線"</string> + <string name="usb_ptp_notification_title" msgid="1960817192216064833">"已視為相機連線"</string> + <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"已視為安裝程式連線"</string> + <string name="usb_notification_message" msgid="4447869605109736382">"輕觸即可顯示其他 USB 選項"</string> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 儲存空間"</string> <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"格式化 USB 儲存裝置時,是否清除其中儲存的所有檔案?這項動作無法復原!"</string> @@ -1015,10 +1035,8 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"協助工具"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string> - <!-- no translation found for vpn_title (8219003246858087489) --> - <skip /> - <!-- no translation found for vpn_title_long (6400714798049252294) --> - <skip /> + <string name="vpn_title" msgid="8219003246858087489">"VPN 已啟用。"</string> + <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string> <string name="vpn_text" msgid="1610714069627824309">"輕按一下即可管理網路。"</string> <string name="vpn_text_long" msgid="4907843483284977618">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕按一下即可管理網路。"</string> <string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string> @@ -1095,18 +1113,13 @@ <string name="validity_period" msgid="8818886137545983110">"有效期間:"</string> <string name="issued_on" msgid="5895017404361397232">"發佈日期:"</string> <string name="expires_on" msgid="3676242949915959821">"到期日:"</string> - <!-- no translation found for serial_number (758814067660862493) --> - <skip /> - <!-- no translation found for fingerprints (4516019619850763049) --> - <skip /> - <!-- no translation found for sha256_fingerprint (4391271286477279263) --> - <skip /> - <!-- no translation found for sha1_fingerprint (7930330235269404581) --> - <skip /> - <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> - <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <string name="serial_number" msgid="758814067660862493">"序號:"</string> + <string name="fingerprints" msgid="4516019619850763049">"指紋"</string> + <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 指紋"</string> + <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指紋"</string> + <string name="activity_chooser_view_see_all" msgid="180268188117163072">"查看所有活動..."</string> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index e712d7b..0e05ad5 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -298,7 +298,7 @@ <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Ivumela uhlelo lokusebena ukufunda imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zifunde imiyalezo eyimfihlo."</string> <!-- no translation found for permlab_writeSms (6881122575154940744) --> <skip /> - <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe kwithebhulethi yakho noma ekhadini le-SIM. Izinhlelo ezi-malicious zingase zisuse imiyalezo yakho."</string> + <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe kwithebhulethi yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zisuse imiyalezo yakho."</string> <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zisuse imiyalezo yakho."</string> <!-- no translation found for permlab_receiveWapPush (8258226427716551388) --> <skip /> @@ -341,7 +341,7 @@ <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Igwema umsebenzisi ukuba ashintshele kolunye uhlelo lokusebenza."</string> <!-- no translation found for permlab_runSetActivityWatcher (7811586187574696296) --> <skip /> - <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ivumela uhlelo lokusebenza ukugada nokulawula indlela uhlelo oluqalisa ngayo imisebenzi. Izinhlelo ezi-malicious zingase zonakalise ngokuphelele uhlelo. Le mvume idingeka kuphela ekuthuthukiseni, hayi ekusebenziseni ifoni okuvamile."</string> + <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ivumela uhlelo lokusebenza ukugada nokulawula indlela uhlelo oluqalisa ngayo imisebenzi. Izinhlelo ezinonya zingase zonakalise ngokuphelele uhlelo. Le mvume idingeka kuphela ekuthuthukiseni, hayi ekusebenziseni ifoni okuvamile."</string> <!-- no translation found for permlab_broadcastPackageRemoved (2576333434893532475) --> <skip /> <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Ivumela uhlelo lokusebenza ukusakaza isaziso sokuthi iphakheji yohlelo lokusebenza ikhishiwe. Izinhlelo ezinonya zingasebenzisa lokhu ukubulala olunye uhlelo lokusebenza olusebenzayo."</string> @@ -369,7 +369,7 @@ <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ivumela ukwenziwa kwemawindi ehloselwe ukusebenziswa uxhumano lomsebenzisi wohlelo lwangaphakathi. Ayisebenziswa izinhlelo zokusebenza ezivamile"</string> <!-- no translation found for permlab_systemAlertWindow (3372321942941168324) --> <skip /> - <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ivumela uhlelo lokusebenza ukubonisa amawindi okuxwayisa ohlelo. Izinhlelo zokusebenza ezi-malicious zingase zithathe isikrini sonke."</string> + <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ivumela uhlelo lokusebenza ukubonisa amawindi okuxwayisa ohlelo. Izinhlelo zokusebenza ezinonya zingase zithathe isikrini sonke."</string> <!-- no translation found for permlab_setAnimationScale (2805103241153907174) --> <skip /> <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ivumela uhlelo lokusebenza ukushintsha isivinini sokugqwayiza jikelele (ukugqwayiza okusheshayo noma okulengayo) nganoma isiphi isikhathi."</string> @@ -378,7 +378,7 @@ <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Ivumela izinhlelo zokusebenza ukwenza nokuphatha amathokhini awo, ngokudlula ukuhleleka kuka-Z. Akusoze kwadingeka ezinhlelweni ezivamile."</string> <!-- no translation found for permlab_injectEvents (1378746584023586600) --> <skip /> - <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebenza. Izinhlelo ezi-malicious zingasebenzisa lokhu ukuthatha ithebhulethi."</string> + <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebenza. Izinhlelo ezinonya zingasebenzisa lokhu ukuthatha ithebhulethi."</string> <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebeza. Izinhlelo ezinonya zingasebenzisa lokhu ukuthatha ifoni."</string> <!-- no translation found for permlab_readInputState (469428900041249234) --> <skip /> @@ -434,8 +434,8 @@ <string name="permdesc_diagnostic" msgid="3121238373951637049">"Ivumela uhlolo lokusebenza ukufunda nokubhala kunoma yimuphi umthombo weqembu ledayegi; ngokwesibonle, amafayela akwi/dev. Lokhu kungase kuthinte kakhulu ukuba nokuphepha kohlelo. Lokhu kumele kusebenziselwe KUPHELA ukuhlola ihadiwe okucacile ngumkhiqizi noma u-opheretha."</string> <!-- no translation found for permlab_changeComponentState (79425198834329406) --> <skip /> - <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string> - <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string> + <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string> + <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string> <!-- no translation found for permlab_setPreferredApplications (3393305202145172005) --> <skip /> <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Ivumela uhlelo lokusebenza ukuguqula izinhlelo zakho ezikhethwayo. Lokhu kungavumela izinhlelo ezinonya ukushintsha ngokuthulile izinhlelo zokusebenza ezisebenziswayo, ukushintsha izinhlelo zakho zokusebenza ezikhona kakade ukuqoqa idatha yangasese kuwe."</string> @@ -453,15 +453,15 @@ <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ivumela uhlelo lokusebenza ukuba luziqalele ngokushesha nje emva kokuba uhlelo luqede ukuqala. Lokhu kungenza kuthathe isikhathi ukuqalisa ifoni futhi kuvumele uhlelo lokusebenza ukwehlisa ifoni yonke ngokusebenza njalo."</string> <!-- no translation found for permlab_broadcastSticky (7919126372606881614) --> <skip /> - <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezi-malicious zingenza ithebhulethii ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string> + <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ithebhulethii ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string> <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ifoni ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string> <!-- no translation found for permlab_readContacts (6219652189510218240) --> <skip /> - <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string> + <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string> <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo zokusebenza zonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string> <!-- no translation found for permlab_writeContacts (644616215860933284) --> <skip /> - <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string> + <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string> <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string> <!-- no translation found for permlab_readProfile (2211941946684590103) --> <skip /> @@ -472,7 +472,7 @@ <!-- no translation found for permdesc_writeProfile (8040643023682531996) --> <skip /> <string name="permlab_readCalendar" msgid="6898987798303840534">"funda izenzakalo zekhalenda"</string> - <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string> + <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string> <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string> <string name="permlab_writeCalendar" msgid="3894879352594904361">"Yengeza noma guqula izenzakalo zekhalenda bese uthumelela izivakashi i-imeyli"</string> <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ivumela uhlelo lokusebenza ukufaka noma ukushintsha izenzakalo ekhalendeni yakho, okungase kuthumele i-imeyli kubavakashi. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula izenzakalo zekhalenda noma ukuthumela abavakashi i-imeyli."</string> @@ -486,11 +486,11 @@ <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Yenza imithombo yokudlala ukuhlola. Izinhlelo ezinonya zingase zisebenzise lokhu ukukhipha indawo futhi/noma isimo esibuyiswe imithombo yendawo yangempela njenge-GPS noma abahlinzeki Benethiwekhi noma zigade futhi zibike indawo yakho njengomthombo wangaphandle."</string> <!-- no translation found for permlab_accessFineLocation (8116127007541369477) --> <skip /> - <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Finyelela kwimithombo ecocekile Njegesistimu Yokumisa Jikelele kwithebhulethi, lapho itholakala. Izinhlelo ezi-malicious zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string> + <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Finyelela kwimithombo ecocekile Njegesistimu Yokumisa Jikelele kwithebhulethi, lapho itholakala. Izinhlelo ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string> <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Finyelela kumithombo ecocekile Njegesistimu Yokumisa Jikelele efonini, lapho itholakala. Izinhlelo ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string> <!-- no translation found for permlab_accessCoarseLocation (4642255009181975828) --> <skip /> - <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Finyelela indawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola endaweni elungile yethebhulethi, lapho itholakala khona. Izinhlelo zokusebenza ezi-malicious zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string> + <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Finyelela indawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola endaweni elungile yethebhulethi, lapho itholakala khona. Izinhlelo zokusebenza ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string> <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Finyelela kundawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola indawo elungile yefoni, lapho itholakala khona. Izinhlelo zokusebenza ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string> <!-- no translation found for permlab_accessSurfaceFlinger (2363969641792388947) --> <skip /> @@ -580,7 +580,7 @@ <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Sebenzise njengokuhlola komkhiqizi wezinga eliphansi, uvumela ukufinyelela okugcwele ihadiwe yefoni. Itholakala kuphela lapho ifoni isebenza kwimodi yokuhlola yomkhiqizi."</string> <!-- no translation found for permlab_setWallpaper (6627192333373465143) --> <skip /> - <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ivumela uhlelo lokusebenza ukuhlela iphephadonga lohlelo."</string> + <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ivumela uhlelo lokusebenza ukuhlela iphephadonga lesistimu."</string> <!-- no translation found for permlab_setWallpaperHints (3600721069353106851) --> <skip /> <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Ivumela uhlelo lokusebenza ukuhlela izihlawumbisela zosayizi wephephadonga lohlelo."</string> @@ -915,7 +915,7 @@ <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <!-- no translation found for factorytest_failed (5410270329114212041) --> <skip /> - <string name="factorytest_not_system" msgid="4435201656767276723">"Isenzo SOKUHLOLA KWASEMBONINI sisekelwa kuphela amaphakheji afakwi kwisistimu/uhlelo."</string> + <string name="factorytest_not_system" msgid="4435201656767276723">"Isenzo SOKUHLOLA_KWASEMBONINI sisekelwa kuphela amaphakheji afakwe kwisistimu/uhlelokusebenza."</string> <string name="factorytest_no_action" msgid="872991874799998561">"Ayikho iphakheji etholakele enikeze isenzo SOKUHLOLA KWASEMBONINI."</string> <!-- no translation found for factorytest_reboot (6320168203050791643) --> <skip /> @@ -931,10 +931,34 @@ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string> <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string> <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string> + <!-- no translation found for autofill_province (2231806553863422300) --> + <skip /> + <!-- no translation found for autofill_postal_code (4696430407689377108) --> + <skip /> + <!-- no translation found for autofill_state (6988894195520044613) --> + <skip /> + <!-- no translation found for autofill_zip_code (8697544592627322946) --> + <skip /> + <!-- no translation found for autofill_county (237073771020362891) --> + <skip /> + <!-- no translation found for autofill_island (4020100875984667025) --> + <skip /> + <!-- no translation found for autofill_district (8400735073392267672) --> + <skip /> + <!-- no translation found for autofill_department (5343279462564453309) --> + <skip /> + <!-- no translation found for autofill_prefecture (2028499485065800419) --> + <skip /> + <!-- no translation found for autofill_parish (8202206105468820057) --> + <skip /> + <!-- no translation found for autofill_area (3547409050889952423) --> + <skip /> + <!-- no translation found for autofill_emirate (2893880978835698818) --> + <skip /> <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"funda umlando Wesiphequluli namabhukimakhi"</string> <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ivumela uhlelo lokusebenza ukufunda wonke ama-URL lawo Isiphequluli esiwavakashele, ngisho nawo wonke amabhukimakhi Esiphequluli."</string> <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"bhala umlando Wesiphequluli namabhukhimaki"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string> <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string> <string name="permlab_setAlarm" msgid="5924401328803615165">"misa i-alamu ewashini le-alamu"</string> <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ivumela uhlelo lokusebenza ukumisa i-alamu kuhlelo lokusebenza lewashi le-alawmu elifakiwe. Ezinye izinhlelo zokusebenza zewashi le-alamu zingase zingasebenzisi lesi sici."</string> @@ -1437,8 +1461,8 @@ <skip /> <!-- no translation found for activity_chooser_view_see_all (180268188117163072) --> <skip /> - <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) --> + <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) --> <skip /> - <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) --> + <!-- no translation found for share_action_provider_share_with (1791316789651185229) --> <skip /> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 9613712..d0361ca 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2302,6 +2302,8 @@ <!-- Flag whether the accessibility service wants to be able to retrieve the active window content. This setting cannot be changed at runtime. --> <attr name="canRetrieveWindowContent" format="boolean" /> + <!-- Short description of the accessibility serivce purpose or behavior.--> + <attr name="description" /> </declare-styleable> <!-- =============================== --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 1f2b7fb..215700c 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -665,4 +665,7 @@ <!-- Timeout to wait for NTP server response. --> <integer name="config_ntpTimeout">20000</integer> + <!-- Default network policy warning threshold, in megabytes. --> + <integer name="config_networkPolicyDefaultWarning">2048</integer> + </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index abc56ec..2ba4e66 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -138,4 +138,16 @@ <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. --> <dimen name="activity_chooser_popup_min_width">200dip</dimen> + <!-- The default gap between components in a layout. --> + <dimen name="default_gap">16dip</dimen> + + <!-- Text padding for dropdown items --> + <dimen name="dropdownitem_text_padding_left">6dip</dimen> + + <!-- Text padding for dropdown items --> + <dimen name="dropdownitem_text_padding_right">6dip</dimen> + + <!-- Width of the icon in a dropdown list --> + <dimen name="dropdownitem_icon_width">48dip</dimen> + </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 6dedc83..f464623 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1787,6 +1787,11 @@ <public type="attr" name="colorActivatedHighlight" /> <public type="attr" name="colorMultiSelectHighlight" /> + <public type="attr" name="drawableStart" /> + <public type="attr" name="drawableEnd" /> + + <public type="attr" name="actionModeStyle" /> + <public type="style" name="TextAppearance.SuggestionHighlight" /> <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" /> <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" /> @@ -1826,7 +1831,4 @@ <public type="color" name="holo_purple" /> <public type="color" name="holo_blue_bright" /> - <public type="attr" name="drawableStart" /> - <public type="attr" name="drawableEnd" /> - </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 6b75146..d647467 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -563,8 +563,8 @@ <style name="Widget.DropDownItem"> <item name="android:textAppearance">@style/TextAppearance.Widget.DropDownItem</item> - <item name="android:paddingLeft">6dip</item> - <item name="android:paddingRight">6dip</item> + <item name="android:paddingLeft">@dimen/dropdownitem_text_padding_left</item> + <item name="android:paddingRight">@dimen/dropdownitem_text_padding_right</item> <item name="android:gravity">center_vertical</item> </style> @@ -713,6 +713,16 @@ <item name="android:quickContactWindowSize">modeLarge</item> </style> + <style name="Widget.ActivityChooserViewButton"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_gravity">center</item> + <item name="android:background">?android:attr/selectableItemBackground</item> + <item name="android:adjustViewBounds">true</item> + <item name="android:scaleType">fitCenter</item> + <item name="android:padding">@android:dimen/action_bar_icon_vertical_padding</item> + </style> + <!-- Text Appearances --> <eat-comment /> diff --git a/core/tests/coretests/src/android/content/ObserverNodeTest.java b/core/tests/coretests/src/android/content/ObserverNodeTest.java index 736c759..95b8465 100644 --- a/core/tests/coretests/src/android/content/ObserverNodeTest.java +++ b/core/tests/coretests/src/android/content/ObserverNodeTest.java @@ -48,9 +48,9 @@ public class ObserverNodeTest extends AndroidTestCase { int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3}; // special case - root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root); + root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root, 0, 0); for(int i = 1; i < uris.length; i++) { - root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root); + root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root, 0, 0); } ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); @@ -77,7 +77,7 @@ public class ObserverNodeTest extends AndroidTestCase { int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1}; for(int i = 0; i < uris.length; i++) { - root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root); + root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root, 0, 0); } ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index b5c2c27..440aeb5 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -856,4 +856,33 @@ public final class JsonReaderTest extends TestCase { } catch (IOException expected) { } } + + public void testFailWithPosition() throws IOException { + testFailWithPosition("Expected literal value at line 6 column 3", + "[\n\n\n\n\n0,}]"); + } + + public void testFailWithPositionGreaterThanBufferSize() throws IOException { + String spaces = repeat(' ', 8192); + testFailWithPosition("Expected literal value at line 6 column 3", + "[\n\n" + spaces + "\n\n\n0,}]"); + } + + private void testFailWithPosition(String message, String json) throws IOException { + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + reader.nextInt(); + try { + reader.peek(); + fail(); + } catch (IOException expected) { + assertEquals(message, expected.getMessage()); + } + } + + private String repeat(char c, int count) { + char[] array = new char[count]; + Arrays.fill(array, c); + return new String(array); + } } diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java index b29e2fd..1239a3c 100644 --- a/core/tests/coretests/src/android/util/JsonWriterTest.java +++ b/core/tests/coretests/src/android/util/JsonWriterTest.java @@ -289,6 +289,15 @@ public final class JsonWriterTest extends TestCase { + "\"\\u0019\"]", stringWriter.toString()); } + public void testUnicodeLineBreaksEscaped() throws IOException { + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.beginArray(); + jsonWriter.value("\u2028 \u2029"); + jsonWriter.endArray(); + assertEquals("[\"\\u2028 \\u2029\"]", stringWriter.toString()); + } + public void testEmptyArray() throws IOException { StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml new file mode 100644 index 0000000..c0d9153 --- /dev/null +++ b/data/fonts/fallback_fonts.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Fallback Fonts + + This file specifies the fonts, and the priority order, that will be searched for any + glyphs not handled by the default fonts specified in /system/etc/system_fonts.xml. + Each entry consists of a family tag and a list of files (file names) which support that + family. The fonts for each family are listed in the order of the styles that they + handle (the order is: regular, bold, italic, and bold-italic). The order in which the + families are listed in this file represents the order in which these fallback fonts + will be searched for glyphs that are not supported by the default system fonts (which are + found in /system/etc/system_fonts.xml). + + Note that there is not nameset for fallback fonts, unlike the fonts specified in + system_fonts.xml. The ability to support specific names in fallback fonts may be supported + in the future. For now, the lack of files entries here is an indicator to the system that + these are fallback fonts, instead of default named system fonts. + + There is another optional file in /vendor/etc/fallback_fonts.xml. That file can be used to + provide references to other font families that should be used in addition to the default + fallback fonts. That file can also specify the order in which the fallback fonts should be + searched, to ensure that a vendor-provided font will be used before another fallback font + which happens to handle the same glyph. +--> +<familyset> + <family> + <fileset> + <file>DroidSansArabic.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansHebrew-Regular.ttf</file> + <file>DroidSansHebrew-Bold.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansThai.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>DroidSansFallback.ttf</file> + </fileset> + </family> +</familyset> diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk index d222c0b..57a1bab 100644 --- a/data/fonts/fonts.mk +++ b/data/fonts/fonts.mk @@ -30,4 +30,6 @@ PRODUCT_COPY_FILES := \ frameworks/base/data/fonts/DroidSansFallback.ttf:system/fonts/DroidSansFallback.ttf \ frameworks/base/data/fonts/AndroidClock.ttf:system/fonts/AndroidClock.ttf \ frameworks/base/data/fonts/AndroidClock_Highlight.ttf:system/fonts/AndroidClock_Highlight.ttf \ - frameworks/base/data/fonts/AndroidClock_Solid.ttf:system/fonts/AndroidClock_Solid.ttf + frameworks/base/data/fonts/AndroidClock_Solid.ttf:system/fonts/AndroidClock_Solid.ttf \ + frameworks/base/data/fonts/system_fonts.xml:system/etc/system_fonts.xml \ + frameworks/base/data/fonts/fallback_fonts.xml:system/etc/fallback_fonts.xml diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml new file mode 100644 index 0000000..8d8d020 --- /dev/null +++ b/data/fonts/system_fonts.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + System Fonts + + This file lists the font families that will be used by default for all supported glyphs. + Each entry consists of a family, various names that are supported by that family, and + up to four font files. The font files are listed in the order of the styles which they + support: regular, bold, italic and bold-italic. If less than four styles are listed, then + the styles with no associated font file will be supported by the other font files listed. + + The first family is also the default font, which handles font request that have not specified + specific font names. + + Any glyph that is not handled by the system fonts will cause a search of the fallback fonts. + The default fallback fonts are specified in the file /system/etc/fallback_fonts.xml, and there + is an optional file which may be supplied by vendors to specify other fallback fonts to use + in /vendor/etc/fallback_fonts.xml. +--> +<familyset> + + <family> + <nameset> + <name>sans-serif</name> + <name>arial</name> + <name>helvetica</name> + <name>tahoma</name> + <name>verdana</name> + </nameset> + <fileset> + <file>DroidSans.ttf</file> + <file>DroidSans-Bold.ttf</file> + </fileset> + </family> + + <family> + <nameset> + <name>serif</name> + <name>times</name> + <name>times new roman</name> + <name>palatino</name> + <name>georgia</name> + <name>baskerville</name> + <name>goudy</name> + <name>fantasy</name> + <name>cursive</name> + <name>ITC Stone Serif</name> + </nameset> + <fileset> + <file>DroidSerif-Regular.ttf</file> + <file>DroidSerif-Bold.ttf</file> + <file>DroidSerif-Italic.ttf</file> + <file>DroidSerif-BoldItalic.ttf</file> + </fileset> + </family> + + <family> + <nameset> + <name>monospace</name> + <name>courier</name> + <name>courier new</name> + <name>monaco</name> + </nameset> + <fileset> + <file>DroidSansMono.ttf</file> + </fileset> + </family> + +</familyset> diff --git a/data/fonts/vendor_fonts.xml b/data/fonts/vendor_fonts.xml new file mode 100644 index 0000000..fe51fd2 --- /dev/null +++ b/data/fonts/vendor_fonts.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Vendor-provided fallback fonts + + This file can be edited to add references to fonts that are not installed or referenced in the + default system. The file should then be placed in /vendor/etc/fallback_fonts.xml. + + For example, vendors might want to build configurations for locales that are + better served by fonts which either handle glyphs not supported in the default fonts or which + handle these glyphs differently than the default fallback fonts. + Each entry in this list is a "family", which consists of a list of "files" + (the filenames for that family). The files objects are + provided in the order of the styles supported for that family: regular, bold, italic, and + bold-italic. Only providing one font means that all styles will be rendered with that font. + Providing two means that these two fonts will render regular and bold fonts (italics will + be mapped to these two fonts). + + There is also an optional "order" attribute on the Family tag. This specifies the index at + which that family of fonts should be inserted in the fallback font list, where the + default fallback fonts on the system (in /system/etc/fallback_fonts.xml) start at index 0. + If no 'order' attribute is supplied, that family will be inserted either at the end of the + current fallback list (if no order was supplied for any previous family in this file) or + after the previous family (if there was an order specified previously). Typically, vendors + may want to supply an order for the first family that puts this set of fonts at the appropriate + place in the overall fallback fonts. The order of this list determines which fallback font + will be used to support any glyphs that are not handled by the default system fonts. + + The sample configuration below is an example of how one might provide two families of fonts + that get inserted at the first and second (0 and 1) position in the overall fallback fonts. + + See /system/etc/system_fonts.xml and /system/etc/fallback_fonts.xml for more information + and to understand the order in which the default system fonts are loaded and structured for + lookup. +--> + +<!-- Sample fallback font additions to the default fallback list. These fonts will be added + to the top two positions of the fallback list, since the first has an order of 0. --> +<!-- +<familyset> + <family order="0"> + <fileset> + <file>MyFont.ttf</file> + </fileset> + </family> + <family> + <fileset> + <file>MyOtherFont.ttf</file> + </fileset> + </family> +</familyset> +-->
\ No newline at end of file diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 5b50f8f..35ed4d2 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1414,77 +1414,13 @@ public class Canvas { } else { char[] buf = TemporaryBuffer.obtain(end - start); TextUtils.getChars(text, start, end, buf, 0); - native_drawText(mNativeCanvas, buf, 0, end - start, x, y, + native_drawText(mNativeCanvas, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint); TemporaryBuffer.recycle(buf); } } /** - * Draw the text, with origin at (x,y), using the specified paint. The - * origin is interpreted based on the Align setting in the paint. - * - * @param text The text to be drawn - * @param x The x-coordinate of the origin of the text being drawn - * @param y The y-coordinate of the origin of the text being drawn - * @param paint The paint used for the text (e.g. color, size, style) - * - * @hide - * - * Used only for BiDi / RTL Tests - */ - public void drawTextWithGlyphs(char[] text, int index, int count, float x, float y, - Paint paint) { - if ((index | count | (index + count) | - (text.length - index - count)) < 0) { - throw new IndexOutOfBoundsException(); - } - native_drawTextWithGlyphs(mNativeCanvas, text, index, count, x, y, paint.mBidiFlags, - paint.mNativePaint); - } - - /** - * Draw the text, with origin at (x,y), using the specified paint. The - * origin is interpreted based on the Align setting in the paint. - * - * @param text The text to be drawn - * @param x The x-coordinate of the origin of the text being drawn - * @param y The y-coordinate of the origin of the text being drawn - * @param paint The paint used for the text (e.g. color, size, style) - * - * @hide - * - * Used only for BiDi / RTL Tests - */ - public void drawTextWithGlyphs(String text, float x, float y, Paint paint) { - native_drawTextWithGlyphs(mNativeCanvas, text, 0, text.length(), x, y, paint.mBidiFlags, - paint.mNativePaint); - } - - /** - * Draw the glyphs, with origin at (x,y), using the specified paint. The - * origin is interpreted based on the Align setting in the paint. - * - * @param glyphs The glyphs to be drawn - * @param x The x-coordinate of the origin of the text being drawn - * @param y The y-coordinate of the origin of the text being drawn - * @param paint The paint used for the text (e.g. color, size, style) - * - * @hide - * - * Used only for BiDi / RTL Tests - */ - public void drawGlyphs(char[] glyphs, int index, int count, float x, float y, - Paint paint) { - if ((index | count | (index + count) | - (glyphs.length - index - count)) < 0) { - throw new IndexOutOfBoundsException(); - } - native_drawGlyphs(mNativeCanvas, glyphs, index, count, x, y, paint.mBidiFlags, - paint.mNativePaint); - } - - /** * Render a run of all LTR or all RTL text, with shaping. This does not run * bidi on the provided text, but renders it as a uniform right-to-left or * left-to-right run, as indicated by dir. Alignment of the text is as @@ -1813,16 +1749,6 @@ public class Canvas { int start, int end, float x, float y, int flags, int paint); - private static native void native_drawTextWithGlyphs(int nativeCanvas, char[] text, - int index, int count, float x, - float y, int flags, int paint); - private static native void native_drawTextWithGlyphs(int nativeCanvas, String text, - int start, int end, float x, - float y, int flags, int paint); - private static native void native_drawGlyphs(int nativeCanvas, char[] glyphs, - int index, int count, float x, - float y, int flags, int paint); - private static native void native_drawTextRun(int nativeCanvas, String text, int start, int end, int contextStart, int contextEnd, float x, float y, int flags, int paint); diff --git a/graphics/java/com/android/internal/graphics/NativeUtils.java b/graphics/java/com/android/internal/graphics/NativeUtils.java deleted file mode 100644 index c91b7d9..0000000 --- a/graphics/java/com/android/internal/graphics/NativeUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.graphics; - -import android.graphics.Canvas; -import android.graphics.Rect; - -public final class NativeUtils { - /** - * This class is uninstantiable. - */ - private NativeUtils() { - // This space intentionally left blank. - } - - /** - * Scroll a rectangular portion of a canvas. - * - * @param canvas the canvas to manipulate - * @param src the source rectangle - * @param dx horizontal offset - * @param dy vertical offset - */ - public static native boolean nativeScrollRect(Canvas canvas, Rect src, - int dx, int dy); -} diff --git a/include/cpustats/CentralTendencyStatistics.h b/include/cpustats/CentralTendencyStatistics.h new file mode 100644 index 0000000..21b6981 --- /dev/null +++ b/include/cpustats/CentralTendencyStatistics.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CENTRAL_TENDENCY_STATISTICS_H +#define _CENTRAL_TENDENCY_STATISTICS_H + +#include <math.h> + +// Not multithread safe +class CentralTendencyStatistics { + +public: + + CentralTendencyStatistics() : + mMean(NAN), mMedian(NAN), mMinimum(INFINITY), mMaximum(-INFINITY), mN(0), mM2(0), + mVariance(NAN), mVarianceKnownForN(0), mStddev(NAN), mStddevKnownForN(0) { } + + ~CentralTendencyStatistics() { } + + // add x to the set of samples + void sample(double x); + + // return the arithmetic mean of all samples so far + double mean() const { return mMean; } + + // return the minimum of all samples so far + double minimum() const { return mMinimum; } + + // return the maximum of all samples so far + double maximum() const { return mMaximum; } + + // return the variance of all samples so far + double variance() const; + + // return the standard deviation of all samples so far + double stddev() const; + + // return the number of samples added so far + unsigned n() const { return mN; } + + // reset the set of samples to be empty + void reset(); + +private: + double mMean; + double mMedian; + double mMinimum; + double mMaximum; + unsigned mN; // number of samples so far + double mM2; + + // cached variance, and n at time of caching + mutable double mVariance; + mutable unsigned mVarianceKnownForN; + + // cached standard deviation, and n at time of caching + mutable double mStddev; + mutable unsigned mStddevKnownForN; + +}; + +#endif // _CENTRAL_TENDENCY_STATISTICS_H diff --git a/include/cpustats/README.txt b/include/cpustats/README.txt new file mode 100644 index 0000000..14439f0 --- /dev/null +++ b/include/cpustats/README.txt @@ -0,0 +1,6 @@ +This is a static library of CPU usage statistics, originally written +for audio but most are not actually specific to audio. + +Requirements to be here: + * should be related to CPU usage statistics + * should be portable to host; avoid Android OS dependencies without a conditional diff --git a/include/cpustats/ThreadCpuUsage.h b/include/cpustats/ThreadCpuUsage.h new file mode 100644 index 0000000..24012a4 --- /dev/null +++ b/include/cpustats/ThreadCpuUsage.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _THREAD_CPU_USAGE_H +#define _THREAD_CPU_USAGE_H + +#include <cpustats/CentralTendencyStatistics.h> + +// Track CPU usage for the current thread, and maintain statistics on +// the CPU usage. Units are in per-thread CPU ns, as reported by +// clock_gettime(CLOCK_THREAD_CPUTIME_ID). Simple usage: for cyclic +// threads where you want to measure the execution time of the whole +// cycle, just call sampleAndEnable() at the start of each cycle. +// Then call statistics() to get the results, and resetStatistics() +// to start a new set of measurements. +// For acyclic threads, or for cyclic threads where you want to measure +// only part of each cycle, call enable(), disable(), and/or setEnabled() +// to demarcate the region(s) of interest, and then call sample() periodically. +// This class is not thread-safe for concurrent calls from multiple threads; +// the methods of this class may only be called by the current thread +// which constructed the object. + +class ThreadCpuUsage +{ + +public: + ThreadCpuUsage() : + mIsEnabled(false), + mWasEverEnabled(false), + mAccumulator(0), + // mPreviousTs + // mMonotonicTs + mMonotonicKnown(false) + // mStatistics + { } + + ~ThreadCpuUsage() { } + + // Return whether currently tracking CPU usage by current thread + bool isEnabled() { return mIsEnabled; } + + // Enable tracking of CPU usage by current thread; + // any CPU used from this point forward will be tracked. + // Returns the previous enabled status. + bool enable() { return setEnabled(true); } + + // Disable tracking of CPU usage by current thread; + // any CPU used from this point forward will be ignored. + // Returns the previous enabled status. + bool disable() { return setEnabled(false); } + + // Set the enabled status and return the previous enabled status. + // This method is intended to be used for safe nested enable/disabling. + bool setEnabled(bool isEnabled); + + // Add a sample point for central tendency statistics, and also + // enable tracking if needed. If tracking has never been enabled, then + // enables tracking but does not add a sample (it is not possible to add + // a sample the first time because no previous). Otherwise if tracking is + // enabled, then adds a sample for tracked CPU ns since the previous + // sample, or since the first call to sampleAndEnable(), enable(), or + // setEnabled(true). If there was a previous sample but tracking is + // now disabled, then adds a sample for the tracked CPU ns accumulated + // up until the most recent disable(), resets this accumulator, and then + // enables tracking. Calling this method rather than enable() followed + // by sample() avoids a race condition for the first sample. + void sampleAndEnable(); + + // Add a sample point for central tendency statistics, but do not + // change the tracking enabled status. If tracking has either never been + // enabled, or has never been enabled since the last sample, then log a warning + // and don't add sample. Otherwise, adds a sample for tracked CPU ns since + // the previous sample or since the first call to sampleAndEnable(), + // enable(), or setEnabled(true) if no previous sample. + void sample(); + + // Return the elapsed delta wall clock ns since initial enable or statistics reset, + // as reported by clock_gettime(CLOCK_MONOTONIC). + long long elapsed() const; + + // Reset statistics and elapsed. Has no effect on tracking or accumulator. + void resetStatistics(); + + // Return a const reference to the central tendency statistics. + // Note that only the const methods can be called on this object. + const CentralTendencyStatistics& statistics() const { + return mStatistics; + } + +private: + bool mIsEnabled; // whether tracking is currently enabled + bool mWasEverEnabled; // whether tracking was ever enabled + long long mAccumulator; // accumulated thread CPU time since last sample, in ns + struct timespec mPreviousTs; // most recent thread CPU time, valid only if mIsEnabled is true + struct timespec mMonotonicTs; // most recent monotonic time + bool mMonotonicKnown; // whether mMonotonicTs has been set + CentralTendencyStatistics mStatistics; +}; + +#endif // _THREAD_CPU_USAGE_H diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index 5ec469e..cfe2aa1 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -21,6 +21,7 @@ #include <gui/SurfaceTexture.h> #include <ui/egl/android_natives.h> +#include <ui/Region.h> #include <utils/RefBase.h> #include <utils/threads.h> @@ -37,29 +38,24 @@ public: sp<ISurfaceTexture> getISurfaceTexture() const; -private: - friend class Surface; +protected: + SurfaceTextureClient(); + void setISurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture); +private: // can't be copied SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs); SurfaceTextureClient(const SurfaceTextureClient& rhs); + void init(); // ANativeWindow hooks - static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); - static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); - static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); - static int perform(ANativeWindow* window, int operation, ...); - static int query(const ANativeWindow* window, int what, int* value); - static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); - static int setSwapInterval(ANativeWindow* window, int interval); - - int cancelBuffer(ANativeWindowBuffer* buffer); - int dequeueBuffer(ANativeWindowBuffer** buffer); - int lockBuffer(ANativeWindowBuffer* buffer); - int perform(int operation, va_list args); - int query(int what, int* value) const; - int queueBuffer(ANativeWindowBuffer* buffer); - int setSwapInterval(int interval); + static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); + static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); + static int hook_lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); + static int hook_perform(ANativeWindow* window, int operation, ...); + static int hook_query(const ANativeWindow* window, int what, int* value); + static int hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); + static int hook_setSwapInterval(ANativeWindow* window, int interval); int dispatchConnect(va_list args); int dispatchDisconnect(va_list args); @@ -71,26 +67,38 @@ private: int dispatchSetBuffersTimestamp(va_list args); int dispatchSetCrop(va_list args); int dispatchSetUsage(va_list args); - - int connect(int api); - int disconnect(int api); - int setBufferCount(int bufferCount); - int setBuffersDimensions(int w, int h); - int setBuffersFormat(int format); - int setBuffersTransform(int transform); - int setBuffersTimestamp(int64_t timestamp); - int setCrop(Rect const* rect); - int setUsage(uint32_t reqUsage); - - void freeAllBuffers(); - int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; - - int getConnectedApi() const; + int dispatchLock(va_list args); + int dispatchUnlockAndPost(va_list args); + +protected: + virtual int cancelBuffer(ANativeWindowBuffer* buffer); + virtual int dequeueBuffer(ANativeWindowBuffer** buffer); + virtual int lockBuffer(ANativeWindowBuffer* buffer); + virtual int perform(int operation, va_list args); + virtual int query(int what, int* value) const; + virtual int queueBuffer(ANativeWindowBuffer* buffer); + virtual int setSwapInterval(int interval); + + virtual int connect(int api); + virtual int disconnect(int api); + virtual int setBufferCount(int bufferCount); + virtual int setBuffersDimensions(int w, int h); + virtual int setBuffersFormat(int format); + virtual int setBuffersTransform(int transform); + virtual int setBuffersTimestamp(int64_t timestamp); + virtual int setCrop(Rect const* rect); + virtual int setUsage(uint32_t reqUsage); + virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); + virtual int unlockAndPost(); enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS }; enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; +private: + void freeAllBuffers(); + int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; + // mSurfaceTexture is the interface to the surface texture server. All // operations on the surface texture client ultimately translate into // interactions with the server using this interface. @@ -145,6 +153,12 @@ private: // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; + + // must be used from the lock/unlock thread + sp<GraphicBuffer> mLockedBuffer; + sp<GraphicBuffer> mPostedBuffer; + mutable Region mOldDirtyRegion; + bool mConnectedToCpu; }; }; // namespace android diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index ea5a9d3..1136f6c 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -25,6 +25,8 @@ #include <utils/KeyedVector.h> #include <utils/String8.h> +class ANativeWindow; + namespace android { class Surface; @@ -196,6 +198,8 @@ private: status_t prepareAsync_l(); status_t getDuration_l(int *msec); status_t setDataSource(const sp<IMediaPlayer>& player); + void disconnectNativeWindow(); + status_t reset_l(); sp<IMediaPlayer> mPlayer; thread_id_t mLockThreadId; @@ -218,6 +222,8 @@ private: int mVideoHeight; int mAudioSessionId; float mSendLevel; + sp<ANativeWindow> mConnectedWindow; + sp<IBinder> mConnectedWindowBinder; }; }; // namespace android diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index a042ddb..20fcde5 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -355,7 +355,7 @@ struct CodecCapabilities { status_t QueryCodecs( const sp<IOMX> &omx, - const char *mimeType, bool queryDecoders, + const char *mimeType, bool queryDecoders, bool hwCodecOnly, Vector<CodecCapabilities> *results); } // namespace android diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index dc2a845..c2a494d 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -28,6 +28,8 @@ #include <ui/Region.h> #include <ui/egl/android_natives.h> +#include <gui/SurfaceTextureClient.h> + #include <surfaceflinger/ISurface.h> #include <surfaceflinger/ISurfaceComposerClient.h> @@ -37,14 +39,9 @@ namespace android { // --------------------------------------------------------------------------- -class GraphicBuffer; -class GraphicBufferMapper; -class IOMX; class ISurfaceTexture; -class Rect; class Surface; class SurfaceComposerClient; -class SurfaceTextureClient; // --------------------------------------------------------------------------- @@ -129,8 +126,7 @@ private: // --------------------------------------------------------------------------- -class Surface - : public EGLNativeBase<ANativeWindow, Surface, RefBase> +class Surface : public SurfaceTextureClient { public: struct SurfaceInfo { @@ -158,32 +154,14 @@ public: sp<ISurfaceTexture> getSurfaceTexture(); // the lock/unlock APIs must be used from the same thread - status_t lock(SurfaceInfo* info, bool blocking = true); - status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); + status_t lock(SurfaceInfo* info, Region* dirty = NULL); status_t unlockAndPost(); sp<IBinder> asBinder() const; private: - /* - * Android frameworks friends - * (eventually this should go away and be replaced by proper APIs) - */ - // camera and camcorder need access to the ISurface binder interface for preview - friend class CameraService; - friend class MediaRecorder; - // MediaPlayer needs access to ISurface for display - friend class MediaPlayer; - friend class IOMX; - friend class SoftwareRenderer; // this is just to be able to write some unit tests friend class Test; - // videoEditor preview classes - friend class VideoEditorPreviewController; - friend class PreviewRenderer; - -private: - friend class SurfaceComposerClient; friend class SurfaceControl; // can't be copied @@ -194,62 +172,27 @@ private: Surface(const Parcel& data, const sp<IBinder>& ref); ~Surface(); - - /* - * ANativeWindow hooks - */ - static int setSwapInterval(ANativeWindow* window, int interval); - static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); - static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); - static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); - static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); - static int query(const ANativeWindow* window, int what, int* value); - static int perform(ANativeWindow* window, int operation, ...); - - int setSwapInterval(int interval); - int dequeueBuffer(ANativeWindowBuffer** buffer); - int lockBuffer(ANativeWindowBuffer* buffer); - int queueBuffer(ANativeWindowBuffer* buffer); - int cancelBuffer(ANativeWindowBuffer* buffer); - int query(int what, int* value) const; - int perform(int operation, va_list args); - /* * private stuff... */ void init(); status_t validate(bool inCancelBuffer = false) const; - int getConnectedApi() const; - static void cleanCachedSurfacesLocked(); + virtual int query(int what, int* value) const; + // constants status_t mInitCheck; sp<ISurface> mSurface; - sp<SurfaceTextureClient> mSurfaceTextureClient; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; - - // protected by mSurfaceLock. These are also used from lock/unlock - // but in that case, they must be called form the same thread. - mutable Region mDirtyRegion; - - // must be used from the lock/unlock thread - sp<GraphicBuffer> mLockedBuffer; - sp<GraphicBuffer> mPostedBuffer; - mutable Region mOldDirtyRegion; - bool mReserved; // query() must be called from dequeueBuffer() thread uint32_t mWidth; uint32_t mHeight; - // Inherently thread-safe - mutable Mutex mSurfaceLock; - mutable Mutex mApiLock; - // A cache of Surface objects that have been deserialized into this process. static Mutex sCachedSurfacesLock; static DefaultKeyedVector<wp<IBinder>, wp<Surface> > sCachedSurfaces; diff --git a/libs/cpustats/Android.mk b/libs/cpustats/Android.mk new file mode 100644 index 0000000..21bacbb --- /dev/null +++ b/libs/cpustats/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + CentralTendencyStatistics.cpp \ + ThreadCpuUsage.cpp + +LOCAL_MODULE := libcpustats + +include $(BUILD_STATIC_LIBRARY) + +#include $(CLEAR_VARS) +# +#LOCAL_SRC_FILES := \ +# CentralTendencyStatistics.cpp \ +# ThreadCpuUsage.cpp +# +#LOCAL_MODULE := libcpustats +# +#include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/libs/cpustats/CentralTendencyStatistics.cpp b/libs/cpustats/CentralTendencyStatistics.cpp new file mode 100644 index 0000000..42ab62b --- /dev/null +++ b/libs/cpustats/CentralTendencyStatistics.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include <cpustats/CentralTendencyStatistics.h> + +void CentralTendencyStatistics::sample(double x) +{ + // update min and max + if (x < mMinimum) + mMinimum = x; + if (x > mMaximum) + mMaximum = x; + // Knuth + if (mN == 0) { + mMean = 0; + } + ++mN; + double delta = x - mMean; + mMean += delta / mN; + mM2 += delta * (x - mMean); +} + +void CentralTendencyStatistics::reset() +{ + mMean = NAN; + mMedian = NAN; + mMinimum = INFINITY; + mMaximum = -INFINITY; + mN = 0; + mM2 = 0; + mVariance = NAN; + mVarianceKnownForN = 0; + mStddev = NAN; + mStddevKnownForN = 0; +} + +double CentralTendencyStatistics::variance() const +{ + double variance; + if (mVarianceKnownForN != mN) { + if (mN > 1) { + // double variance_n = M2/n; + variance = mM2 / (mN - 1); + } else { + variance = NAN; + } + mVariance = variance; + mVarianceKnownForN = mN; + } else { + variance = mVariance; + } + return variance; +} + +double CentralTendencyStatistics::stddev() const +{ + double stddev; + if (mStddevKnownForN != mN) { + stddev = sqrt(variance()); + mStddev = stddev; + mStddevKnownForN = mN; + } else { + stddev = mStddev; + } + return stddev; +} diff --git a/libs/cpustats/ThreadCpuUsage.cpp b/libs/cpustats/ThreadCpuUsage.cpp new file mode 100644 index 0000000..4bfbdf3 --- /dev/null +++ b/libs/cpustats/ThreadCpuUsage.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <time.h> + +#include <utils/Log.h> + +#include <cpustats/ThreadCpuUsage.h> + +bool ThreadCpuUsage::setEnabled(bool isEnabled) +{ + bool wasEnabled = mIsEnabled; + // only do something if there is a change + if (isEnabled != wasEnabled) { + int rc; + // enabling + if (isEnabled) { + rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mPreviousTs); + if (rc) { + LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); + isEnabled = false; + } else { + mWasEverEnabled = true; + // record wall clock time at first enable + if (!mMonotonicKnown) { + rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); + if (rc) { + LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); + } else { + mMonotonicKnown = true; + } + } + } + // disabling + } else { + struct timespec ts; + rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + if (rc) { + LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); + } else { + long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + + (ts.tv_nsec - mPreviousTs.tv_nsec); + mAccumulator += delta; +#if 0 + mPreviousTs = ts; +#endif + } + } + mIsEnabled = isEnabled; + } + return wasEnabled; +} + +void ThreadCpuUsage::sampleAndEnable() +{ + bool wasEverEnabled = mWasEverEnabled; + if (enable()) { + // already enabled, so add a new sample relative to previous + sample(); + } else if (wasEverEnabled) { + // was disabled, but add sample for accumulated time while enabled + mStatistics.sample((double) mAccumulator); + mAccumulator = 0; + } +} + +void ThreadCpuUsage::sample() +{ + if (mWasEverEnabled) { + if (mIsEnabled) { + struct timespec ts; + int rc; + rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + if (rc) { + LOGE("clock_gettime(CLOCK_THREAD_CPUTIME_ID) errno=%d", errno); + } else { + long long delta = (ts.tv_sec - mPreviousTs.tv_sec) * 1000000000LL + + (ts.tv_nsec - mPreviousTs.tv_nsec); + mAccumulator += delta; + mPreviousTs = ts; + } + } else { + mWasEverEnabled = false; + } + mStatistics.sample((double) mAccumulator); + mAccumulator = 0; + } else { + LOGW("Can't add sample because measurements have never been enabled"); + } +} + +long long ThreadCpuUsage::elapsed() const +{ + long long elapsed; + if (mMonotonicKnown) { + struct timespec ts; + int rc; + rc = clock_gettime(CLOCK_MONOTONIC, &ts); + if (rc) { + LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); + elapsed = 0; + } else { + // mMonotonicTs is updated only at first enable and resetStatistics + elapsed = (ts.tv_sec - mMonotonicTs.tv_sec) * 1000000000LL + + (ts.tv_nsec - mMonotonicTs.tv_nsec); + } + } else { + LOGW("Can't compute elapsed time because measurements have never been enabled"); + elapsed = 0; + } + return elapsed; +} + +void ThreadCpuUsage::resetStatistics() +{ + mStatistics.reset(); + if (mMonotonicKnown) { + int rc; + rc = clock_gettime(CLOCK_MONOTONIC, &mMonotonicTs); + if (rc) { + LOGE("clock_gettime(CLOCK_MONOTONIC) errno=%d", errno); + mMonotonicKnown = false; + } + } +} diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 9185e1e..dabe643f 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -46,59 +46,6 @@ namespace android { -// ---------------------------------------------------------------------- - -static status_t copyBlt( - const sp<GraphicBuffer>& dst, - const sp<GraphicBuffer>& src, - const Region& reg) -{ - // src and dst with, height and format must be identical. no verification - // is done here. - status_t err; - uint8_t const * src_bits = NULL; - err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); - LOGE_IF(err, "error locking src buffer %s", strerror(-err)); - - uint8_t* dst_bits = NULL; - err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); - LOGE_IF(err, "error locking dst buffer %s", strerror(-err)); - - Region::const_iterator head(reg.begin()); - Region::const_iterator tail(reg.end()); - if (head != tail && src_bits && dst_bits) { - const size_t bpp = bytesPerPixel(src->format); - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; - - while (head != tail) { - const Rect& r(*head++); - ssize_t h = r.height(); - if (h <= 0) continue; - size_t size = r.width() * bpp; - uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); - } - } - - if (src_bits) - src->unlock(); - - if (dst_bits) - dst->unlock(); - - return err; -} - // ============================================================================ // SurfaceControl // ============================================================================ @@ -277,7 +224,8 @@ sp<Surface> SurfaceControl::getSurface() const // --------------------------------------------------------------------------- Surface::Surface(const sp<SurfaceControl>& surface) - : mInitCheck(NO_INIT), + : SurfaceTextureClient(), + mInitCheck(NO_INIT), mSurface(surface->mSurface), mIdentity(surface->mIdentity), mFormat(surface->mFormat), mFlags(surface->mFlags), @@ -287,7 +235,8 @@ Surface::Surface(const sp<SurfaceControl>& surface) } Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) - : mInitCheck(NO_INIT) + : SurfaceTextureClient(), + mInitCheck(NO_INIT) { mSurface = interface_cast<ISurface>(ref); mIdentity = parcel.readInt32(); @@ -363,36 +312,21 @@ void Surface::cleanCachedSurfacesLocked() { void Surface::init() { - ANativeWindow::setSwapInterval = setSwapInterval; - ANativeWindow::dequeueBuffer = dequeueBuffer; - ANativeWindow::cancelBuffer = cancelBuffer; - ANativeWindow::lockBuffer = lockBuffer; - ANativeWindow::queueBuffer = queueBuffer; - ANativeWindow::query = query; - ANativeWindow::perform = perform; - if (mSurface != NULL) { sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture()); LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); if (surfaceTexture != NULL) { - mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture); - mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER); + setISurfaceTexture(surfaceTexture); + setUsage(GraphicBuffer::USAGE_HW_RENDER); } DisplayInfo dinfo; SurfaceComposerClient::getDisplayInfo(0, &dinfo); const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi; const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi; - - const_cast<int&>(ANativeWindow::minSwapInterval) = - mSurfaceTextureClient->minSwapInterval; - - const_cast<int&>(ANativeWindow::maxSwapInterval) = - mSurfaceTextureClient->maxSwapInterval; - const_cast<uint32_t&>(ANativeWindow::flags) = 0; - if (mSurfaceTextureClient != 0) { + if (surfaceTexture != NULL) { mInitCheck = NO_ERROR; } } @@ -402,7 +336,6 @@ Surface::~Surface() { // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. - mSurfaceTextureClient.clear(); mSurface.clear(); IPCThreadState::self()->flushCommands(); } @@ -431,77 +364,6 @@ sp<IBinder> Surface::asBinder() const { // ---------------------------------------------------------------------------- -int Surface::setSwapInterval(ANativeWindow* window, int interval) { - Surface* self = getSelf(window); - return self->setSwapInterval(interval); -} - -int Surface::dequeueBuffer(ANativeWindow* window, - ANativeWindowBuffer** buffer) { - Surface* self = getSelf(window); - return self->dequeueBuffer(buffer); -} - -int Surface::cancelBuffer(ANativeWindow* window, - ANativeWindowBuffer* buffer) { - Surface* self = getSelf(window); - return self->cancelBuffer(buffer); -} - -int Surface::lockBuffer(ANativeWindow* window, - ANativeWindowBuffer* buffer) { - Surface* self = getSelf(window); - return self->lockBuffer(buffer); -} - -int Surface::queueBuffer(ANativeWindow* window, - ANativeWindowBuffer* buffer) { - Surface* self = getSelf(window); - return self->queueBuffer(buffer); -} - -int Surface::query(const ANativeWindow* window, - int what, int* value) { - const Surface* self = getSelf(window); - return self->query(what, value); -} - -int Surface::perform(ANativeWindow* window, - int operation, ...) { - va_list args; - va_start(args, operation); - Surface* self = getSelf(window); - int res = self->perform(operation, args); - va_end(args); - return res; -} - -// ---------------------------------------------------------------------------- - -int Surface::setSwapInterval(int interval) { - return mSurfaceTextureClient->setSwapInterval(interval); -} - -int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) { - status_t err = mSurfaceTextureClient->dequeueBuffer(buffer); - if (err == NO_ERROR) { - mDirtyRegion.set(buffer[0]->width, buffer[0]->height); - } - return err; -} - -int Surface::cancelBuffer(ANativeWindowBuffer* buffer) { - return mSurfaceTextureClient->cancelBuffer(buffer); -} - -int Surface::lockBuffer(ANativeWindowBuffer* buffer) { - return mSurfaceTextureClient->lockBuffer(buffer); -} - -int Surface::queueBuffer(ANativeWindowBuffer* buffer) { - return mSurfaceTextureClient->queueBuffer(buffer); -} - int Surface::query(int what, int* value) const { switch (what) { case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: @@ -509,141 +371,39 @@ int Surface::query(int what, int* value) const { *value = 1; return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: - // TODO: this is not needed anymore *value = NATIVE_WINDOW_SURFACE; return NO_ERROR; } - return mSurfaceTextureClient->query(what, value); -} - -int Surface::perform(int operation, va_list args) { - return mSurfaceTextureClient->perform(operation, args); + return SurfaceTextureClient::query(what, value); } // ---------------------------------------------------------------------------- -int Surface::getConnectedApi() const { - return mSurfaceTextureClient->getConnectedApi(); -} +status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn) { + ANativeWindow_Buffer outBuffer; -// ---------------------------------------------------------------------------- - -status_t Surface::lock(SurfaceInfo* info, bool blocking) { - return Surface::lock(info, NULL, blocking); -} - -status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) -{ - if (getConnectedApi()) { - LOGE("Surface::lock(%p) failed. Already connected to another API", - (ANativeWindow*)this); - CallStack stack; - stack.update(); - stack.dump(""); - return INVALID_OPERATION; - } - - if (mApiLock.tryLock() != NO_ERROR) { - LOGE("calling Surface::lock from different threads!"); - CallStack stack; - stack.update(); - stack.dump(""); - return WOULD_BLOCK; + ARect temp; + ARect* inOutDirtyBounds = NULL; + if (dirtyIn) { + temp = dirtyIn->getBounds(); + inOutDirtyBounds = &temp; } - /* Here we're holding mApiLock */ - - if (mLockedBuffer != 0) { - LOGE("Surface::lock failed, already locked"); - mApiLock.unlock(); - return INVALID_OPERATION; - } - - // we're intending to do software rendering from this point - mSurfaceTextureClient->setUsage( - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds); - ANativeWindowBuffer* out; - status_t err = mSurfaceTextureClient->dequeueBuffer(&out); - LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { - sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); - err = mSurfaceTextureClient->lockBuffer(backBuffer.get()); - LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", - backBuffer->handle, strerror(-err)); - if (err == NO_ERROR) { - const Rect bounds(backBuffer->width, backBuffer->height); - const Region boundsRegion(bounds); - Region scratch(boundsRegion); - Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); - newDirtyRegion &= boundsRegion; - - // figure out if we can copy the frontbuffer back - const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); - const bool canCopyBack = (frontBuffer != 0 && - backBuffer->width == frontBuffer->width && - backBuffer->height == frontBuffer->height && - backBuffer->format == frontBuffer->format && - !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); - - // the dirty region we report to surfaceflinger is the one - // given by the user (as opposed to the one *we* return to the - // user). - mDirtyRegion = newDirtyRegion; - - if (canCopyBack) { - // copy the area that is invalid and not repainted this round - const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); - if (!copyback.isEmpty()) - copyBlt(backBuffer, frontBuffer, copyback); - } else { - // if we can't copy-back anything, modify the user's dirty - // region to make sure they redraw the whole buffer - newDirtyRegion = boundsRegion; - } - - // keep track of the are of the buffer that is "clean" - // (ie: that will be redrawn) - mOldDirtyRegion = newDirtyRegion; - - void* vaddr; - status_t res = backBuffer->lock( - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - newDirtyRegion.bounds(), &vaddr); - - LOGW_IF(res, "failed locking buffer (handle = %p)", - backBuffer->handle); - - mLockedBuffer = backBuffer; - other->w = backBuffer->width; - other->h = backBuffer->height; - other->s = backBuffer->stride; - other->usage = backBuffer->usage; - other->format = backBuffer->format; - other->bits = vaddr; - } + other->w = uint32_t(outBuffer.width); + other->h = uint32_t(outBuffer.height); + other->s = uint32_t(outBuffer.stride); + other->usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; + other->format = uint32_t(outBuffer.format); + other->bits = outBuffer.bits; } - mApiLock.unlock(); return err; } - -status_t Surface::unlockAndPost() -{ - if (mLockedBuffer == 0) { - LOGE("Surface::unlockAndPost failed, no locked buffer"); - return INVALID_OPERATION; - } - - status_t err = mLockedBuffer->unlock(); - LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); - - err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get()); - LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", - mLockedBuffer->handle, strerror(-err)); - mPostedBuffer = mLockedBuffer; - mLockedBuffer = 0; - return err; +status_t Surface::unlockAndPost() { + return SurfaceTextureClient::unlockAndPost(); } // ---------------------------------------------------------------------------- diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 1410481..a12d40a 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -495,7 +495,7 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { } status_t SurfaceTexture::connect(int api) { - LOGV("SurfaceTexture::connect"); + LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); int err = NO_ERROR; switch (api) { @@ -504,6 +504,8 @@ status_t SurfaceTexture::connect(int api) { case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi != NO_CONNECTED_API) { + LOGE("connect: already connected (cur=%d, req=%d)", + mConnectedApi, api); err = -EINVAL; } else { mConnectedApi = api; @@ -517,7 +519,7 @@ status_t SurfaceTexture::connect(int api) { } status_t SurfaceTexture::disconnect(int api) { - LOGV("SurfaceTexture::disconnect"); + LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); int err = NO_ERROR; switch (api) { @@ -528,6 +530,8 @@ status_t SurfaceTexture::disconnect(int api) { if (mConnectedApi == api) { mConnectedApi = NO_CONNECTED_API; } else { + LOGE("disconnect: connected to another api (cur=%d, req=%d)", + mConnectedApi, api); err = -EINVAL; } break; diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index f39cabf..d5b7c89 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -24,24 +24,45 @@ namespace android { SurfaceTextureClient::SurfaceTextureClient( - const sp<ISurfaceTexture>& surfaceTexture): - mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0), - mReqHeight(0), mReqFormat(0), mReqUsage(0), - mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), - mQueryWidth(0), mQueryHeight(0), mQueryFormat(0), - mMutex() { + const sp<ISurfaceTexture>& surfaceTexture) +{ + SurfaceTextureClient::init(); + SurfaceTextureClient::setISurfaceTexture(surfaceTexture); +} + +SurfaceTextureClient::SurfaceTextureClient() { + SurfaceTextureClient::init(); +} + +void SurfaceTextureClient::init() { // Initialize the ANativeWindow function pointers. - ANativeWindow::setSwapInterval = setSwapInterval; - ANativeWindow::dequeueBuffer = dequeueBuffer; - ANativeWindow::cancelBuffer = cancelBuffer; - ANativeWindow::lockBuffer = lockBuffer; - ANativeWindow::queueBuffer = queueBuffer; - ANativeWindow::query = query; - ANativeWindow::perform = perform; + ANativeWindow::setSwapInterval = hook_setSwapInterval; + ANativeWindow::dequeueBuffer = hook_dequeueBuffer; + ANativeWindow::cancelBuffer = hook_cancelBuffer; + ANativeWindow::lockBuffer = hook_lockBuffer; + ANativeWindow::queueBuffer = hook_queueBuffer; + ANativeWindow::query = hook_query; + ANativeWindow::perform = hook_perform; const_cast<int&>(ANativeWindow::minSwapInterval) = 0; const_cast<int&>(ANativeWindow::maxSwapInterval) = 1; + mReqWidth = 0; + mReqHeight = 0; + mReqFormat = 0; + mReqUsage = 0; + mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; + mQueryWidth = 0; + mQueryHeight = 0; + mQueryFormat = 0; + mConnectedToCpu = false; +} + +void SurfaceTextureClient::setISurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) +{ + mSurfaceTexture = surfaceTexture; + // Get a reference to the allocator. mAllocator = mSurfaceTexture->getAllocator(); } @@ -50,42 +71,42 @@ sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const { return mSurfaceTexture; } -int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) { +int SurfaceTextureClient::hook_setSwapInterval(ANativeWindow* window, int interval) { SurfaceTextureClient* c = getSelf(window); return c->setSwapInterval(interval); } -int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window, +int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer) { SurfaceTextureClient* c = getSelf(window); return c->dequeueBuffer(buffer); } -int SurfaceTextureClient::cancelBuffer(ANativeWindow* window, +int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { SurfaceTextureClient* c = getSelf(window); return c->cancelBuffer(buffer); } -int SurfaceTextureClient::lockBuffer(ANativeWindow* window, +int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { SurfaceTextureClient* c = getSelf(window); return c->lockBuffer(buffer); } -int SurfaceTextureClient::queueBuffer(ANativeWindow* window, +int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer) { SurfaceTextureClient* c = getSelf(window); return c->queueBuffer(buffer); } -int SurfaceTextureClient::query(const ANativeWindow* window, +int SurfaceTextureClient::hook_query(const ANativeWindow* window, int what, int* value) { const SurfaceTextureClient* c = getSelf(window); return c->query(what, value); } -int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) { +int SurfaceTextureClient::hook_perform(ANativeWindow* window, int operation, ...) { va_list args; va_start(args, operation); SurfaceTextureClient* c = getSelf(window); @@ -219,7 +240,6 @@ int SurfaceTextureClient::query(int what, int* value) const { *value = 0; return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: - // TODO: this is not needed anymore *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; return NO_ERROR; } @@ -260,6 +280,12 @@ int SurfaceTextureClient::perform(int operation, va_list args) case NATIVE_WINDOW_SET_BUFFERS_FORMAT: res = dispatchSetBuffersFormat(args); break; + case NATIVE_WINDOW_LOCK: + res = dispatchLock(args); + break; + case NATIVE_WINDOW_UNLOCK_AND_POST: + res = dispatchUnlockAndPost(args); + break; default: res = NAME_NOT_FOUND; break; @@ -324,28 +350,37 @@ int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { return setBuffersTimestamp(timestamp); } +int SurfaceTextureClient::dispatchLock(va_list args) { + ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*); + ARect* inOutDirtyBounds = va_arg(args, ARect*); + return lock(outBuffer, inOutDirtyBounds); +} + +int SurfaceTextureClient::dispatchUnlockAndPost(va_list args) { + return unlockAndPost(); +} + + int SurfaceTextureClient::connect(int api) { LOGV("SurfaceTextureClient::connect"); Mutex::Autolock lock(mMutex); - return mSurfaceTexture->connect(api); + int err = mSurfaceTexture->connect(api); + if (!err && api == NATIVE_WINDOW_API_CPU) { + mConnectedToCpu = true; + } + return err; } int SurfaceTextureClient::disconnect(int api) { LOGV("SurfaceTextureClient::disconnect"); Mutex::Autolock lock(mMutex); - return mSurfaceTexture->disconnect(api); -} - -int SurfaceTextureClient::getConnectedApi() const -{ - // XXX: This method will be going away shortly, and is currently bogus. It - // always returns "nothing is connected". It will go away once Surface gets - // updated to actually connect as the 'CPU' API when locking a buffer. - Mutex::Autolock lock(mMutex); - return 0; + int err = mSurfaceTexture->disconnect(api); + if (!err && api == NATIVE_WINDOW_API_CPU) { + mConnectedToCpu = false; + } + return err; } - int SurfaceTextureClient::setUsage(uint32_t reqUsage) { LOGV("SurfaceTextureClient::setUsage"); @@ -443,4 +478,160 @@ void SurfaceTextureClient::freeAllBuffers() { } } +// ---------------------------------------------------------------------- +// the lock/unlock APIs must be used from the same thread + +static status_t copyBlt( + const sp<GraphicBuffer>& dst, + const sp<GraphicBuffer>& src, + const Region& reg) +{ + // src and dst with, height and format must be identical. no verification + // is done here. + status_t err; + uint8_t const * src_bits = NULL; + err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); + LOGE_IF(err, "error locking src buffer %s", strerror(-err)); + + uint8_t* dst_bits = NULL; + err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); + LOGE_IF(err, "error locking dst buffer %s", strerror(-err)); + + Region::const_iterator head(reg.begin()); + Region::const_iterator tail(reg.end()); + if (head != tail && src_bits && dst_bits) { + const size_t bpp = bytesPerPixel(src->format); + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + + while (head != tail) { + const Rect& r(*head++); + ssize_t h = r.height(); + if (h <= 0) continue; + size_t size = r.width() * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; + } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); + } + } + + if (src_bits) + src->unlock(); + + if (dst_bits) + dst->unlock(); + + return err; +} + +// ---------------------------------------------------------------------------- + +status_t SurfaceTextureClient::lock( + ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) +{ + if (mLockedBuffer != 0) { + LOGE("Surface::lock failed, already locked"); + return INVALID_OPERATION; + } + + if (!mConnectedToCpu) { + int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU); + if (err) { + return err; + } + // we're intending to do software rendering from this point + setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + } + + ANativeWindowBuffer* out; + status_t err = dequeueBuffer(&out); + LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); + if (err == NO_ERROR) { + sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out)); + err = lockBuffer(backBuffer.get()); + LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)", + backBuffer->handle, strerror(-err)); + if (err == NO_ERROR) { + const Rect bounds(backBuffer->width, backBuffer->height); + + Region newDirtyRegion; + if (inOutDirtyBounds) { + newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds)); + newDirtyRegion.andSelf(bounds); + } else { + newDirtyRegion.set(bounds); + } + + // figure out if we can copy the frontbuffer back + const sp<GraphicBuffer>& frontBuffer(mPostedBuffer); + const bool canCopyBack = (frontBuffer != 0 && + backBuffer->width == frontBuffer->width && + backBuffer->height == frontBuffer->height && + backBuffer->format == frontBuffer->format); + + if (canCopyBack) { + // copy the area that is invalid and not repainted this round + const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); + if (!copyback.isEmpty()) + copyBlt(backBuffer, frontBuffer, copyback); + } else { + // if we can't copy-back anything, modify the user's dirty + // region to make sure they redraw the whole buffer + newDirtyRegion.set(bounds); + } + + // keep track of the are of the buffer that is "clean" + // (ie: that will be redrawn) + mOldDirtyRegion = newDirtyRegion; + + if (inOutDirtyBounds) { + *inOutDirtyBounds = newDirtyRegion.getBounds(); + } + + void* vaddr; + status_t res = backBuffer->lock( + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + newDirtyRegion.bounds(), &vaddr); + + LOGW_IF(res, "failed locking buffer (handle = %p)", + backBuffer->handle); + + mLockedBuffer = backBuffer; + outBuffer->width = backBuffer->width; + outBuffer->height = backBuffer->height; + outBuffer->stride = backBuffer->stride; + outBuffer->format = backBuffer->format; + outBuffer->bits = vaddr; + } + } + return err; +} + +status_t SurfaceTextureClient::unlockAndPost() +{ + if (mLockedBuffer == 0) { + LOGE("Surface::unlockAndPost failed, no locked buffer"); + return INVALID_OPERATION; + } + + status_t err = mLockedBuffer->unlock(); + LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); + + err = queueBuffer(mLockedBuffer.get()); + LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", + mLockedBuffer->handle, strerror(-err)); + + mPostedBuffer = mLockedBuffer; + mLockedBuffer = 0; + return err; +} + }; // namespace android diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 519b40e..2b8f204 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -613,4 +613,90 @@ TEST_F(SurfaceTextureClientTest, QueryFormatAfterSettingWorks) { } } +class MultiSurfaceTextureClientTest : public ::testing::Test { + +public: + MultiSurfaceTextureClientTest() : + mEglDisplay(EGL_NO_DISPLAY), + mEglContext(EGL_NO_CONTEXT) { + for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { + mEglSurfaces[i] = EGL_NO_CONTEXT; + } + } + +protected: + + enum { NUM_SURFACE_TEXTURES = 32 }; + + virtual void SetUp() { + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); + + EGLint majorVersion, minorVersion; + EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EGLConfig myConfig; + EGLint numConfigs = 0; + EGLint configAttribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE + }; + EXPECT_TRUE(eglChooseConfig(mEglDisplay, configAttribs, &myConfig, 1, + &numConfigs)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, + 0); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_CONTEXT, mEglContext); + + for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { + sp<SurfaceTexture> st(new SurfaceTexture(i)); + sp<SurfaceTextureClient> stc(new SurfaceTextureClient(st)); + mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig, + static_cast<ANativeWindow*>(stc.get()), NULL); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_SURFACE, mEglSurfaces[i]); + } + } + + virtual void TearDown() { + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { + if (mEglSurfaces[i] != EGL_NO_SURFACE) { + eglDestroySurface(mEglDisplay, mEglSurfaces[i]); + } + } + + if (mEglContext != EGL_NO_CONTEXT) { + eglDestroyContext(mEglDisplay, mEglContext); + } + + if (mEglDisplay != EGL_NO_DISPLAY) { + eglTerminate(mEglDisplay); + } + } + + EGLDisplay mEglDisplay; + EGLSurface mEglSurfaces[NUM_SURFACE_TEXTURES]; + EGLContext mEglContext; +}; + +// XXX: This test is disabled because it causes a hang on some devices. See bug +// 5015672. +TEST_F(MultiSurfaceTextureClientTest, DISABLED_MakeCurrentBetweenSurfacesWorks) { + for (int iter = 0; iter < 8; iter++) { + for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) { + eglMakeCurrent(mEglDisplay, mEglSurfaces[i], mEglSurfaces[i], + mEglContext); + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(mEglDisplay, mEglSurfaces[i]); + } + } +} + } // namespace android diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index e232ddd..7114b6a 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -33,6 +33,16 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Caches); namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// +// Macros +/////////////////////////////////////////////////////////////////////////////// + +#if DEBUG_CACHE_FLUSH + #define FLUSH_LOGD(...) LOGD(__VA_ARGS__) +#else + #define FLUSH_LOGD(...) +#endif + +/////////////////////////////////////////////////////////////////////////////// // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// @@ -150,6 +160,30 @@ void Caches::deleteLayerDeferred(Layer* layer) { mLayerGarbage.push(layer); } +void Caches::flush(FlushMode mode) { + FLUSH_LOGD("Flushing caches (mode %d)", mode); + + clearGarbage(); + + switch (mode) { + case kFlushMode_Full: + textureCache.clear(); + patchCache.clear(); + dropShadowCache.clear(); + gradientCache.clear(); + // fall through + case kFlushMode_Moderate: + layerCache.clear(); + pathCache.clear(); + roundRectShapeCache.clear(); + circleShapeCache.clear(); + ovalShapeCache.clear(); + rectShapeCache.clear(); + arcShapeCache.clear(); + break; + } +} + /////////////////////////////////////////////////////////////////////////////// // VBO /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index e64d8ac..76dff4b 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -100,6 +100,18 @@ class Caches: public Singleton<Caches> { Vector<Layer*> mLayerGarbage; public: + enum FlushMode { + kFlushMode_Moderate = 0, + kFlushMode_Full + }; + + /** + * Flush the cache. + * + * @param mode Indicates how much of the cache should be flushed + */ + void flush(FlushMode mode); + /** * Indicates whether the renderer is in debug mode. * This debug mode provides limited information to app developers. diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h index 2cdc8c3..5db73db 100644 --- a/libs/hwui/Debug.h +++ b/libs/hwui/Debug.h @@ -26,6 +26,9 @@ // Turn on to enable memory usage summary on each frame #define DEBUG_MEMORY_USAGE 0 +// Turn on to enable debugging of cache flushes +#define DEBUG_CACHE_FLUSH 1 + // Turn on to enable layers debugging when rendered as regions #define DEBUG_LAYERS_AS_REGIONS 0 diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 9c10c75..794747d 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -303,6 +303,10 @@ int FramebufferNativeWindow::perform(ANativeWindow* window, case NATIVE_WINDOW_CONNECT: case NATIVE_WINDOW_DISCONNECT: break; + case NATIVE_WINDOW_LOCK: + return INVALID_OPERATION; + case NATIVE_WINDOW_UNLOCK_AND_POST: + return INVALID_OPERATION; default: return NAME_NOT_FOUND; } diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index b20a6e9..4f9eb2b 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -551,7 +551,9 @@ public class AudioTrack * @see #PLAYSTATE_PLAYING */ public int getPlayState() { - return mPlayState; + synchronized (mPlayStateLock) { + return mPlayState; + } } /** diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk new file mode 100755 index 0000000..77d40b6 --- /dev/null +++ b/media/libeffects/preprocessing/Android.mk @@ -0,0 +1,32 @@ +LOCAL_PATH:= $(call my-dir) + +# audio preprocessing wrapper +include $(CLEAR_VARS) + +LOCAL_MODULE:= libaudiopreprocessing +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx + +LOCAL_SRC_FILES:= \ + PreProcessing.cpp + +LOCAL_C_INCLUDES += \ + external/webrtc/src \ + external/webrtc/src/modules/interface \ + external/webrtc/src/modules/audio_processing/main/interface \ + system/media/audio_effects/include + +LOCAL_C_INCLUDES += $(call include-path-for, speex) + +LOCAL_SHARED_LIBRARIES := \ + libwebrtc_audio_preprocessing \ + libspeexresampler \ + libutils + +ifeq ($(TARGET_SIMULATOR),true) +LOCAL_LDLIBS += -ldl +else +LOCAL_SHARED_LIBRARIES += libdl +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp new file mode 100755 index 0000000..ba286a1 --- /dev/null +++ b/media/libeffects/preprocessing/PreProcessing.cpp @@ -0,0 +1,1609 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <string.h> +#define LOG_TAG "PreProcessing" +//#define LOG_NDEBUG 0 +#include <utils/Log.h> +#include <utils/Timers.h> +#include <hardware/audio_effect.h> +#include <audio_effects/effect_aec.h> +#include <audio_effects/effect_agc.h> +#include <audio_effects/effect_ns.h> +#include "modules/interface/module_common_types.h" +#include "modules/audio_processing/main/interface/audio_processing.h" +#include "speex/speex_resampler.h" + + +//------------------------------------------------------------------------------ +// local definitions +//------------------------------------------------------------------------------ + +// maximum number of sessions +#define PREPROC_NUM_SESSIONS 8 + +// types of pre processing modules +enum preproc_id +{ + PREPROC_AGC, // Automatic Gain Control + PREPROC_AEC, // Acoustic Echo Canceler + PREPROC_NS, // Noise Suppressor + PREPROC_NUM_EFFECTS +}; + +// Session state +enum preproc_session_state { + PREPROC_SESSION_STATE_INIT, // initialized + PREPROC_SESSION_STATE_CONFIG // configuration received +}; + +// Effect/Preprocessor state +enum preproc_effect_state { + PREPROC_EFFECT_STATE_INIT, // initialized + PREPROC_EFFECT_STATE_CREATED, // webRTC engine created + PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled + PREPROC_EFFECT_STATE_ACTIVE // active/enabled +}; + +// handle on webRTC engine +typedef void* preproc_fx_handle_t; + +typedef struct preproc_session_s preproc_session_t; +typedef struct preproc_effect_s preproc_effect_t; +typedef struct preproc_ops_s preproc_ops_t; + +// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table. +// Function pointer can be null if no action required. +struct preproc_ops_s { + int (* create)(preproc_effect_t *fx); + int (* init)(preproc_effect_t *fx); + int (* reset)(preproc_effect_t *fx); + void (* enable)(preproc_effect_t *fx); + void (* disable)(preproc_effect_t *fx); + int (* set_parameter)(preproc_effect_t *fx, void *param, void *value); + int (* get_parameter)(preproc_effect_t *fx, void *param, size_t *size, void *value); + int (* set_device)(preproc_effect_t *fx, uint32_t device); +}; + +// Effect context +struct preproc_effect_s { + const struct effect_interface_s *itfe; + uint32_t procId; // type of pre processor (enum preproc_id) + uint32_t state; // current state (enum preproc_effect_state) + preproc_session_t *session; // session the effect is on + const preproc_ops_t *ops; // effect ops table + preproc_fx_handle_t engine; // handle on webRTC engine +}; + +// Session context +struct preproc_session_s { + struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session + uint32_t state; // current state (enum preproc_session_state) + int id; // audio session ID + int io; // handle of input stream this session is on + webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM) + size_t apmFrameCount; // buffer size for webRTC process (10 ms) + uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz) + size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount) + uint32_t samplingRate; // sampling rate at effect process interface + uint32_t inChannelCount; // input channel count + uint32_t outChannelCount; // output channel count + uint32_t createdMsk; // bit field containing IDs of crested pre processors + uint32_t enabledMsk; // bit field containing IDs of enabled pre processors + uint32_t processedMsk; // bit field containing IDs of pre processors already + // processed in current round + webrtc::AudioFrame *procFrame; // audio frame passed to webRTC AMP ProcessStream() + int16_t *inBuf; // input buffer used when resampling + size_t inBufSize; // input buffer size in frames + size_t framesIn; // number of frames in input buffer + SpeexResamplerState *inResampler; // handle on input speex resampler + int16_t *outBuf; // output buffer used when resampling + size_t outBufSize; // output buffer size in frames + size_t framesOut; // number of frames in output buffer + SpeexResamplerState *outResampler; // handle on output speex resampler + uint32_t revChannelCount; // number of channels on reverse stream + uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors + // with reverse channel + uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse + // channel already processed in current round + webrtc::AudioFrame *revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream() + int16_t *revBuf; // reverse channel input buffer + size_t revBufSize; // reverse channel input buffer size + size_t framesRev; // number of frames in reverse channel input buffer + SpeexResamplerState *revResampler; // handle on reverse channel input speex resampler +}; + +//------------------------------------------------------------------------------ +// Effect descriptors +//------------------------------------------------------------------------------ + +// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html +// as the pre processing effects are not defined by OpenSL ES + +// Automatic Gain Control +static const effect_descriptor_t sAgcDescriptor = { + { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type + { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid + EFFECT_CONTROL_API_VERSION, + (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), + 0, //FIXME indicate CPU load + 0, //FIXME indicate memory usage + "Automatic Gain Control", + "The Android Open Source Project" +}; + +// Acoustic Echo Cancellation +static const effect_descriptor_t sAecDescriptor = { + { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type + { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid + EFFECT_CONTROL_API_VERSION, + (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), + 0, //FIXME indicate CPU load + 0, //FIXME indicate memory usage + "Acoustic Echo Canceler", + "The Android Open Source Project" +}; + +// Noise suppression +static const effect_descriptor_t sNsDescriptor = { + { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type + { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid + EFFECT_CONTROL_API_VERSION, + (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), + 0, //FIXME indicate CPU load + 0, //FIXME indicate memory usage + "Noise Suppression", + "The Android Open Source Project" +}; + + +static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = { + &sAgcDescriptor, + &sAecDescriptor, + &sNsDescriptor +}; + +//------------------------------------------------------------------------------ +// Helper functions +//------------------------------------------------------------------------------ + +const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = { + FX_IID_AGC, + FX_IID_AEC, + FX_IID_NS +}; + + +const effect_uuid_t * ProcIdToUuid(int procId) +{ + if (procId >= PREPROC_NUM_EFFECTS) { + return EFFECT_UUID_NULL; + } + return sUuidToPreProcTable[procId]; +} + +uint32_t UuidToProcId(const effect_uuid_t * uuid) +{ + size_t i; + for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { + if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) { + break; + } + } + return i; +} + +bool HasReverseStream(uint32_t procId) +{ + if (procId == PREPROC_AEC) { + return true; + } + return false; +} + + +//------------------------------------------------------------------------------ +// Automatic Gain Control (AGC) +//------------------------------------------------------------------------------ + +static const int kAgcDefaultTargetLevel = 0; +static const int kAgcDefaultCompGain = 90; +static const bool kAgcDefaultLimiter = true; + +int AgcInit (preproc_effect_t *effect) +{ + LOGV("AgcInit"); + webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); + agc->set_mode(webrtc::GainControl::kFixedDigital); + agc->set_target_level_dbfs(kAgcDefaultTargetLevel); + agc->set_compression_gain_db(kAgcDefaultCompGain); + agc->enable_limiter(kAgcDefaultLimiter); + return 0; +} + +int AgcCreate(preproc_effect_t *effect) +{ + webrtc::GainControl *agc = effect->session->apm->gain_control(); + LOGV("AgcCreate got agc %p", agc); + if (agc == NULL) { + LOGW("AgcCreate Error"); + return -ENOMEM; + } + effect->engine = static_cast<preproc_fx_handle_t>(agc); + AgcInit(effect); + return 0; +} + +int AgcGetParameter(preproc_effect_t *effect, + void *pParam, + size_t *pValueSize, + void *pValue) +{ + int status = 0; + uint32_t param = *(uint32_t *)pParam; + t_agc_settings *pProperties = (t_agc_settings *)pValue; + webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); + + switch (param) { + case AGC_PARAM_TARGET_LEVEL: + case AGC_PARAM_COMP_GAIN: + if (*pValueSize < sizeof(int16_t)) { + *pValueSize = 0; + return -EINVAL; + } + break; + case AGC_PARAM_LIMITER_ENA: + if (*pValueSize < sizeof(bool)) { + *pValueSize = 0; + return -EINVAL; + } + break; + case AGC_PARAM_PROPERTIES: + if (*pValueSize < sizeof(t_agc_settings)) { + *pValueSize = 0; + return -EINVAL; + } + break; + + default: + LOGW("AgcGetParameter() unknown param %08x", param); + status = -EINVAL; + break; + } + + switch (param) { + case AGC_PARAM_TARGET_LEVEL: + *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100); + LOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue); + break; + case AGC_PARAM_COMP_GAIN: + *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100); + LOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue); + break; + case AGC_PARAM_LIMITER_ENA: + *(bool *) pValue = (bool)agc->is_limiter_enabled(); + LOGV("AgcGetParameter() limiter enabled %s", + (*(int16_t *) pValue != 0) ? "true" : "false"); + break; + case AGC_PARAM_PROPERTIES: + pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100); + pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100); + pProperties->limiterEnabled = (bool)agc->is_limiter_enabled(); + break; + default: + LOGW("AgcGetParameter() unknown param %d", param); + status = -EINVAL; + break; + } + return status; +} + +int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) +{ + int status = 0; + uint32_t param = *(uint32_t *)pParam; + t_agc_settings *pProperties = (t_agc_settings *)pValue; + webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); + + switch (param) { + case AGC_PARAM_TARGET_LEVEL: + LOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue); + status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100)); + break; + case AGC_PARAM_COMP_GAIN: + LOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue); + status = agc->set_compression_gain_db(*(int16_t *)pValue / 100); + break; + case AGC_PARAM_LIMITER_ENA: + LOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false"); + status = agc->enable_limiter(*(bool *)pValue); + break; + case AGC_PARAM_PROPERTIES: + LOGV("AgcSetParameter() properties level %d, gain %d limiter %d", + pProperties->targetLevel, + pProperties->compGain, + pProperties->limiterEnabled); + status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100)); + if (status != 0) break; + status = agc->set_compression_gain_db(pProperties->compGain / 100); + if (status != 0) break; + status = agc->enable_limiter(pProperties->limiterEnabled); + break; + default: + LOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); + status = -EINVAL; + break; + } + + LOGV("AgcSetParameter() done status %d", status); + + return status; +} + +void AgcEnable(preproc_effect_t *effect) +{ + webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); + LOGV("AgcEnable agc %p", agc); + agc->Enable(true); +} + +void AgcDisable(preproc_effect_t *effect) +{ + LOGV("AgcDisable"); + webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); + agc->Enable(false); +} + + +static const preproc_ops_t sAgcOps = { + AgcCreate, + AgcInit, + NULL, + AgcEnable, + AgcDisable, + AgcSetParameter, + AgcGetParameter, + NULL +}; + + +//------------------------------------------------------------------------------ +// Acoustic Echo Canceler (AEC) +//------------------------------------------------------------------------------ + +static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode = + webrtc::EchoControlMobile::kEarpiece; +static const bool kAecDefaultComfortNoise = true; + +int AecInit (preproc_effect_t *effect) +{ + LOGV("AecInit"); + webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); + aec->set_routing_mode(kAecDefaultMode); + aec->enable_comfort_noise(kAecDefaultComfortNoise); + return 0; +} + +int AecCreate(preproc_effect_t *effect) +{ + webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile(); + LOGV("AecCreate got aec %p", aec); + if (aec == NULL) { + LOGW("AgcCreate Error"); + return -ENOMEM; + } + effect->engine = static_cast<preproc_fx_handle_t>(aec); + AecInit (effect); + return 0; +} + +int AecGetParameter(preproc_effect_t *effect, + void *pParam, + size_t *pValueSize, + void *pValue) +{ + int status = 0; + uint32_t param = *(uint32_t *)pParam; + + if (*pValueSize < sizeof(uint32_t)) { + return -EINVAL; + } + switch (param) { + case AEC_PARAM_ECHO_DELAY: + case AEC_PARAM_PROPERTIES: + *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms(); + LOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue); + break; + default: + LOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); + status = -EINVAL; + break; + } + return status; +} + +int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) +{ + int status = 0; + uint32_t param = *(uint32_t *)pParam; + uint32_t value = *(uint32_t *)pValue; + + switch (param) { + case AEC_PARAM_ECHO_DELAY: + case AEC_PARAM_PROPERTIES: + status = effect->session->apm->set_stream_delay_ms(value/1000); + LOGV("AecSetParameter() echo delay %d us, status %d", value, status); + break; + default: + LOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); + status = -EINVAL; + break; + } + return status; +} + +void AecEnable(preproc_effect_t *effect) +{ + webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); + LOGV("AecEnable aec %p", aec); + aec->Enable(true); +} + +void AecDisable(preproc_effect_t *effect) +{ + LOGV("AecDisable"); + webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); + aec->Enable(false); +} + +int AecSetDevice(preproc_effect_t *effect, uint32_t device) +{ + LOGV("AecSetDevice %08x", device); + webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); + webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset; + + switch(device) { + case AUDIO_DEVICE_OUT_EARPIECE: + mode = webrtc::EchoControlMobile::kEarpiece; + break; + case AUDIO_DEVICE_OUT_SPEAKER: + mode = webrtc::EchoControlMobile::kSpeakerphone; + break; + case AUDIO_DEVICE_OUT_WIRED_HEADSET: + case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: + default: + break; + } + aec->set_routing_mode(mode); + return 0; +} + +static const preproc_ops_t sAecOps = { + AecCreate, + AecInit, + NULL, + AecEnable, + AecDisable, + AecSetParameter, + AecGetParameter, + AecSetDevice +}; + +//------------------------------------------------------------------------------ +// Noise Suppression (NS) +//------------------------------------------------------------------------------ + +static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate; + +int NsInit (preproc_effect_t *effect) +{ + LOGV("NsInit"); + webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); + ns->set_level(kNsDefaultLevel); + return 0; +} + +int NsCreate(preproc_effect_t *effect) +{ + webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression(); + LOGV("NsCreate got ns %p", ns); + if (ns == NULL) { + LOGW("AgcCreate Error"); + return -ENOMEM; + } + effect->engine = static_cast<preproc_fx_handle_t>(ns); + NsInit (effect); + return 0; +} + +int NsGetParameter(preproc_effect_t *effect, + void *pParam, + size_t *pValueSize, + void *pValue) +{ + int status = 0; + return status; +} + +int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) +{ + int status = 0; + return status; +} + +void NsEnable(preproc_effect_t *effect) +{ + webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); + LOGV("NsEnable ns %p", ns); + ns->Enable(true); +} + +void NsDisable(preproc_effect_t *effect) +{ + LOGV("NsDisable"); + webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); + ns->Enable(false); +} + +static const preproc_ops_t sNsOps = { + NsCreate, + NsInit, + NULL, + NsEnable, + NsDisable, + NsSetParameter, + NsGetParameter, + NULL +}; + + +static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = { + &sAgcOps, + &sAecOps, + &sNsOps +}; + + +//------------------------------------------------------------------------------ +// Effect functions +//------------------------------------------------------------------------------ + +void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled); + +extern "C" const struct effect_interface_s sEffectInterface; +extern "C" const struct effect_interface_s sEffectInterfaceReverse; + +#define BAD_STATE_ABORT(from, to) \ + LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to); + +int Effect_SetState(preproc_effect_t *effect, uint32_t state) +{ + int status = 0; + LOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state); + switch(state) { + case PREPROC_EFFECT_STATE_INIT: + switch(effect->state) { + case PREPROC_EFFECT_STATE_ACTIVE: + effect->ops->disable(effect); + Session_SetProcEnabled(effect->session, effect->procId, false); + case PREPROC_EFFECT_STATE_CONFIG: + case PREPROC_EFFECT_STATE_CREATED: + case PREPROC_EFFECT_STATE_INIT: + break; + default: + BAD_STATE_ABORT(effect->state, state); + } + break; + case PREPROC_EFFECT_STATE_CREATED: + switch(effect->state) { + case PREPROC_EFFECT_STATE_INIT: + status = effect->ops->create(effect); + break; + case PREPROC_EFFECT_STATE_CREATED: + case PREPROC_EFFECT_STATE_ACTIVE: + case PREPROC_EFFECT_STATE_CONFIG: + LOGE("Effect_SetState invalid transition"); + status = -ENOSYS; + break; + default: + BAD_STATE_ABORT(effect->state, state); + } + break; + case PREPROC_EFFECT_STATE_CONFIG: + switch(effect->state) { + case PREPROC_EFFECT_STATE_INIT: + LOGE("Effect_SetState invalid transition"); + status = -ENOSYS; + break; + case PREPROC_EFFECT_STATE_ACTIVE: + effect->ops->disable(effect); + Session_SetProcEnabled(effect->session, effect->procId, false); + break; + case PREPROC_EFFECT_STATE_CREATED: + case PREPROC_EFFECT_STATE_CONFIG: + break; + default: + BAD_STATE_ABORT(effect->state, state); + } + break; + case PREPROC_EFFECT_STATE_ACTIVE: + switch(effect->state) { + case PREPROC_EFFECT_STATE_INIT: + case PREPROC_EFFECT_STATE_CREATED: + case PREPROC_EFFECT_STATE_ACTIVE: + LOGE("Effect_SetState invalid transition"); + status = -ENOSYS; + break; + case PREPROC_EFFECT_STATE_CONFIG: + effect->ops->enable(effect); + Session_SetProcEnabled(effect->session, effect->procId, true); + break; + default: + BAD_STATE_ABORT(effect->state, state); + } + break; + default: + BAD_STATE_ABORT(effect->state, state); + } + if (status == 0) { + effect->state = state; + } + return status; +} + +int Effect_Init(preproc_effect_t *effect, uint32_t procId) +{ + if (HasReverseStream(procId)) { + effect->itfe = &sEffectInterfaceReverse; + } else { + effect->itfe = &sEffectInterface; + } + effect->ops = sPreProcOps[procId]; + effect->procId = procId; + effect->state = PREPROC_EFFECT_STATE_INIT; + return 0; +} + +int Effect_Create(preproc_effect_t *effect, + preproc_session_t *session, + effect_handle_t *interface) +{ + effect->session = session; + *interface = (effect_handle_t)&effect->itfe; + return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED); +} + +int Effect_Release(preproc_effect_t *effect) +{ + return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT); +} + + +//------------------------------------------------------------------------------ +// Session functions +//------------------------------------------------------------------------------ + +#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP + +static const int kPreprocDefaultSr = 16000; +static const int kPreProcDefaultCnl = 1; + +int Session_Init(preproc_session_t *session) +{ + size_t i; + int status = 0; + + session->state = PREPROC_SESSION_STATE_INIT; + session->id = 0; + session->io = 0; + session->createdMsk = 0; + session->apm = NULL; + for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) { + status = Effect_Init(&session->effects[i], i); + } + return status; +} + + +extern "C" int Session_CreateEffect(preproc_session_t *session, + int32_t procId, + effect_handle_t *interface) +{ + int status = -ENOMEM; + + LOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk); + + if (session->createdMsk == 0) { + session->apm = webrtc::AudioProcessing::Create(session->io); + if (session->apm == NULL) { + LOGW("Session_CreateEffect could not get apm engine"); + goto error; + } + session->apm->set_sample_rate_hz(kPreprocDefaultSr); + session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl); + session->apm->set_num_reverse_channels(kPreProcDefaultCnl); + session->procFrame = new webrtc::AudioFrame(); + if (session->procFrame == NULL) { + LOGW("Session_CreateEffect could not allocate audio frame"); + goto error; + } + session->revFrame = new webrtc::AudioFrame(); + if (session->revFrame == NULL) { + LOGW("Session_CreateEffect could not allocate reverse audio frame"); + goto error; + } + session->apmSamplingRate = kPreprocDefaultSr; + session->apmFrameCount = (kPreprocDefaultSr) / 100; + session->frameCount = session->apmFrameCount; + session->samplingRate = kPreprocDefaultSr; + session->inChannelCount = kPreProcDefaultCnl; + session->outChannelCount = kPreProcDefaultCnl; + session->procFrame->_frequencyInHz = kPreprocDefaultSr; + session->procFrame->_audioChannel = kPreProcDefaultCnl; + session->revChannelCount = kPreProcDefaultCnl; + session->revFrame->_frequencyInHz = kPreprocDefaultSr; + session->revFrame->_audioChannel = kPreProcDefaultCnl; + session->enabledMsk = 0; + session->processedMsk = 0; + session->revEnabledMsk = 0; + session->revProcessedMsk = 0; + session->inResampler = NULL; + session->inBuf = NULL; + session->inBufSize = 0; + session->outResampler = NULL; + session->outBuf = NULL; + session->outBufSize = 0; + session->revResampler = NULL; + session->revBuf = NULL; + session->revBufSize = 0; + } + status = Effect_Create(&session->effects[procId], session, interface); + if (status < 0) { + goto error; + } + LOGV("Session_CreateEffect OK"); + session->createdMsk |= (1<<procId); + return status; + +error: + if (session->createdMsk == 0) { + delete session->revFrame; + session->revFrame = NULL; + delete session->procFrame; + session->procFrame = NULL; + webrtc::AudioProcessing::Destroy(session->apm); + session->apm = NULL; + } + return status; +} + +int Session_ReleaseEffect(preproc_session_t *session, + preproc_effect_t *fx) +{ + LOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId); + session->createdMsk &= ~(1<<fx->procId); + if (session->createdMsk == 0) { + webrtc::AudioProcessing::Destroy(session->apm); + session->apm = NULL; + delete session->procFrame; + session->procFrame = NULL; + delete session->revFrame; + session->revFrame = NULL; + if (session->inResampler != NULL) { + speex_resampler_destroy(session->inResampler); + session->inResampler = NULL; + } + if (session->outResampler != NULL) { + speex_resampler_destroy(session->outResampler); + session->outResampler = NULL; + } + if (session->revResampler != NULL) { + speex_resampler_destroy(session->revResampler); + session->revResampler = NULL; + } + delete session->inBuf; + session->inBuf = NULL; + delete session->outBuf; + session->outBuf = NULL; + delete session->revBuf; + session->revBuf = NULL; + + session->io = 0; + } + + return 0; +} + + +int Session_SetConfig(preproc_session_t *session, effect_config_t *config) +{ + uint32_t sr; + uint32_t inCnl = popcount(config->inputCfg.channels); + uint32_t outCnl = popcount(config->outputCfg.channels); + + if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || + config->inputCfg.format != config->outputCfg.format || + config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { + return -EINVAL; + } + + LOGV("Session_SetConfig sr %d cnl %08x", + config->inputCfg.samplingRate, config->inputCfg.channels); + int status; + + // AEC implementation is limited to 16kHz + if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) { + session->apmSamplingRate = 32000; + } else + if (config->inputCfg.samplingRate >= 16000) { + session->apmSamplingRate = 16000; + } else if (config->inputCfg.samplingRate >= 8000) { + session->apmSamplingRate = 8000; + } + status = session->apm->set_sample_rate_hz(session->apmSamplingRate); + if (status < 0) { + return -EINVAL; + } + status = session->apm->set_num_channels(inCnl, outCnl); + if (status < 0) { + return -EINVAL; + } + status = session->apm->set_num_reverse_channels(inCnl); + if (status < 0) { + return -EINVAL; + } + + session->samplingRate = config->inputCfg.samplingRate; + session->apmFrameCount = session->apmSamplingRate / 100; + if (session->samplingRate == session->apmSamplingRate) { + session->frameCount = session->apmFrameCount; + } else { + session->frameCount = (session->apmFrameCount * session->samplingRate) / + session->apmSamplingRate + 1; + } + session->inChannelCount = inCnl; + session->outChannelCount = outCnl; + session->procFrame->_audioChannel = inCnl; + session->procFrame->_frequencyInHz = session->apmSamplingRate; + + session->revChannelCount = inCnl; + session->revFrame->_audioChannel = inCnl; + session->revFrame->_frequencyInHz = session->apmSamplingRate; + + if (session->inResampler != NULL) { + speex_resampler_destroy(session->inResampler); + session->inResampler = NULL; + } + if (session->outResampler != NULL) { + speex_resampler_destroy(session->outResampler); + session->outResampler = NULL; + } + if (session->revResampler != NULL) { + speex_resampler_destroy(session->revResampler); + session->revResampler = NULL; + } + if (session->samplingRate != session->apmSamplingRate) { + int error; + session->inResampler = speex_resampler_init(session->inChannelCount, + session->samplingRate, + session->apmSamplingRate, + RESAMPLER_QUALITY, + &error); + if (session->inResampler == NULL) { + LOGW("Session_SetConfig Cannot create speex resampler: %s", + speex_resampler_strerror(error)); + return -EINVAL; + } + session->outResampler = speex_resampler_init(session->outChannelCount, + session->apmSamplingRate, + session->samplingRate, + RESAMPLER_QUALITY, + &error); + if (session->outResampler == NULL) { + LOGW("Session_SetConfig Cannot create speex resampler: %s", + speex_resampler_strerror(error)); + speex_resampler_destroy(session->inResampler); + session->inResampler = NULL; + return -EINVAL; + } + session->revResampler = speex_resampler_init(session->inChannelCount, + session->samplingRate, + session->apmSamplingRate, + RESAMPLER_QUALITY, + &error); + if (session->revResampler == NULL) { + LOGW("Session_SetConfig Cannot create speex resampler: %s", + speex_resampler_strerror(error)); + speex_resampler_destroy(session->inResampler); + session->inResampler = NULL; + speex_resampler_destroy(session->outResampler); + session->outResampler = NULL; + return -EINVAL; + } + } + + session->state = PREPROC_SESSION_STATE_CONFIG; + return 0; +} + +int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config) +{ + if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || + config->inputCfg.format != config->outputCfg.format || + config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { + return -EINVAL; + } + + LOGV("Session_SetReverseConfig sr %d cnl %08x", + config->inputCfg.samplingRate, config->inputCfg.channels); + + if (session->state < PREPROC_SESSION_STATE_CONFIG) { + return -ENOSYS; + } + if (config->inputCfg.samplingRate != session->samplingRate || + config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { + return -EINVAL; + } + uint32_t inCnl = popcount(config->inputCfg.channels); + int status = session->apm->set_num_reverse_channels(inCnl); + if (status < 0) { + return -EINVAL; + } + session->revChannelCount = inCnl; + session->revFrame->_audioChannel = inCnl; + session->revFrame->_frequencyInHz = session->apmSamplingRate; + return 0; +} + +void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled) +{ + if (enabled) { + if(session->enabledMsk == 0) { + session->framesIn = 0; + if (session->inResampler != NULL) { + speex_resampler_reset_mem(session->inResampler); + } + session->framesOut = 0; + if (session->outResampler != NULL) { + speex_resampler_reset_mem(session->outResampler); + } + } + session->enabledMsk |= (1 << procId); + if (HasReverseStream(procId)) { + session->framesRev = 0; + if (session->revResampler != NULL) { + speex_resampler_reset_mem(session->revResampler); + } + session->revEnabledMsk |= (1 << procId); + } + } else { + session->enabledMsk &= ~(1 << procId); + if (HasReverseStream(procId)) { + session->revEnabledMsk &= ~(1 << procId); + } + } + LOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", + procId, enabled, session->enabledMsk, session->revEnabledMsk); + session->processedMsk = 0; + if (HasReverseStream(procId)) { + session->revProcessedMsk = 0; + } +} + +//------------------------------------------------------------------------------ +// Bundle functions +//------------------------------------------------------------------------------ + +static int sInitStatus = 1; +static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; + +preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) +{ + size_t i; + int free = -1; + for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { + if (sSessions[i].io == ioId) { + if (sSessions[i].createdMsk & (1 << procId)) { + return NULL; + } + return &sSessions[i]; + } + } + for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { + if (sSessions[i].io == 0) { + sSessions[i].id = sessionId; + sSessions[i].io = ioId; + return &sSessions[i]; + } + } + return NULL; +} + + +int PreProc_Init() { + size_t i; + int status = 0; + + if (sInitStatus <= 0) { + return sInitStatus; + } + for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { + status = Session_Init(&sSessions[i]); + } + sInitStatus = status; + return sInitStatus; +} + +const effect_descriptor_t *PreProc_GetDescriptor(effect_uuid_t *uuid) +{ + size_t i; + for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { + if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { + return sDescriptors[i]; + } + } + return NULL; +} + + +extern "C" { + +//------------------------------------------------------------------------------ +// Effect Control Interface Implementation +//------------------------------------------------------------------------------ + +int PreProcessingFx_Process(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer) +{ + preproc_effect_t * effect = (preproc_effect_t *)self; + int status = 0; + + if (effect == NULL){ + LOGV("PreProcessingFx_Process() ERROR effect == NULL"); + return -EINVAL; + } + preproc_session_t * session = (preproc_session_t *)effect->session; + + if (inBuffer == NULL || inBuffer->raw == NULL || + outBuffer == NULL || outBuffer->raw == NULL){ + LOGW("PreProcessingFx_Process() ERROR bad pointer"); + return -EINVAL; + } + + session->processedMsk |= (1<<effect->procId); + +// LOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", +// inBuffer->frameCount, session->enabledMsk, session->processedMsk); + + if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { + effect->session->processedMsk = 0; + size_t framesRq = outBuffer->frameCount; + size_t framesWr = 0; + if (session->framesOut) { + size_t fr = session->framesOut; + if (outBuffer->frameCount < fr) { + fr = outBuffer->frameCount; + } + memcpy(outBuffer->s16, + session->outBuf, + fr * session->outChannelCount * sizeof(int16_t)); + memcpy(session->outBuf, + session->outBuf + fr * session->outChannelCount, + (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); + session->framesOut -= fr; + framesWr += fr; + } + outBuffer->frameCount = framesWr; + if (framesWr == framesRq) { + inBuffer->frameCount = 0; + return 0; + } + + if (session->inResampler != NULL) { + size_t fr = session->frameCount - session->framesIn; + if (inBuffer->frameCount < fr) { + fr = inBuffer->frameCount; + } + if (session->inBufSize < session->framesIn + fr) { + session->inBufSize = session->framesIn + fr; + session->inBuf = (int16_t *)realloc(session->inBuf, + session->inBufSize * session->inChannelCount * sizeof(int16_t)); + } + memcpy(session->inBuf + session->framesIn * session->inChannelCount, + inBuffer->s16, + fr * session->inChannelCount * sizeof(int16_t)); + + session->framesIn += fr; + inBuffer->frameCount = fr; + if (session->framesIn < session->frameCount) { + return 0; + } + size_t frIn = session->framesIn; + size_t frOut = session->apmFrameCount; + if (session->inChannelCount == 1) { + speex_resampler_process_int(session->inResampler, + 0, + session->inBuf, + &frIn, + session->procFrame->_payloadData, + &frOut); + } else { + speex_resampler_process_interleaved_int(session->inResampler, + session->inBuf, + &frIn, + session->procFrame->_payloadData, + &frOut); + } + memcpy(session->inBuf, + session->inBuf + frIn * session->inChannelCount, + (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); + session->framesIn -= frIn; + } else { + size_t fr = session->frameCount - session->framesIn; + if (inBuffer->frameCount < fr) { + fr = inBuffer->frameCount; + } + memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount, + inBuffer->s16, + fr * session->inChannelCount * sizeof(int16_t)); + session->framesIn += fr; + inBuffer->frameCount = fr; + if (session->framesIn < session->frameCount) { + return 0; + } + session->framesIn = 0; + } + session->procFrame->_payloadDataLengthInSamples = + session->apmFrameCount * session->inChannelCount; + + effect->session->apm->ProcessStream(session->procFrame); + + if (session->outBufSize < session->framesOut + session->frameCount) { + session->outBufSize = session->framesOut + session->frameCount; + session->outBuf = (int16_t *)realloc(session->outBuf, + session->outBufSize * session->outChannelCount * sizeof(int16_t)); + } + + if (session->outResampler != NULL) { + size_t frIn = session->apmFrameCount; + size_t frOut = session->frameCount; + if (session->inChannelCount == 1) { + speex_resampler_process_int(session->outResampler, + 0, + session->procFrame->_payloadData, + &frIn, + session->outBuf + session->framesOut * session->outChannelCount, + &frOut); + } else { + speex_resampler_process_interleaved_int(session->outResampler, + session->procFrame->_payloadData, + &frIn, + session->outBuf + session->framesOut * session->outChannelCount, + &frOut); + } + session->framesOut += frOut; + } else { + memcpy(session->outBuf + session->framesOut * session->outChannelCount, + session->procFrame->_payloadData, + session->frameCount * session->outChannelCount * sizeof(int16_t)); + session->framesOut += session->frameCount; + } + size_t fr = session->framesOut; + if (framesRq - framesWr < fr) { + fr = framesRq - framesWr; + } + memcpy(outBuffer->s16 + framesWr * session->outChannelCount, + session->outBuf, + fr * session->outChannelCount * sizeof(int16_t)); + memcpy(session->outBuf, + session->outBuf + fr * session->outChannelCount, + (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); + session->framesOut -= fr; + outBuffer->frameCount += fr; + + return 0; + } else { + return -ENODATA; + } +} + +int PreProcessingFx_Command(effect_handle_t self, + uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData) +{ + preproc_effect_t * effect = (preproc_effect_t *) self; + int retsize; + int status; + + if (effect == NULL){ + return -EINVAL; + } + + //LOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); + + switch (cmdCode){ + case EFFECT_CMD_INIT: + if (pReplyData == NULL || *replySize != sizeof(int)){ + return -EINVAL; + } + if (effect->ops->init) { + effect->ops->init(effect); + } + *(int *)pReplyData = 0; + break; + + case EFFECT_CMD_CONFIGURE: + if (pCmdData == NULL|| + cmdSize != sizeof(effect_config_t)|| + pReplyData == NULL|| + *replySize != sizeof(int)){ + LOGV("PreProcessingFx_Command cmdCode Case: " + "EFFECT_CMD_CONFIGURE: ERROR"); + return -EINVAL; + } + *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); + if (*(int *)pReplyData != 0) { + break; + } + *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); + break; + + case EFFECT_CMD_CONFIGURE_REVERSE: + if (pCmdData == NULL|| + cmdSize != sizeof(effect_config_t)|| + pReplyData == NULL|| + *replySize != sizeof(int)){ + LOGV("PreProcessingFx_Command cmdCode Case: " + "EFFECT_CMD_CONFIGURE_REVERSE: ERROR"); + return -EINVAL; + } + *(int *)pReplyData = Session_SetReverseConfig(effect->session, + (effect_config_t *)pCmdData); + if (*(int *)pReplyData != 0) { + break; + } + break; + + case EFFECT_CMD_RESET: + if (effect->ops->reset) { + effect->ops->reset(effect); + } + break; + + case EFFECT_CMD_GET_PARAM:{ + if (pCmdData == NULL || + cmdSize < (int)sizeof(effect_param_t) || + pReplyData == NULL || + *replySize < (int)sizeof(effect_param_t)){ + LOGV("PreProcessingFx_Command cmdCode Case: " + "EFFECT_CMD_GET_PARAM: ERROR"); + return -EINVAL; + } + effect_param_t *p = (effect_param_t *)pCmdData; + + memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); + + p = (effect_param_t *)pReplyData; + + int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); + + if (effect->ops->get_parameter) { + p->status = effect->ops->get_parameter(effect, p->data, + (size_t *)&p->vsize, + p->data + voffset); + *replySize = sizeof(effect_param_t) + voffset + p->vsize; + } + } break; + + case EFFECT_CMD_SET_PARAM:{ + if (pCmdData == NULL|| + cmdSize < (int)sizeof(effect_param_t) || + pReplyData == NULL || + *replySize != sizeof(int32_t)){ + LOGV("PreProcessingFx_Command cmdCode Case: " + "EFFECT_CMD_SET_PARAM: ERROR"); + return -EINVAL; + } + effect_param_t *p = (effect_param_t *) pCmdData; + + if (p->psize != sizeof(int32_t)){ + LOGV("PreProcessingFx_Command cmdCode Case: " + "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); + return -EINVAL; + } + if (effect->ops->set_parameter) { + *(int *)pReplyData = effect->ops->set_parameter(effect, + (void *)p->data, + p->data + p->psize); + } + } break; + + case EFFECT_CMD_ENABLE: + if (pReplyData == NULL || *replySize != sizeof(int)){ + LOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); + return -EINVAL; + } + *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); + break; + + case EFFECT_CMD_DISABLE: + if (pReplyData == NULL || *replySize != sizeof(int)){ + LOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); + return -EINVAL; + } + *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); + break; + + case EFFECT_CMD_SET_DEVICE: + case EFFECT_CMD_SET_INPUT_DEVICE: + if (pCmdData == NULL || + cmdSize != sizeof(uint32_t)) { + LOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); + return -EINVAL; + } + + if (effect->ops->set_device) { + effect->ops->set_device(effect, *(uint32_t *)pCmdData); + } + break; + + case EFFECT_CMD_SET_VOLUME: + case EFFECT_CMD_SET_AUDIO_MODE: + break; + + default: + return -EINVAL; + } + return 0; +} + + +int PreProcessingFx_GetDescriptor(effect_handle_t self, + effect_descriptor_t *pDescriptor) +{ + preproc_effect_t * effect = (preproc_effect_t *) self; + + if (effect == NULL || pDescriptor == NULL) { + return -EINVAL; + } + + memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t)); + + return 0; +} + +int PreProcessingFx_ProcessReverse(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer) +{ + preproc_effect_t * effect = (preproc_effect_t *)self; + int status = 0; + + if (effect == NULL){ + LOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); + return -EINVAL; + } + preproc_session_t * session = (preproc_session_t *)effect->session; + + if (inBuffer == NULL || inBuffer->raw == NULL){ + LOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); + return -EINVAL; + } + + session->revProcessedMsk |= (1<<effect->procId); + +// LOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", +// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); + + + if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { + effect->session->revProcessedMsk = 0; + if (session->revResampler != NULL) { + size_t fr = session->frameCount - session->framesRev; + if (inBuffer->frameCount < fr) { + fr = inBuffer->frameCount; + } + if (session->revBufSize < session->framesRev + fr) { + session->revBufSize = session->framesRev + fr; + session->revBuf = (int16_t *)realloc(session->revBuf, + session->revBufSize * session->inChannelCount * sizeof(int16_t)); + } + memcpy(session->revBuf + session->framesRev * session->inChannelCount, + inBuffer->s16, + fr * session->inChannelCount * sizeof(int16_t)); + + session->framesRev += fr; + inBuffer->frameCount = fr; + if (session->framesRev < session->frameCount) { + return 0; + } + size_t frIn = session->framesRev; + size_t frOut = session->apmFrameCount; + if (session->inChannelCount == 1) { + speex_resampler_process_int(session->revResampler, + 0, + session->revBuf, + &frIn, + session->revFrame->_payloadData, + &frOut); + } else { + speex_resampler_process_interleaved_int(session->revResampler, + session->revBuf, + &frIn, + session->revFrame->_payloadData, + &frOut); + } + memcpy(session->revBuf, + session->revBuf + frIn * session->inChannelCount, + (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); + session->framesRev -= frIn; + } else { + size_t fr = session->frameCount - session->framesRev; + if (inBuffer->frameCount < fr) { + fr = inBuffer->frameCount; + } + memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount, + inBuffer->s16, + fr * session->inChannelCount * sizeof(int16_t)); + session->framesRev += fr; + inBuffer->frameCount = fr; + if (session->framesRev < session->frameCount) { + return 0; + } + session->framesRev = 0; + } + session->revFrame->_payloadDataLengthInSamples = + session->apmFrameCount * session->inChannelCount; + effect->session->apm->AnalyzeReverseStream(session->revFrame); + return 0; + } else { + return -ENODATA; + } +} + + +// effect_handle_t interface implementation for effect +const struct effect_interface_s sEffectInterface = { + PreProcessingFx_Process, + PreProcessingFx_Command, + PreProcessingFx_GetDescriptor, + NULL +}; + +const struct effect_interface_s sEffectInterfaceReverse = { + PreProcessingFx_Process, + PreProcessingFx_Command, + PreProcessingFx_GetDescriptor, + PreProcessingFx_ProcessReverse +}; + +//------------------------------------------------------------------------------ +// Effect Library Interface Implementation +//------------------------------------------------------------------------------ + +int PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects) +{ + if (PreProc_Init() != 0) { + return sInitStatus; + } + if (pNumEffects == NULL) { + return -EINVAL; + } + *pNumEffects = PREPROC_NUM_EFFECTS; + return sInitStatus; +} + +int PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) +{ + if (PreProc_Init() != 0) { + return sInitStatus; + } + if (index >= PREPROC_NUM_EFFECTS) { + return -EINVAL; + } + memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t)); + return 0; +} + +int PreProcessingLib_Create(effect_uuid_t *uuid, + int32_t sessionId, + int32_t ioId, + effect_handle_t *pInterface) +{ + LOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); + + int status; + const effect_descriptor_t *desc; + preproc_session_t *session; + uint32_t procId; + + if (PreProc_Init() != 0) { + return sInitStatus; + } + desc = PreProc_GetDescriptor(uuid); + if (desc == NULL) { + LOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); + return -EINVAL; + } + procId = UuidToProcId(&desc->type); + + session = PreProc_GetSession(procId, sessionId, ioId); + if (session == NULL) { + LOGW("EffectCreate: no more session available"); + return -EINVAL; + } + + status = Session_CreateEffect(session, procId, pInterface); + + if (status < 0 && session->createdMsk == 0) { + session->io = 0; + } + return status; +} + +int PreProcessingLib_Release(effect_handle_t interface) +{ + int status; + LOGV("EffectRelease start %p", interface); + if (PreProc_Init() != 0) { + return sInitStatus; + } + + preproc_effect_t *fx = (preproc_effect_t *)interface; + + if (fx->session->io == 0) { + return -EINVAL; + } + return Session_ReleaseEffect(fx->session, fx); +} + +int PreProcessingLib_GetDescriptor(effect_uuid_t *uuid, + effect_descriptor_t *pDescriptor) { + + if (pDescriptor == NULL || uuid == NULL){ + return -EINVAL; + } + + const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); + if (desc == NULL) { + LOGV("PreProcessingLib_GetDescriptor() not found"); + return -EINVAL; + } + + LOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); + + memcpy(pDescriptor, desc, sizeof(effect_descriptor_t)); + return 0; +} + +audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { + tag : AUDIO_EFFECT_LIBRARY_TAG, + version : EFFECT_LIBRARY_API_VERSION, + name : "Audio Preprocessing Library", + implementor : "The Android Open Source Project", + query_num_effects : PreProcessingLib_QueryNumberEffects, + query_effect : PreProcessingLib_QueryEffect, + create_effect : PreProcessingLib_Create, + release_effect : PreProcessingLib_Release, + get_descriptor : PreProcessingLib_GetDescriptor +}; + +}; // extern "C" diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 7b7ba74..178039c 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -27,6 +27,8 @@ #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> +#include <gui/SurfaceTextureClient.h> + #include <media/mediaplayer.h> #include <media/AudioTrack.h> @@ -38,6 +40,7 @@ #include <utils/String8.h> #include <system/audio.h> +#include <system/window.h> namespace android { @@ -194,13 +197,62 @@ status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *m return mPlayer->getMetadata(update_only, apply_filter, metadata); } +void MediaPlayer::disconnectNativeWindow() { + if (mConnectedWindow != NULL) { + status_t err = native_window_disconnect(mConnectedWindow.get(), + NATIVE_WINDOW_API_MEDIA); + + if (err != OK) { + LOGW("native_window_disconnect returned an error: %s (%d)", + strerror(-err), err); + } + } + mConnectedWindow.clear(); +} + status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) { LOGV("setVideoSurface"); Mutex::Autolock _l(mLock); if (mPlayer == 0) return NO_INIT; - return mPlayer->setVideoSurface(surface); + sp<IBinder> binder(surface == NULL ? NULL : surface->asBinder()); + if (mConnectedWindowBinder == binder) { + return OK; + } + + if (surface != NULL) { + status_t err = native_window_connect(surface.get(), + NATIVE_WINDOW_API_MEDIA); + + if (err != OK) { + // Note that we must do the reset before disconnecting from the ANW. + // Otherwise queue/dequeue calls could be made on the disconnected + // ANW, which may result in errors. + reset_l(); + + disconnectNativeWindow(); + + return err; + } + } + + // Note that we must set the player's new surface before disconnecting the + // old one. Otherwise queue/dequeue calls could be made on the disconnected + // ANW, which may result in errors. + status_t err = mPlayer->setVideoSurface(surface); + + disconnectNativeWindow(); + + mConnectedWindow = surface; + + if (err == OK) { + mConnectedWindowBinder = binder; + } else { + disconnectNativeWindow(); + } + + return err; } status_t MediaPlayer::setVideoSurfaceTexture( @@ -210,7 +262,46 @@ status_t MediaPlayer::setVideoSurfaceTexture( Mutex::Autolock _l(mLock); if (mPlayer == 0) return NO_INIT; - return mPlayer->setVideoSurfaceTexture(surfaceTexture); + sp<IBinder> binder(surfaceTexture == NULL ? NULL : + surfaceTexture->asBinder()); + if (mConnectedWindowBinder == binder) { + return OK; + } + + sp<ANativeWindow> anw; + if (surfaceTexture != NULL) { + anw = new SurfaceTextureClient(surfaceTexture); + status_t err = native_window_connect(anw.get(), + NATIVE_WINDOW_API_MEDIA); + + if (err != OK) { + // Note that we must do the reset before disconnecting from the ANW. + // Otherwise queue/dequeue calls could be made on the disconnected + // ANW, which may result in errors. + reset_l(); + + disconnectNativeWindow(); + + return err; + } + } + + // Note that we must set the player's new SurfaceTexture before + // disconnecting the old one. Otherwise queue/dequeue calls could be made + // on the disconnected ANW, which may result in errors. + status_t err = mPlayer->setVideoSurfaceTexture(surfaceTexture); + + disconnectNativeWindow(); + + mConnectedWindow = anw; + + if (err == OK) { + mConnectedWindowBinder = binder; + } else { + disconnectNativeWindow(); + } + + return err; } // must call with lock held @@ -434,10 +525,8 @@ status_t MediaPlayer::seekTo(int msec) return result; } -status_t MediaPlayer::reset() +status_t MediaPlayer::reset_l() { - LOGV("reset"); - Mutex::Autolock _l(mLock); mLoop = false; if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; mPrepareSync = false; @@ -458,6 +547,13 @@ status_t MediaPlayer::reset() return NO_ERROR; } +status_t MediaPlayer::reset() +{ + LOGV("reset"); + Mutex::Autolock _l(mLock); + return reset_l(); +} + status_t MediaPlayer::setAudioStreamType(int type) { LOGV("MediaPlayer::setAudioStreamType"); diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index 5a5330d..0251baf 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -58,8 +58,10 @@ NuPlayer::HTTPLiveSource::HTTPLiveSource( } NuPlayer::HTTPLiveSource::~HTTPLiveSource() { - mLiveSession->disconnect(); - mLiveLooper->stop(); + if (mLiveSession != NULL) { + mLiveSession->disconnect(); + mLiveLooper->stop(); + } } void NuPlayer::HTTPLiveSource::start() { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 7cd8b6c..c6fca2c 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -118,9 +118,15 @@ status_t NuPlayerDriver::start() { mPlayer->start(); if (mStartupSeekTimeUs >= 0) { - mPlayer->seekToAsync(mStartupSeekTimeUs); + if (mStartupSeekTimeUs == 0) { + notifySeekComplete(); + } else { + mPlayer->seekToAsync(mStartupSeekTimeUs); + } + mStartupSeekTimeUs = -1; } + break; } case PLAYING: diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 5cab60e..4f8336e 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -4330,26 +4330,19 @@ status_t OMXCodec::pause() { status_t QueryCodecs( const sp<IOMX> &omx, - const char *mime, bool queryDecoders, + const char *mime, bool queryDecoders, bool hwCodecOnly, Vector<CodecCapabilities> *results) { + Vector<String8> matchingCodecs; results->clear(); - for (int index = 0;; ++index) { - const char *componentName; + OMXCodec::findMatchingCodecs(mime, + !queryDecoders /*createEncoder*/, + NULL /*matchComponentName*/, + hwCodecOnly ? OMXCodec::kHardwareCodecsOnly : 0 /*flags*/, + &matchingCodecs); - if (!queryDecoders) { - componentName = GetCodec( - kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]), - mime, index); - } else { - componentName = GetCodec( - kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]), - mime, index); - } - - if (!componentName) { - return OK; - } + for (size_t c = 0; c < matchingCodecs.size(); c++) { + const char *componentName = matchingCodecs.itemAt(c).string(); if (strncmp(componentName, "OMX.", 4)) { // Not an OpenMax component but a software codec. @@ -4411,6 +4404,8 @@ status_t QueryCodecs( CHECK_EQ(omx->freeNode(node), (status_t)OK); } + + return OK; } void OMXCodec::restorePatchedDataPointer(BufferInfo *info) { diff --git a/media/libstagefright/XINGSeeker.cpp b/media/libstagefright/XINGSeeker.cpp index 0d0d6c2..2091381 100644 --- a/media/libstagefright/XINGSeeker.cpp +++ b/media/libstagefright/XINGSeeker.cpp @@ -24,8 +24,8 @@ namespace android { static bool parse_xing_header( const sp<DataSource> &source, off64_t first_frame_pos, int32_t *frame_number = NULL, int32_t *byte_number = NULL, - char *table_of_contents = NULL, int32_t *quality_indicator = NULL, - int64_t *duration = NULL); + unsigned char *table_of_contents = NULL, + int32_t *quality_indicator = NULL, int64_t *duration = NULL); // static sp<XINGSeeker> XINGSeeker::CreateFromSource( @@ -94,7 +94,7 @@ bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) { static bool parse_xing_header( const sp<DataSource> &source, off64_t first_frame_pos, int32_t *frame_number, int32_t *byte_number, - char *table_of_contents, int32_t *quality_indicator, + unsigned char *table_of_contents, int32_t *quality_indicator, int64_t *duration) { if (frame_number) { *frame_number = 0; diff --git a/media/libstagefright/codecs/aacenc/src/bit_cnt.c b/media/libstagefright/codecs/aacenc/src/bit_cnt.c index dd0b9b4..8853efc 100644 --- a/media/libstagefright/codecs/aacenc/src/bit_cnt.c +++ b/media/libstagefright/codecs/aacenc/src/bit_cnt.c @@ -496,7 +496,7 @@ Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF { Word32 i, t0, t1, t2, t3, t00, t01; - Word16 codeWord, codeLength; + UWord16 codeWord, codeLength; Word16 sign, signLength; diff --git a/media/libstagefright/codecs/aacenc/src/memalign.c b/media/libstagefright/codecs/aacenc/src/memalign.c index 7d20352..44dd4ba 100644 --- a/media/libstagefright/codecs/aacenc/src/memalign.c +++ b/media/libstagefright/codecs/aacenc/src/memalign.c @@ -23,6 +23,11 @@ #include "memalign.h" +#ifdef _MSC_VER +#include <stddef.h> +#else +#include <stdint.h> +#endif /***************************************************************************** * @@ -66,8 +71,8 @@ mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, pMemop->Set(CodecID, tmp, 0, size + alignment); mem_ptr = - (unsigned char *) ((unsigned int) (tmp + alignment - 1) & - (~((unsigned int) (alignment - 1)))); + (unsigned char *) ((intptr_t) (tmp + alignment - 1) & + (~((intptr_t) (alignment - 1)))); if (mem_ptr == tmp) mem_ptr += alignment; diff --git a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c deleted file mode 100644 index dd7c26d..0000000 --- a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - ** Copyright 2003-2010, VisualOn, 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 - ** - ** 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. - */ -/******************************************************************************* - File: cmnMemory.c - - Content: sample code for memory operator implementation - -*******************************************************************************/ -#include "cmnMemory.h" - -#include <malloc.h> -#if defined LINUX -#include <string.h> -#endif - -//VO_MEM_OPERATOR g_memOP; - -VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) -{ - if (!pMemInfo) - return VO_ERR_INVALID_ARG; - - pMemInfo->VBuffer = malloc (pMemInfo->Size); - return 0; -} - -VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem) -{ - free (pMem); - return 0; -} - -VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize) -{ - memset (pBuff, uValue, uSize); - return 0; -} - -VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) -{ - memcpy (pDest, pSource, uSize); - return 0; -} - -VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize) -{ - return 0; -} - -VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize) -{ - return memcmp(pBuffer1, pBuffer2, uSize); -} - -VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) -{ - memmove (pDest, pSource, uSize); - return 0; -} - diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c index dd7c26d..aa52bd9 100644 --- a/media/libstagefright/codecs/common/cmnMemory.c +++ b/media/libstagefright/codecs/common/cmnMemory.c @@ -21,10 +21,8 @@ *******************************************************************************/ #include "cmnMemory.h" -#include <malloc.h> -#if defined LINUX +#include <stdlib.h> #include <string.h> -#endif //VO_MEM_OPERATOR g_memOP; diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/libstagefright/codecs/common/include/voType.h index 70b2e83..5f659ab 100644 --- a/media/libstagefright/codecs/common/include/voType.h +++ b/media/libstagefright/codecs/common/include/voType.h @@ -101,7 +101,7 @@ typedef signed long VO_S32; since the compiler does not support the way the component was written. */ #ifndef VO_SKIP64BIT -#ifdef _WIN32 +#ifdef _MSC_VER /** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ typedef unsigned __int64 VO_U64; /** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */ diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index 8ecc17c..73b3d5b 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -36,11 +36,10 @@ #include <ctype.h> #include <openssl/aes.h> +#include <openssl/md5.h> namespace android { -const int64_t LiveSession::kMaxPlaylistAgeUs = 15000000ll; - LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid) : mFlags(flags), mUIDValid(uidValid), @@ -59,7 +58,8 @@ LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid) mDurationUs(-1), mSeekDone(false), mDisconnectPending(false), - mMonitorQueueGeneration(0) { + mMonitorQueueGeneration(0), + mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY) { if (mUIDValid) { mHTTPDataSource->setUID(mUID); } @@ -175,7 +175,8 @@ void LiveSession::onConnect(const sp<AMessage> &msg) { mMasterURL = url; - sp<M3UParser> playlist = fetchPlaylist(url.c_str()); + bool dummy; + sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy); if (playlist == NULL) { LOGE("unable to fetch master playlist '%s'.", url.c_str()); @@ -289,7 +290,9 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) { return OK; } -sp<M3UParser> LiveSession::fetchPlaylist(const char *url) { +sp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) { + *unchanged = false; + sp<ABuffer> buffer; status_t err = fetchFile(url, &buffer); @@ -297,6 +300,38 @@ sp<M3UParser> LiveSession::fetchPlaylist(const char *url) { return NULL; } + // MD5 functionality is not available on the simulator, treat all + // playlists as changed. + +#if defined(HAVE_ANDROID_OS) + uint8_t hash[16]; + + MD5_CTX m; + MD5_Init(&m); + MD5_Update(&m, buffer->data(), buffer->size()); + + MD5_Final(hash, &m); + + if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) { + // playlist unchanged + + if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) { + mRefreshState = (RefreshState)(mRefreshState + 1); + } + + *unchanged = true; + + LOGV("Playlist unchanged, refresh state is now %d", + (int)mRefreshState); + + return NULL; + } + + memcpy(mPlaylistHash, hash, sizeof(hash)); + + mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; +#endif + sp<M3UParser> playlist = new M3UParser(url, buffer->data(), buffer->size()); @@ -384,6 +419,63 @@ size_t LiveSession::getBandwidthIndex() { return index; } +bool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const { + if (mPlaylist == NULL) { + CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY); + return true; + } + + int32_t targetDurationSecs; + CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); + + int64_t targetDurationUs = targetDurationSecs * 1000000ll; + + int64_t minPlaylistAgeUs; + + switch (mRefreshState) { + case INITIAL_MINIMUM_RELOAD_DELAY: + { + size_t n = mPlaylist->size(); + if (n > 0) { + sp<AMessage> itemMeta; + CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta)); + + int64_t itemDurationUs; + CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); + + minPlaylistAgeUs = itemDurationUs; + break; + } + + // fall through + } + + case FIRST_UNCHANGED_RELOAD_ATTEMPT: + { + minPlaylistAgeUs = targetDurationUs / 2; + break; + } + + case SECOND_UNCHANGED_RELOAD_ATTEMPT: + { + minPlaylistAgeUs = (targetDurationUs * 3) / 2; + break; + } + + case THIRD_UNCHANGED_RELOAD_ATTEMPT: + { + minPlaylistAgeUs = targetDurationUs * 3; + break; + } + + default: + TRESPASS(); + break; + } + + return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs; +} + void LiveSession::onDownloadNext() { size_t bandwidthIndex = getBandwidthIndex(); @@ -392,8 +484,7 @@ rinse_repeat: if (mLastPlaylistFetchTimeUs < 0 || (ssize_t)bandwidthIndex != mPrevBandwidthIndex - || (!mPlaylist->isComplete() - && mLastPlaylistFetchTimeUs + kMaxPlaylistAgeUs <= nowUs)) { + || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) { AString url; if (mBandwidthItems.size() > 0) { url = mBandwidthItems.editItemAt(bandwidthIndex).mURI; @@ -403,11 +494,25 @@ rinse_repeat: bool firstTime = (mPlaylist == NULL); - mPlaylist = fetchPlaylist(url.c_str()); - if (mPlaylist == NULL) { - LOGE("failed to load playlist at url '%s'", url.c_str()); - mDataSource->queueEOS(ERROR_IO); - return; + if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) { + // If we switch bandwidths, do not pay any heed to whether + // playlists changed since the last time... + mPlaylist.clear(); + } + + bool unchanged; + sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged); + if (playlist == NULL) { + if (unchanged) { + // We succeeded in fetching the playlist, but it was + // unchanged from the last time we tried. + } else { + LOGE("failed to load playlist at url '%s'", url.c_str()); + mDataSource->queueEOS(ERROR_IO); + return; + } + } else { + mPlaylist = playlist; } if (firstTime) { diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h index 188ef5e..116ed0e 100644 --- a/media/libstagefright/include/LiveSession.h +++ b/media/libstagefright/include/LiveSession.h @@ -62,8 +62,6 @@ private: kMaxNumRetries = 5, }; - static const int64_t kMaxPlaylistAgeUs; - enum { kWhatConnect = 'conn', kWhatDisconnect = 'disc', @@ -106,6 +104,16 @@ private: int32_t mMonitorQueueGeneration; + enum RefreshState { + INITIAL_MINIMUM_RELOAD_DELAY, + FIRST_UNCHANGED_RELOAD_ATTEMPT, + SECOND_UNCHANGED_RELOAD_ATTEMPT, + THIRD_UNCHANGED_RELOAD_ATTEMPT + }; + RefreshState mRefreshState; + + uint8_t mPlaylistHash[16]; + void onConnect(const sp<AMessage> &msg); void onDisconnect(); void onDownloadNext(); @@ -113,7 +121,7 @@ private: void onSeek(const sp<AMessage> &msg); status_t fetchFile(const char *url, sp<ABuffer> *out); - sp<M3UParser> fetchPlaylist(const char *url); + sp<M3UParser> fetchPlaylist(const char *url, bool *unchanged); size_t getBandwidthIndex(); status_t decryptBuffer( @@ -121,6 +129,8 @@ private: void postMonitorQueue(int64_t delayUs = 0); + bool timeToRefreshPlaylist(int64_t nowUs) const; + static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *); DISALLOW_EVIL_CONSTRUCTORS(LiveSession); diff --git a/media/libstagefright/include/XINGSeeker.h b/media/libstagefright/include/XINGSeeker.h index d5a484e..ec5bd9b 100644 --- a/media/libstagefright/include/XINGSeeker.h +++ b/media/libstagefright/include/XINGSeeker.h @@ -37,7 +37,7 @@ private: int32_t mSizeBytes; // TOC entries in XING header. Skip the first one since it's always 0. - char mTableOfContents[99]; + unsigned char mTableOfContents[99]; XINGSeeker(); diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp index 817eac0..20225ba 100644 --- a/media/mtp/MtpDataPacket.cpp +++ b/media/mtp/MtpDataPacket.cpp @@ -345,56 +345,28 @@ void MtpDataPacket::putString(const uint16_t* string) { #ifdef MTP_DEVICE int MtpDataPacket::read(int fd) { - // first read the header - int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); - if (ret != MTP_CONTAINER_HEADER_SIZE) - return -1; - // then the following data - int total = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); - allocate(total); - int remaining = total - MTP_CONTAINER_HEADER_SIZE; - ret = ::read(fd, &mBuffer[0] + MTP_CONTAINER_HEADER_SIZE, remaining); - if (ret != remaining) + int ret = ::read(fd, mBuffer, mBufferSize); + if (ret < MTP_CONTAINER_HEADER_SIZE) return -1; - - mPacketSize = total; + mPacketSize = ret; mOffset = MTP_CONTAINER_HEADER_SIZE; - return total; -} - -int MtpDataPacket::readDataHeader(int fd) { - int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); - if (ret > 0) - mPacketSize = ret; - else - mPacketSize = 0; return ret; } int MtpDataPacket::write(int fd) { MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize); MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); - // send header separately from data - int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); - if (ret == MTP_CONTAINER_HEADER_SIZE) - ret = ::write(fd, mBuffer + MTP_CONTAINER_HEADER_SIZE, - mPacketSize - MTP_CONTAINER_HEADER_SIZE); - return (ret < 0 ? ret : 0); -} - -int MtpDataPacket::writeDataHeader(int fd, uint32_t length) { - MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length); - MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); - int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); + int ret = ::write(fd, mBuffer, mPacketSize); return (ret < 0 ? ret : 0); } int MtpDataPacket::writeData(int fd, void* data, uint32_t length) { - MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length + MTP_CONTAINER_HEADER_SIZE); + allocate(length); + memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length); + length += MTP_CONTAINER_HEADER_SIZE; + MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length); MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); - int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); - if (ret == MTP_CONTAINER_HEADER_SIZE) - ret = ::write(fd, data, length); + int ret = ::write(fd, mBuffer, length); return (ret < 0 ? ret : 0); } diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h index 8a08948..2b81063 100644 --- a/media/mtp/MtpDataPacket.h +++ b/media/mtp/MtpDataPacket.h @@ -41,6 +41,7 @@ public: void setOperationCode(MtpOperationCode code); void setTransactionID(MtpTransactionID id); + inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; } inline uint8_t getUInt8() { return (uint8_t)mBuffer[mOffset++]; } inline int8_t getInt8() { return (int8_t)mBuffer[mOffset++]; } uint16_t getUInt16(); @@ -95,11 +96,9 @@ public: #ifdef MTP_DEVICE // fill our buffer with data from the given file descriptor int read(int fd); - int readDataHeader(int fd); // write our data to the given file descriptor int write(int fd); - int writeDataHeader(int fd, uint32_t length); int writeData(int fd, void* data, uint32_t length); #endif diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 4047e2e..a9b539b 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -731,14 +731,12 @@ MtpResponseCode MtpServer::doGetObject() { } mfr.offset = 0; mfr.length = fileLength; - - // send data header - mData.setOperationCode(mRequest.getOperationCode()); - mData.setTransactionID(mRequest.getTransactionID()); - mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE); + mfr.command = mRequest.getOperationCode(); + mfr.transaction_id = mRequest.getTransactionID(); // then transfer the file - int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); + int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); + LOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); close(mfr.fd); if (ret < 0) { if (errno == ECANCELED) @@ -798,15 +796,13 @@ MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { } mfr.offset = offset; mfr.length = length; + mfr.command = mRequest.getOperationCode(); + mfr.transaction_id = mRequest.getTransactionID(); mResponse.setParameter(1, length); - // send data header - mData.setOperationCode(mRequest.getOperationCode()); - mData.setTransactionID(mRequest.getTransactionID()); - mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE); - - // then transfer the file - int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); + // transfer the file + int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); + LOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); close(mfr.fd); if (ret < 0) { if (errno == ECANCELED) @@ -918,7 +914,7 @@ MtpResponseCode MtpServer::doSendObject() { return MTP_RESPONSE_GENERAL_ERROR; MtpResponseCode result = MTP_RESPONSE_OK; mode_t mask; - int ret; + int ret, initialData; if (mSendObjectHandle == kInvalidObjectHandle) { LOGE("Expected SendObjectInfo before SendObject"); @@ -926,12 +922,13 @@ MtpResponseCode MtpServer::doSendObject() { goto done; } - // read the header - ret = mData.readDataHeader(mFD); - // FIXME - check for errors here. - - // reset so we don't attempt to send this back - mData.reset(); + // read the header, and possibly some data + ret = mData.read(mFD); + if (ret < MTP_CONTAINER_HEADER_SIZE) { + result = MTP_RESPONSE_GENERAL_ERROR; + goto done; + } + initialData = ret - MTP_CONTAINER_HEADER_SIZE; mtp_file_range mfr; mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); @@ -945,15 +942,19 @@ MtpResponseCode MtpServer::doSendObject() { fchmod(mfr.fd, mFilePermission); umask(mask); - mfr.offset = 0; - mfr.length = mSendObjectFileSize; + if (initialData > 0) + ret = write(mfr.fd, mData.getData(), initialData); - LOGV("receiving %s\n", (const char *)mSendObjectFilePath); - // transfer the file - ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); - close(mfr.fd); + if (mSendObjectFileSize - initialData > 0) { + mfr.offset = initialData; + mfr.length = mSendObjectFileSize - initialData; - LOGV("MTP_RECEIVE_FILE returned %d", ret); + LOGV("receiving %s\n", (const char *)mSendObjectFilePath); + // transfer the file + ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); + LOGV("MTP_RECEIVE_FILE returned %d\n", ret); + } + close(mfr.fd); if (ret < 0) { unlink(mSendObjectFilePath); @@ -964,6 +965,9 @@ MtpResponseCode MtpServer::doSendObject() { } done: + // reset so we don't attempt to send the data back + mData.reset(); + mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, result == MTP_RESPONSE_OK); mSendObjectHandle = kInvalidObjectHandle; @@ -1096,23 +1100,31 @@ MtpResponseCode MtpServer::doSendPartialObject() { return MTP_RESPONSE_GENERAL_ERROR; } - // read the header - int ret = mData.readDataHeader(mFD); - // FIXME - check for errors here. + const char* filePath = (const char *)edit->mPath; + LOGV("receiving partial %s %lld %lld\n", filePath, offset, length); - // reset so we don't attempt to send this back - mData.reset(); + // read the header, and possibly some data + int ret = mData.read(mFD); + if (ret < MTP_CONTAINER_HEADER_SIZE) + return MTP_RESPONSE_GENERAL_ERROR; + int initialData = ret - MTP_CONTAINER_HEADER_SIZE; - const char* filePath = (const char *)edit->mPath; - LOGV("receiving partial %s %lld %ld\n", filePath, offset, length); - mtp_file_range mfr; - mfr.fd = edit->mFD; - mfr.offset = offset; - mfr.length = length; + if (initialData > 0) { + ret = write(edit->mFD, mData.getData(), initialData); + offset += initialData; + length -= initialData; + } - // transfer the file - ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); - LOGV("MTP_RECEIVE_FILE returned %d", ret); + if (length > 0) { + mtp_file_range mfr; + mfr.fd = edit->mFD; + mfr.offset = offset; + mfr.length = length; + + // transfer the file + ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); + LOGV("MTP_RECEIVE_FILE returned %d", ret); + } if (ret < 0) { mResponse.setParameter(1, 0); if (errno == ECANCELED) @@ -1120,6 +1132,9 @@ MtpResponseCode MtpServer::doSendPartialObject() { else return MTP_RESPONSE_GENERAL_ERROR; } + + // reset so we don't attempt to send this back + mData.reset(); mResponse.setParameter(1, length); uint64_t end = offset + length; if (end > edit->mSize) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java index 59783e5..4d517db 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java @@ -91,8 +91,12 @@ public class MediaPropertiesTest extends assertEquals("AudioType Mismatch ", audioCodecType, mvi.getAudioType()); assertEquals("Audio Sampling " + mvi.getAudioSamplingFrequency(), audioSamplingFrequency, mvi.getAudioSamplingFrequency()); - assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel, - mvi.getAudioChannels()); + // PV SW AAC codec always returns number of channels as Stereo. + // So we do not assert for number of audio channels for AAC_LC + if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) { + assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel, + mvi.getAudioChannels()); + } } protected void validateAudioProperties(int audioCodecType, int duration, @@ -103,8 +107,12 @@ public class MediaPropertiesTest extends duration, aT.getDuration(), 10)); assertEquals("Audio Sampling " + aT.getAudioSamplingFrequency(), audioSamplingFrequency, aT.getAudioSamplingFrequency()); - assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel, - aT.getAudioChannels()); + // PV SW AAC codec always returns number of channels as Stereo. + // So we do not assert for number of audio channels for AAC_LC + if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) { + assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel, + aT.getAudioChannels()); + } } protected void validateImageProperties(int aspectRatio, int fileType, diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp index 2c0e88e..5c016c4 100644 --- a/native/android/native_window.cpp +++ b/native/android/native_window.cpp @@ -81,39 +81,9 @@ int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) { - int type = -1; - if (window->query(window, NATIVE_WINDOW_CONCRETE_TYPE, &type) != 0 || - type != NATIVE_WINDOW_SURFACE) { - return BAD_VALUE; - } - - Region dirtyRegion; - Region* dirtyParam = NULL; - if (inOutDirtyBounds != NULL) { - dirtyRegion.set(*(Rect*)inOutDirtyBounds); - dirtyParam = &dirtyRegion; - } - - Surface::SurfaceInfo info; - status_t res = static_cast<Surface*>(window)->lock(&info, dirtyParam); - if (res != OK) { - return -1; - } - - outBuffer->width = (int32_t)info.w; - outBuffer->height = (int32_t)info.h; - outBuffer->stride = (int32_t)info.s; - outBuffer->format = (int32_t)info.format; - outBuffer->bits = info.bits; - - if (inOutDirtyBounds != NULL) { - *inOutDirtyBounds = dirtyRegion.getBounds(); - } - - return 0; + return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); } int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) { - status_t res = static_cast<Surface*>(window)->unlockAndPost(); - return res == android::OK ? 0 : -1; + return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); } diff --git a/native/include/android/native_window.h b/native/include/android/native_window.h index 337fa96..2f4f2d3 100644 --- a/native/include/android/native_window.h +++ b/native/include/android/native_window.h @@ -99,10 +99,16 @@ int32_t ANativeWindow_getFormat(ANativeWindow* window); * width and height must be either both zero or both non-zero. * */ -int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height, int32_t format); +int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, + int32_t width, int32_t height, int32_t format); /** * Lock the window's next drawing surface for writing. + * inOutDirtyBounds is used as an in/out parameter, upon entering the + * function, it contains the dirty region, that is, the region the caller + * intends to redraw. When the function returns, inOutDirtyBounds is updated + * with the actual area the caller needs to redraw -- this region is often + * extended by ANativeWindow_lock. */ int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 1123e16..6a199db 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -226,7 +226,7 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGL #ifndef EGL_ANDROID_image_native_buffer #define EGL_ANDROID_image_native_buffer 1 struct ANativeWindowBuffer; -#define EGL_NATIVE_BUFFER_ANDROID 0x3140 /* eglCreateImageKHR target */ +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 /* eglCreateImageKHR target */ #endif #ifndef EGL_ANDROID_swap_rectangle @@ -237,6 +237,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSetSwapRectangleANDROID (EGLDisplay dpy, EGLSur typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height); #endif +#ifndef EGL_ANDROID_recordable +#define EGL_ANDROID_recordable 1 +#define EGL_RECORDABLE_ANDROID 0x3142 /* EGLConfig attribute */ +#endif + #ifdef __cplusplus } #endif diff --git a/opengl/specs/EGL_ANDROID_recordable.txt b/opengl/specs/EGL_ANDROID_recordable.txt index cf44465..8dbd26f 100644 --- a/opengl/specs/EGL_ANDROID_recordable.txt +++ b/opengl/specs/EGL_ANDROID_recordable.txt @@ -55,7 +55,7 @@ New Tokens Accepted by the <attribute> parameter of eglGetConfigAttrib and the <attrib_list> parameter of eglChooseConfig: - EGL_RECORDABLE_ANDROID 0xXXXX + EGL_RECORDABLE_ANDROID 0x3142 Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) @@ -103,11 +103,38 @@ Issues RESOLVED: It should not affect sorting. Some implementations may not have any drawback associated with using a recordable EGLConfig. Such - implementations should not have to double-up some of their configs to one sort earlier than . - Implementations that do have drawbacks can use the existing caveat - mechanism to report this drawback to the client. + implementations should not have to double-up some of their configs to one + sort earlier than . Implementations that do have drawbacks can use the + existing caveat mechanism to report this drawback to the client. + + 3. How is this extension expected to be implemented? + + RESPONSE: There are two basic approaches to implementing this extension + that were considered during its design. In both cases it is assumed that a + color space conversion must be performed at some point because most video + encoding formats use a YUV color space. The two approaches are + distinguished by the point at which this color space conversion is + performed. + + One approach involves performing the color space conversion as part of the + eglSwapBuffers call before queuing the rendered image to the ANativeWindow. + In this case, the VisualID of the EGLConfig would correspond to a YUV + Android HAL pixel format from which the video encoder can read. The + EGLConfig would likely have the EGL_SLOW_CONFIG caveat because using that + config to render normal window contents would result in an RGB -> YUV color + space conversion when rendering the frame as well as a YUV -> RGB + conversion when compositing the window. + + The other approach involves performing the color space conversion in the + video encoder. In this case, the VisualID of the EGLConfig would + correspond to an RGB HAL pixel format from which the video encoder can + read. The EGLConfig would likely not need to have any caveat set, as using + this config for normal window rendering would not have any added cost. Revision History +#2 (Jamie Gennis, July 15, 2011) + - Added issue 3. + #1 (Jamie Gennis, July 8, 2011) - Initial draft. diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml b/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml deleted file mode 100644 index 0e58e12..0000000 --- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_selector.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android" - android:exitFadeDuration="@android:integer/config_mediumAnimTime"> - - <item android:state_window_focused="false" android:drawable="@android:color/transparent" /> - - <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. --> - <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/recents_thumbnail_bg_holo" /> - <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/recents_thumbnail_bg_holo" /> - <item android:state_focused="true" android:drawable="@drawable/recents_thumbnail_bg_holo" /> -</selector> - diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml b/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml new file mode 100644 index 0000000..6cae2c4 --- /dev/null +++ b/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:drawable="@drawable/recents_thumbnail_bg" android:id="@+id/base_layer"/> + <item android:drawable="@drawable/recents_thumbnail_overlay" android:id="@+id/overlay_layer"/> +</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml b/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml new file mode 100644 index 0000000..200bac4 --- /dev/null +++ b/packages/SystemUI/res/drawable/recents_thumbnail_overlay.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/recents_thumbnail_bg_press" android:state_pressed="true" /> + <item android:drawable="@*android:color/transparent"/> +</selector> diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml index be4f1d7..8c29042 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml @@ -24,14 +24,15 @@ android:layout_height="wrap_content" android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> - <ImageView android:id="@+id/app_thumbnail" + <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" - android:background="@drawable/recents_thumbnail_bg_selector" + android:clickable="true" + android:background="@drawable/recents_thumbnail_layers" /> <ImageView android:id="@+id/app_icon" diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml index efdd9ac..20ef7cf 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml @@ -51,7 +51,6 @@ android:fadingEdge="horizontal" android:scrollbars="none" android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length" - android:listSelector="@drawable/recents_thumbnail_bg_selector" android:layout_gravity="bottom|left" android:orientation="horizontal" android:clipToPadding="false" diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml index 76965c9..c705a69 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml @@ -24,13 +24,15 @@ android:layout_height="wrap_content" android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> - <ImageView android:id="@+id/app_thumbnail" + <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" + android:clickable="true" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" + android:background="@drawable/recents_thumbnail_layers" /> <ImageView android:id="@+id/app_icon" diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml index 28ef239..c680b8e 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml @@ -48,7 +48,6 @@ android:fadingEdge="vertical" android:scrollbars="none" android:fadingEdgeLength="@*android:dimen/status_bar_height" - android:listSelector="@drawable/recents_thumbnail_bg_selector" android:layout_gravity="bottom|left" android:clipToPadding="false" android:clipChildren="false"> diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml index 9687866..386ce30 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml @@ -24,13 +24,15 @@ android:layout_height="wrap_content" android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> - <ImageView android:id="@+id/app_thumbnail" + <FrameLayout android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" + android:clickable="true" + android:background="@drawable/recents_thumbnail_layers" /> <ImageView android:id="@+id/app_icon" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml index 75fdc67..2c9a152 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml @@ -56,7 +56,6 @@ android:scrollbars="none" android:fadingEdgeLength="20dip" android:layout_gravity="bottom|left" - android:listSelector="@drawable/recents_thumbnail_bg_selector" android:clipToPadding="false" android:clipChildren="false"> diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml b/packages/SystemUI/res/menu/recent_popup_menu.xml index f9bba2a..eecfb9a 100644 --- a/packages/SystemUI/res/drawable/recents_thumbnail_bg_holo.xml +++ b/packages/SystemUI/res/menu/recent_popup_menu.xml @@ -17,7 +17,7 @@ ** limitations under the License. */ --> -<transition xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:drawable="@drawable/recents_thumbnail_bg_press"/> - <item android:drawable="@drawable/recents_thumbnail_bg_press"/> -</transition> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/recent_remove_item" android:title="@string/status_bar_recent_remove_item_title" /> + <item android:id="@+id/recent_inspect_item" android:title="@string/status_bar_recent_inspect_item_title" /> +</menu> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index d8aa61f..f22a657 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"تكبير/تصغير التوافق"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"عند تصميم تطبيق لشاشة أصغر، سيظهر عنصر تحكم في التكبير/التصغير بجوار الساعة."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"تم حفظ لقطة الشاشة إلى المعرض."</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"تعذر حفظ لقطة الشاشة."</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 20748ee..7560aca 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Промяна на мащаба за съвместимост"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Когато дадено приложение е създадено за по-малък екран, до часовника ще се покаже управление за промяна на мащаба."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Екранната снимка е запазена в галерията"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Екранната снимка не можа да бъде запазена"</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index c346184..cba8db4 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilitat"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Quan una aplicació s\'hagi dissenyat per a una pantalla més petita, apareixerà un control de zoom al costat del rellotge."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla desada a la galeria"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"No es pot desar la captura de pantalla"</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 692dd4c..acdbbe5 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilní přiblížení"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Pokud je aplikace navržena pro menší obrazovku, zobrazí se vedle hodin ovládací prvek přiblížení."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Snímek obrazovky byl uložen do Galerie"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Snímek obrazovky se nepodařilo uložit"</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index bd1bd02..d74dc62 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitetszoom"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Når en app er udviklet til en mindre skærm, vises der en zoomfunktion ved uret."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Skærmbilledet gemmes i Galleri"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Skærmbilledet kunne ikke gemmes"</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index ed0bfa4..e09598f 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitätszoom"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Wenn eine App für einen kleineren Bildschirm ausgelegt ist, wird ein Zoom-Steuerelement neben der Uhr angezeigt."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot in Galerie gespeichert."</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Screenshot konnte nicht gespeichert werden."</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 1d907c5..1fc6871 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Ζουμ για συμβατότητα"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Όταν μια εφαρμογή έχει σχεδιαστεί για προβολή σε μικρότερη οθόνη, δίπλα από το ρολόι θα εμφανιστεί ένα στοιχείο ελέγχου ζουμ."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Το στιγμιότυπο οθόνης αποθηκεύτηκε στη συλλογή"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Δεν ήταν δυνατή η αποθήκευση του στιγμιοτύπου οθόνης"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index cda0718..c9bb124 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibility Zoom"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"When an app was designed for a smaller screen, a zoom control will appear by the clock."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot saved to Gallery"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Could not save screenshot"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index fd16ccf..ace34d6 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilidad"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Cuando una aplicación fue diseñada para una pantalla más pequeña, aparece un control de zoom junto al reloj."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la Galería"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"No se pudo guardar la captura de pantalla."</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index a57258a..d4594df 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilidad"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Si la aplicación se ha diseñado para una pantalla más pequeña, aparecerá un control de zoom junto al reloj."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la galería"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"No se ha podido guardar la captura de pantalla."</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 95f1c75..81d3b84 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"بزرگنمایی سازگاری"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"اگر یک برنامه برای صفحه کوچک تری طراحی شده باشد، یک کنترل بزرگنمایی توسط ساعت نشان داده می شود."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"تصویر از صفحه در گالری ذخیره شد"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"ذخیره تصویر صفحه ممکن نیست"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 7bf504f..e0e65ad 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Yhteensopivuustilan zoomaus"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Jos sovellus on suunniteltu pienemmälle näytölle, kellon viereen tulee näkyviin zoomaussäädin."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Kuvakaappaus on tallennettu galleriaan"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Kuvakaappausta ei voitu tallentaa"</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index c1daaa5..1342d8b 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilité"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Si une application a été conçue pour un écran plus petit, une commande de zoom s\'affiche à côté de l\'horloge."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Capture d\'écran enregistrée dans la galerie."</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Impossible d\'enregistrer la capture d\'écran."</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index decaacd..afb18ab 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilni zum"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Kada je aplikacija dizajnirana za manji zaslon, kontrole zumiranja prikazuju se pored sata."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Snimak zaslona spremljen u Galeriju"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Ne mogu spremiti snimak zaslona"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 696566f..448c3e6 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitás -- nagyítás/kicsinyítés"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Ha egy alkalmazást kisebb képernyőre terveztek, akkor a nagyítás/kicsinyítés vezérlője az óra mellett jelenik meg."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Képernyőkép mentve a galériába"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Nem sikerült menteni a képernyőképet"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 78f29c1..02f1ff6 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom Kompatibilitas"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Saat apl dirancang untuk layar yang lebih kecil, kontrol zoom akan tampil di dekat jam."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Tangkapan layar disimpan ke Galeri"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Tidak dapat menyimpan tangkapan layar"</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 8c6cd6d..763842a 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom compatibilità"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Se un\'applicazione è stata progettata per uno schermo più piccolo, accanto all\'orologio viene visualizzato un controllo dello zoom."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot salvato nella galleria"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Impossibile salvare lo screenshot"</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 511d49e..5236740 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"שינוי מרחק מתצוגה לתאימות"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"כאשר יישום מיועד למסך קטן יותר, פקד של מרחק מתצוגה יופיע ליד השעון."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"צילום המסך נשמר בגלריה"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"לא ניתן לשמור את צילום המסך"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 88611dd..2e0fad2 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"互換ズーム"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"より小型の画面向けのアプリの場合は、ズームコントロールが時計のそばに表示されます。"</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"スクリーンショットがギャラリーに保存されました"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"スクリーンショットを保存できませんでした"</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 4cc668a..a46b608 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"호환성 확대/축소"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"앱이 작은 화면에 맞도록 설계된 경우 시계 옆에 확대/축소 컨트롤이 표시됩니다."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"캡쳐화면이 갤러리에 저장되었습니다."</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"캡쳐화면을 저장하지 못했습니다."</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index fbdba57..356f46b 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Suderinamumo mastelio keitimas"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Kai programa bus pritaikyta mažesniam ekranui, mastelio keitimo valdiklis bus parodytas šalia laikrodžio."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekrano kopija išsaugota galerijoje"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Nepavyko išsaugoti ekrano kopijos"</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 37e3f92..bf6dbd4 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Saderības tālummaiņa"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Ja lietotne ir paredzēta mazākam ekrānam, blakus pulkstenim tiks parādīta tālummaiņas vadīkla."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekrānuzņēmums ir saglabāts galerijā."</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Nevarēja saglabāt ekrānuzņēmumu."</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index c24a8fb..d51f0cc 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -61,8 +61,6 @@ <skip /> <!-- no translation found for compat_mode_help_body (4946726776359270040) --> <skip /> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Tangkapan skrin disimpan ke Galeri"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Tidak boleh menyimpan tangkapan skrin"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index df92a70..be10217 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitets-zooming"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Når en app er utformet for en mindre skjerm, vises det en zoomkontroll ved klokken."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Skjermdump ble lagret i galleriet"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Lagring av skjermdump mislyktes"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 518402f..c83c7c4 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibiliteitszoom"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Wanneer een app is ontworpen voor een kleiner scherm, wordt naast de klok een zoomknop weergegeven."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Schermafbeelding is opgeslagen in de galerij"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Schermafbeelding is niet opgeslagen"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index c59df62..e5937e2 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Powiększenie w trybie zgodności"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Jeśli aplikacja została przystosowana do mniejszego ekranu, obok zegara zostanie wyświetlony element sterujący powiększeniem."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Zrzut ekranu został zapisany w galerii."</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Nie można zapisać zrzutu ekranu."</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index ee79283..400d805 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibilidade de zoom"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Sempre que uma aplicação tiver sido concebida para ecrãs mais pequenos, aparecerá um controlo de zoom junto ao relógio."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecrã guardada na Galeria"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Não foi possível guardar a captura de ecrã"</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 447cce1..90dd212 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom em modo de compatibilidade"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Quando um aplicativo é desenvolvido para uma tela menor, um controle de zoom é exibido perto do relógio."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"A captura de tela foi salva na Galeria"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Não foi possível salvar a captura de tela"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 07394ab..6dfd055 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilitate"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Atunci când o aplicaţie a fost concepută pentru un ecran mai mic, o comandă pentru mărire/micşorare va apărea alături de ceas."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecran a fost salvată în Galerie"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Captura de ecran nu a putut fi salvată"</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index e4f3e83..d1f6cd2 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Масштаб и совместимость"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Если приложение рассчитано на экран меньших размеров, рядом с часами появятся средства масштабирования."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Скриншот сохранен в галерее"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Не удалось сохранить скриншот"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index f720662..d67752b 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilné priblíženie"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Ak je aplikácia navrhnutá pre menšiu obrazovku, zobrazí sa vedľa hodín ovládací prvok priblíženia."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Snímka obrazovky bola uložená do Galérie"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Snímku obrazovky sa nepodarilo uložiť"</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 37ecf50..c7aade9 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Povečava združljivosti"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Če je program izdelan za manjše zaslone, se ob uri pokaže kontrolnik za povečavo."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Posnetek zaslona je shranjen v galerijo"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Posnetka zaslona ni bilo mogoče shraniti"</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 7290f4c..0afdf98 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Компатибилно зумирање"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Када је апликација намењена мањем екрану, контрола зумирања приказује се поред сата."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Снимак екрана је сачуван у Галерији"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Није могуће сачувати снимак екрана"</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 19c9a09..6cbca3f 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom i kompatibilitetsläge"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"När en app är anpassad för en mindre skärm visas ett zoomreglage vid klockan."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Skärmdumpen sparades i galleriet"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Det gick inte att spara skärmdumpen"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 15f3007..9744c60 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"ความเข้ากันได้ของการย่อ/ขยาย"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"สำหรับแอปพลิเคชันที่ออกแบบมาสำหรับหน้าจอขนาดเล็ก ตัวควบคุมการย่อ/ขยายจะปรากฏขึ้นข้างนาฬิกา"</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"บันทึกภาพหน้าจอในแกลเลอรีแล้ว"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"ไม่สามารถบันทึกภาพหน้าจอ"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 93fdb6a..93796f3 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom sa Pagiging Tugma"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Kapag nakadisenyo ang isang app para sa mas maliit na screen, isang kontrol ng zoom ang lalabas sa may orasan."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Na-save ang screenshot sa Gallery"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Hindi ma-save ang screenshot"</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 5ec11b6..2fd0df5 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Uyumluluk Zum\'u"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Uygulama küçük bir ekran için tasarlanmışsa saatin yanında bir yakınlaştırma denetimi görünür."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekran görüntüsü Galeri\'ye kaydedildi"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Ekran görüntüsü kaydedilemedi"</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 759acdc..a81dbbf 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Елемент керування масштабом для сумісності"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Якщо програму призначено для менших екранів, елемент керування масштабом буде відображатися біля годинника."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Знімок екрана збережено в Галереї"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Неможливо зберегти знімок екрана"</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index af44600..b660b98 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"Thu phóng tương thích"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"Khi ứng dụng được thiết kế cho một màn hình nhỏ hơn, điều khiển thu phóng sẽ xuất hiện bên cạnh đồng hồ."</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"Đã lưu ảnh chụp màn hình vào Thư viện"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"Không thể lưu ảnh chụp màn hình"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 201ecfa..397d590 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"兼容性缩放"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"如果应用程序是针对较小屏幕设计的,则时钟旁会显示缩放控件。"</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"屏幕截图已保存到“图库”"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"无法保存屏幕截图"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index a46a909..61afd2ff 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -57,8 +57,6 @@ <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string> <string name="compat_mode_help_header" msgid="7020175705401506719">"相容性縮放"</string> <string name="compat_mode_help_body" msgid="4946726776359270040">"執行專為較小螢幕設計的應用程式時,系統會在時鐘旁顯示縮放控制項。"</string> - <!-- no translation found for screenshot_saving_toast (8592630119048713208) --> - <skip /> - <!-- no translation found for screenshot_failed_toast (655180965533683356) --> - <skip /> + <string name="screenshot_saving_toast" msgid="8592630119048713208">"螢幕擷取畫面已儲存至圖片庫"</string> + <string name="screenshot_failed_toast" msgid="655180965533683356">"無法儲存螢幕擷取畫面"</string> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 882455e..01cf2dc 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -35,6 +35,14 @@ shown again. [CHAR LIMIT=25] --> <string name="status_bar_please_disturb_button">Show notifications</string> + <!-- Title shown in recents popup for removing an application from the list --> + <string name="status_bar_recent_remove_item_title">Remove</string> + + <!-- Title shown in recents popup for inspecting an application's properties --> + <string name="status_bar_recent_inspect_item_title">Inspect</string> + + + <!-- The label in the bar at the top of the status bar when there are no notifications showing. [CHAR LIMIT=40]--> diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java index 37a9913..2d327c4 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java @@ -53,8 +53,6 @@ import android.view.View; void createAnimation(boolean appearing) { float start, end; - if (RecentsPanelView.DEBUG) Log.e(TAG, "createAnimation()", new Exception()); - // 0: on-screen // height: off-screen float y = mContentView.getTranslationY(); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java index 5d29e2a..797f94c 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java @@ -26,5 +26,5 @@ public interface RecentsCallback { void handleOnClick(View selectedView); void handleSwipe(View selectedView, int direction); - void handleLongPress(View selectedView); + void handleLongPress(View selectedView, View anchorView); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index f984aac..2a5d1dd 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -20,6 +20,7 @@ import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; import android.animation.Animator; import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -30,7 +31,6 @@ import android.database.DataSetObserver; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -42,10 +42,9 @@ import android.widget.LinearLayout; import com.android.systemui.R; -public class RecentsHorizontalScrollView extends HorizontalScrollView - implements View.OnClickListener, View.OnTouchListener { - private static final boolean DEBUG_INVALIDATE = false; +public class RecentsHorizontalScrollView extends HorizontalScrollView { private static final String TAG = RecentsPanelView.TAG; + private static final boolean DEBUG_INVALIDATE = false; private static final boolean DEBUG = RecentsPanelView.DEBUG; private LinearLayout mLinearLayout; private ActivityDescriptionAdapter mAdapter; @@ -57,6 +56,15 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView private VelocityTracker mVelocityTracker; private float mDensityScale; private float mPagingTouchSlop; + private OnLongClickListener mOnLongClick = new OnLongClickListener() { + public boolean onLongClick(View v) { + final View anchorView = v.findViewById(R.id.app_description); + mCurrentView = v; + mCallback.handleLongPress(v, anchorView); + mCurrentView = null; // make sure we don't accept the return click from this + return true; + } + }; public RecentsHorizontalScrollView(Context context) { this(context, null); @@ -72,13 +80,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView return mLinearLayout.getWidth() - getWidth(); } - public void update() { + private void update() { mLinearLayout.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { - View view = mAdapter.getView(i, null, mLinearLayout); + final View view = mAdapter.getView(i, null, mLinearLayout); view.setClickable(true); - view.setOnClickListener(this); - view.setOnTouchListener(this); + view.setOnLongClickListener(mOnLongClick); mLinearLayout.addView(view); } // Scroll to end after layout. @@ -91,7 +98,20 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } @Override + public void removeViewInLayout(final View view) { + ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION, + "y", view.getY(), view.getY() + view.getHeight()); + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + RecentsHorizontalScrollView.super.removeView(view); + } + }); + anim.start(); + } + + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } @@ -100,6 +120,18 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView case MotionEvent.ACTION_DOWN: mDragging = false; mLastY = ev.getY(); + final float x = ev.getX() + getScrollX(); + final float y = ev.getY() + getScrollY(); + mCurrentView = null; + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View item = mLinearLayout.getChildAt(i); + if (x >= item.getLeft() && x < item.getRight() + && y >= item.getTop() && y < item.getBottom()) { + mCurrentView = item; + if (DEBUG) Log.v(TAG, "Hit item " + item); + break; + } + } break; case MotionEvent.ACTION_MOVE: @@ -111,6 +143,9 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView break; case MotionEvent.ACTION_UP: + if (mCurrentView != null) { + mCallback.handleOnClick(mCurrentView); + } mDragging = false; break; } @@ -125,7 +160,6 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } else if (view.getY() < thumbHeight * (1.0f - Constants.ALPHA_FADE_START)) { result = 1.0f + (thumbHeight * Constants.ALPHA_FADE_START + view.getY()) / fadeHeight; } - if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result); return result; } @@ -138,12 +172,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView mVelocityTracker.addMovement(ev); final View animView = mCurrentView; - // TODO: Cache thumbnail - final View thumb = animView.findViewById(R.id.app_thumbnail); + switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: if (animView != null) { final float delta = ev.getY() - mLastY; + final View thumb = animView.findViewById(R.id.app_thumbnail); animView.setY(animView.getY() + delta); animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); invalidateGlobalRegion(animView); @@ -167,35 +201,18 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView long duration = (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)); duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); - anim = ObjectAnimator.ofFloat(animView, "y", curY, newY); - anim.setInterpolator(new LinearInterpolator()); - final int swipeDirection = animView.getY() >= 0.0f ? - RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; - anim.addListener(new AnimatorListener() { - public void onAnimationStart(Animator animation) { - } - public void onAnimationRepeat(Animator animation) { - } - public void onAnimationEnd(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - public void onAnimationCancel(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - }); - anim.setDuration(duration); + anim = animateClosed(animView, duration, "y", curY, newY); } else { // Animate back to position long duration = Math.abs(velocityY) > 0.0f ? (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)) : Constants.SNAP_BACK_DURATION; duration = Math.min(duration, Constants.SNAP_BACK_DURATION); anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f); - anim.setInterpolator(new DecelerateInterpolator(2.0f)); + anim.setInterpolator(new DecelerateInterpolator(4.0f)); anim.setDuration(duration); } + final View thumb = animView.findViewById(R.id.app_thumbnail); anim.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); @@ -212,6 +229,26 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView return true; } + private ObjectAnimator animateClosed(final View animView, long duration, + String attr, float from, float to) { + ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to); + anim.setInterpolator(new LinearInterpolator()); + final int swipeDirection = animView.getX() >= 0.0f ? + RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + public void onAnimationCancel(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + }); + anim.setDuration(duration); + return anim; + } + void invalidateGlobalRegion(View view) { RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); @@ -236,13 +273,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView @Override protected void onFinishInflate() { super.onFinishInflate(); - LayoutInflater inflater = (LayoutInflater) - mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - setScrollbarFadingEnabled(true); - mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); - final int leftPadding = mContext.getResources() .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); setOverScrollEffectPadding(leftPadding, 0); @@ -306,16 +338,7 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView mLinearLayout.setLayoutTransition(transition); } - public void onClick(View view) { - mCallback.handleOnClick(view); - } - public void setCallback(RecentsCallback callback) { mCallback = callback; } - - public boolean onTouch(View v, MotionEvent event) { - mCurrentView = v; - return false; - } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index a55fe9c..bc0a508 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -22,6 +22,7 @@ import java.util.List; import android.animation.Animator; import android.animation.LayoutTransition; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -39,16 +40,22 @@ import android.graphics.RectF; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.net.Uri; +import android.provider.Settings; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; +import android.widget.Button; import android.widget.ImageView; +import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.TextView; @@ -69,7 +76,7 @@ public class RecentsPanelView extends RelativeLayout private int mIconDpi; private View mRecentsScrim; private View mRecentsGlowView; - private View mRecentsContainer; + private ViewGroup mRecentsContainer; private Bitmap mGlowBitmap; // TODO: add these widgets attributes to the layout file private int mGlowBitmapPaddingLeftPx; @@ -107,8 +114,18 @@ public class RecentsPanelView extends RelativeLayout } }; + private final class OnLongClickDelegate implements View.OnLongClickListener { + View mOtherView; + OnLongClickDelegate(View other) { + mOtherView = other; + } + public boolean onLongClick(View v) { + return mOtherView.performLongClick(); + } + } + /* package */ final static class ViewHolder { - ImageView thumbnailView; + View thumbnailView; ImageView iconView; TextView labelView; TextView descriptionView; @@ -139,7 +156,7 @@ public class RecentsPanelView extends RelativeLayout if (convertView == null) { convertView = mInflater.inflate(R.layout.status_bar_recent_item, null); holder = new ViewHolder(); - holder.thumbnailView = (ImageView) convertView.findViewById(R.id.app_thumbnail); + holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail); holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon); holder.labelView = (TextView) convertView.findViewById(R.id.app_label); holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description); @@ -153,11 +170,12 @@ public class RecentsPanelView extends RelativeLayout final ActivityDescription activityDescription = mActivityDescriptions.get(activityId); final Bitmap thumb = activityDescription.thumbnail; - holder.thumbnailView.setImageBitmap(compositeBitmap(mGlowBitmap, thumb)); + updateDrawable(holder.thumbnailView, compositeBitmap(mGlowBitmap, thumb)); holder.iconView.setImageDrawable(activityDescription.icon); holder.labelView.setText(activityDescription.label); holder.descriptionView.setText(activityDescription.description); holder.thumbnailView.setTag(activityDescription); + holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView)); holder.activityDescription = activityDescription; return convertView; @@ -174,6 +192,20 @@ public class RecentsPanelView extends RelativeLayout return x >= l && x < r && y >= t && y < b; } + private void updateDrawable(View thumbnailView, Bitmap bitmap) { + Drawable d = thumbnailView.getBackground(); + if (d instanceof LayerDrawable) { + LayerDrawable layerD = (LayerDrawable) d; + Drawable thumb = layerD.findDrawableByLayerId(R.id.base_layer); + if (thumb != null) { + layerD.setDrawableByLayerId(R.id.base_layer, + new BitmapDrawable(getResources(), bitmap)); + return; + } + } + Log.w(TAG, "Failed to update drawable"); + } + public void show(boolean show, boolean animate) { if (animate) { if (mShowing != show) { @@ -260,7 +292,7 @@ public class RecentsPanelView extends RelativeLayout protected void onFinishInflate() { super.onFinishInflate(); mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mRecentsContainer = findViewById(R.id.recents_container); + mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container); mListAdapter = new ActivityDescriptionAdapter(mContext); if (mRecentsContainer instanceof RecentsListView) { RecentsListView listView = (RecentsListView) mRecentsContainer; @@ -503,7 +535,35 @@ public class RecentsPanelView extends RelativeLayout am.removeTask(ad.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS); } - public void handleLongPress(View selectedView) { - // TODO show context menu : "Remove from list", "Show properties" + private void startApplicationDetailsActivity(String packageName) { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.fromParts("package", packageName, null)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getContext().startActivity(intent); + } + + public void handleLongPress(final View selectedView, final View anchorView) { + PopupMenu popup = new PopupMenu(mContext, anchorView == null ? selectedView : anchorView); + popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu()); + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + if (item.getItemId() == R.id.recent_remove_item) { + mRecentsContainer.removeViewInLayout(selectedView); + } else if (item.getItemId() == R.id.recent_inspect_item) { + ViewHolder viewHolder = (ViewHolder) selectedView.getTag(); + if (viewHolder != null) { + final ActivityDescription ad = viewHolder.activityDescription; + startApplicationDetailsActivity(ad.packageName); + mBar.animateCollapse(); + } else { + throw new IllegalStateException("Oops, no tag on view " + selectedView); + } + } else { + return false; + } + return true; + } + }); + popup.show(); } } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index 27bb0b5..47ee4aa 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -20,6 +20,7 @@ import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; import android.animation.Animator; import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -42,8 +43,7 @@ import android.widget.ScrollView; import com.android.systemui.R; -public class RecentsVerticalScrollView extends ScrollView - implements View.OnClickListener, View.OnTouchListener { +public class RecentsVerticalScrollView extends ScrollView { private static final String TAG = RecentsPanelView.TAG; private static final boolean DEBUG_INVALIDATE = false; private static final boolean DEBUG = RecentsPanelView.DEBUG; @@ -57,6 +57,15 @@ public class RecentsVerticalScrollView extends ScrollView private VelocityTracker mVelocityTracker; private float mDensityScale; private float mPagingTouchSlop; + private OnLongClickListener mOnLongClick = new OnLongClickListener() { + public boolean onLongClick(View v) { + final View anchorView = v.findViewById(R.id.app_description); + mCurrentView = v; + mCallback.handleLongPress(v, anchorView); + mCurrentView = null; // make sure we don't accept the return click from this + return true; + } + }; public RecentsVerticalScrollView(Context context) { this(context, null); @@ -72,13 +81,12 @@ public class RecentsVerticalScrollView extends ScrollView return mLinearLayout.getHeight() - getHeight(); } - public void update() { + private void update() { mLinearLayout.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { - View view = mAdapter.getView(i, null, mLinearLayout); + final View view = mAdapter.getView(i, null, mLinearLayout); view.setClickable(true); - view.setOnClickListener(this); - view.setOnTouchListener(this); + view.setOnLongClickListener(mOnLongClick); mLinearLayout.addView(view); } // Scroll to end after layout. @@ -91,7 +99,20 @@ public class RecentsVerticalScrollView extends ScrollView } @Override + public void removeViewInLayout(final View view) { + ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION, + "x", view.getX(), view.getX() + view.getWidth()); + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + RecentsVerticalScrollView.super.removeView(view); + } + }); + anim.start(); + } + + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } @@ -100,6 +121,18 @@ public class RecentsVerticalScrollView extends ScrollView case MotionEvent.ACTION_DOWN: mDragging = false; mLastX = ev.getX(); + final float x = ev.getX() + getScrollX(); + final float y = ev.getY() + getScrollY(); + mCurrentView = null; + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View item = mLinearLayout.getChildAt(i); + if (x >= item.getLeft() && x < item.getRight() + && y >= item.getTop() && y < item.getBottom()) { + mCurrentView = item; + Log.v(TAG, "Hit item " + item); + break; + } + } break; case MotionEvent.ACTION_MOVE: @@ -111,6 +144,9 @@ public class RecentsVerticalScrollView extends ScrollView break; case MotionEvent.ACTION_UP: + if (mCurrentView != null) { + mCallback.handleOnClick(mCurrentView); + } mDragging = false; break; } @@ -125,7 +161,6 @@ public class RecentsVerticalScrollView extends ScrollView } else if (view.getX() < thumbWidth* (1.0f - Constants.ALPHA_FADE_START)) { result = 1.0f + (thumbWidth*Constants.ALPHA_FADE_START + view.getX()) / fadeWidth; } - if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result); return result; } @@ -138,12 +173,12 @@ public class RecentsVerticalScrollView extends ScrollView mVelocityTracker.addMovement(ev); final View animView = mCurrentView; - // TODO: Cache thumbnail - final View thumb = animView.findViewById(R.id.app_thumbnail); + switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: if (animView != null) { final float delta = ev.getX() - mLastX; + final View thumb = animView.findViewById(R.id.app_thumbnail); animView.setX(animView.getX() + delta); animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth())); invalidateGlobalRegion(animView); @@ -163,29 +198,11 @@ public class RecentsVerticalScrollView extends ScrollView final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale; if (Math.abs(velocityX) > Math.abs(velocityY) && Math.abs(velocityX) > maxVelocity - && (velocityX > 0.0f) == (animView.getX() >= 0)) { + && (velocityX >= 0.0f) == (animView.getX() >= 0)) { long duration = (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX)); duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); - anim = ObjectAnimator.ofFloat(animView, "x", curX, newX); - anim.setInterpolator(new LinearInterpolator()); - final int swipeDirection = animView.getX() >= 0.0f ? - RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; - anim.addListener(new AnimatorListener() { - public void onAnimationStart(Animator animation) { - } - public void onAnimationRepeat(Animator animation) { - } - public void onAnimationEnd(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - public void onAnimationCancel(Animator animation) { - mLinearLayout.removeView(mCurrentView); - mCallback.handleSwipe(animView, swipeDirection); - } - }); - anim.setDuration(duration); + anim = animateClosed(animView, duration, "x", curX, newX); } else { // Animate back to position long duration = Math.abs(velocityX) > 0.0f ? (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX)) @@ -196,6 +213,7 @@ public class RecentsVerticalScrollView extends ScrollView anim.setDuration(duration); } + final View thumb = animView.findViewById(R.id.app_thumbnail); anim.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth())); @@ -212,6 +230,26 @@ public class RecentsVerticalScrollView extends ScrollView return true; } + private ObjectAnimator animateClosed(final View animView, long duration, + String attr, float from, float to) { + ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to); + anim.setInterpolator(new LinearInterpolator()); + final int swipeDirection = animView.getX() >= 0.0f ? + RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + public void onAnimationCancel(Animator animation) { + mLinearLayout.removeView(animView); + mCallback.handleSwipe(animView, swipeDirection); + } + }); + anim.setDuration(duration); + return anim; + } + void invalidateGlobalRegion(View view) { RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); @@ -236,13 +274,8 @@ public class RecentsVerticalScrollView extends ScrollView @Override protected void onFinishInflate() { super.onFinishInflate(); - LayoutInflater inflater = (LayoutInflater) - mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - setScrollbarFadingEnabled(true); - mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); - final int leftPadding = mContext.getResources() .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); setOverScrollEffectPadding(leftPadding, 0); @@ -306,16 +339,7 @@ public class RecentsVerticalScrollView extends ScrollView mLinearLayout.setLayoutTransition(transition); } - public void onClick(View view) { - mCallback.handleOnClick(view); - } - public void setCallback(RecentsCallback callback) { mCallback = callback; } - - public boolean onTouch(View v, MotionEvent event) { - mCurrentView = v; - return false; - } } 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 dedbe5d..af5c72d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -218,9 +218,165 @@ public class PhoneStatusBarPolicy { R.drawable.stat_sys_roaming_cdma_0, R.drawable.stat_sys_roaming_cdma_0, R.drawable.stat_sys_roaming_cdma_0, - R.drawable.stat_sys_roaming_cdma_0 //83 + R.drawable.stat_sys_roaming_cdma_0, //83 + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0 //239 - // 128-255 Reserved + // 240-255 Reserved }; //***** Data connection icons diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml index 5ab6ee2..11a247a 100644 --- a/packages/VpnDialogs/res/layout/confirm.xml +++ b/packages/VpnDialogs/res/layout/confirm.xml @@ -18,7 +18,7 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="5mm"> + android:padding="3mm"> <ImageView android:id="@+id/icon" android:layout_width="@android:dimen/app_icon_size" diff --git a/packages/VpnDialogs/res/layout/manage.xml b/packages/VpnDialogs/res/layout/manage.xml index 330b8e3..3dcbb46 100644 --- a/packages/VpnDialogs/res/layout/manage.xml +++ b/packages/VpnDialogs/res/layout/manage.xml @@ -18,6 +18,7 @@ <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:padding="3mm" android:stretchColumns="0,1"> <TableRow> diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 4be00c5..b963b13 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -1668,14 +1668,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - // Back cancels action modes first. - if (mActionMode != null && keyCode == KeyEvent.KEYCODE_BACK) { - if (action == KeyEvent.ACTION_UP) { - mActionMode.finish(); - } - return true; - } - if (!isDestroyed()) { final Callback cb = getCallback(); final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) @@ -1684,6 +1676,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return true; } } + return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event) : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event); } @@ -1730,7 +1723,32 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } public boolean superDispatchKeyEvent(KeyEvent event) { - return super.dispatchKeyEvent(event); + if (super.dispatchKeyEvent(event)) { + return true; + } + + // Not handled by the view hierarchy, does the action bar want it + // to cancel out of something special? + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { + final int action = event.getAction(); + // Back cancels action modes first. + if (mActionMode != null) { + if (action == KeyEvent.ACTION_UP) { + mActionMode.finish(); + } + return true; + } + + // Next collapse any expanded action views. + if (mActionBar != null && mActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + mActionBar.collapseActionView(); + } + return true; + } + } + + return false; } public boolean superDispatchKeyShortcutEvent(KeyEvent event) { diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 6bb1f56..a0407b9 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -24,6 +24,7 @@ LOCAL_SHARED_LIBRARIES := \ libdl LOCAL_STATIC_LIBRARIES := \ + libcpustats \ libmedia_helper LOCAL_MODULE:= libaudioflinger diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index daf94f2..86d4cc3 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -52,6 +52,9 @@ #include <media/EffectsFactoryApi.h> #include <audio_effects/effect_visualizer.h> +#include <cpustats/ThreadCpuUsage.h> +// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds + // ---------------------------------------------------------------------------- @@ -1529,9 +1532,40 @@ bool AudioFlinger::MixerThread::threadLoop() uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; Vector< sp<EffectChain> > effectChains; +#ifdef DEBUG_CPU_USAGE + ThreadCpuUsage cpu; + const CentralTendencyStatistics& stats = cpu.statistics(); +#endif while (!exitPending()) { +#ifdef DEBUG_CPU_USAGE + cpu.sampleAndEnable(); + unsigned n = stats.n(); + // cpu.elapsed() is expensive, so don't call it every loop + if ((n & 127) == 1) { + long long elapsed = cpu.elapsed(); + if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) { + double perLoop = elapsed / (double) n; + double perLoop100 = perLoop * 0.01; + double mean = stats.mean(); + double stddev = stats.stddev(); + double minimum = stats.minimum(); + double maximum = stats.maximum(); + cpu.resetStatistics(); + LOGI("CPU usage over past %.1f secs (%u mixer loops at %.1f mean ms per loop):\n us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f", + elapsed * .000000001, n, perLoop * .000001, + mean * .001, + stddev * .001, + minimum * .001, + maximum * .001, + mean / perLoop100, + stddev / perLoop100, + minimum / perLoop100, + maximum / perLoop100); + } + } +#endif processConfigEvents(); mixerStatus = MIXER_IDLE; diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 9b09983..0eff776 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -502,77 +502,82 @@ void CameraService::Client::disconnect() { // ---------------------------------------------------------------------------- -// set the Surface that the preview will use -status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) { - LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); +static void disconnectWindow(const sp<ANativeWindow>& window) { + if (window != 0) { + status_t result = native_window_disconnect(window.get(), + NATIVE_WINDOW_API_CAMERA); + if (result != NO_ERROR) { + LOGW("native_window_disconnect failed: %s (%d)", strerror(-result), + result); + } + } +} + +status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder, + const sp<ANativeWindow>& window) { Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; - result = NO_ERROR; - // return if no change in surface. - sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0); if (binder == mSurface) { - return result; + return NO_ERROR; } - if (mSurface != 0) { - LOG1("clearing old preview surface %p", mSurface.get()); + if (window != 0) { + result = native_window_connect(window.get(), NATIVE_WINDOW_API_CAMERA); + if (result != NO_ERROR) { + LOGE("native_window_connect failed: %s (%d)", strerror(-result), + result); + return result; + } } - mSurface = binder; - mPreviewWindow = surface; - // If preview has been already started, register preview - // buffers now. + // If preview has been already started, register preview buffers now. if (mHardware->previewEnabled()) { - if (mPreviewWindow != 0) { - native_window_set_buffers_transform(mPreviewWindow.get(), - mOrientation); - result = mHardware->setPreviewWindow(mPreviewWindow); + if (window != 0) { + native_window_set_buffers_transform(window.get(), mOrientation); + result = mHardware->setPreviewWindow(window); } } + if (result == NO_ERROR) { + // Everything has succeeded. Disconnect the old window and remember the + // new window. + disconnectWindow(mPreviewWindow); + mSurface = binder; + mPreviewWindow = window; + } else { + // Something went wrong after we connected to the new window, so + // disconnect here. + disconnectWindow(window); + } + return result; } +// set the Surface that the preview will use +status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) { + LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); + + sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0); + sp<ANativeWindow> window(surface); + return setPreviewWindow(binder, window); +} + // set the SurfaceTexture that the preview will use status_t CameraService::Client::setPreviewTexture( const sp<ISurfaceTexture>& surfaceTexture) { LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(), getCallingPid()); - Mutex::Autolock lock(mLock); - status_t result = checkPidAndHardware(); - if (result != NO_ERROR) return result; - - // return if no change in surface. - // asBinder() is safe on NULL (returns NULL) - if (surfaceTexture->asBinder() == mSurface) { - return result; - } - if (mSurface != 0) { - LOG1("clearing old preview surface %p", mSurface.get()); - } - mSurface = surfaceTexture->asBinder(); + sp<IBinder> binder; + sp<ANativeWindow> window; if (surfaceTexture != 0) { - mPreviewWindow = new SurfaceTextureClient(surfaceTexture); - } else { - mPreviewWindow = 0; - } - - // If preview has been already started, set overlay or register preview - // buffers now. - if (mHardware->previewEnabled()) { - // XXX: What if the new preview window is 0? - if (mPreviewWindow != 0) { - native_window_set_buffers_transform(mPreviewWindow.get(), - mOrientation); - result = mHardware->setPreviewWindow(mPreviewWindow); - } + binder = surfaceTexture->asBinder(); + window = new SurfaceTextureClient(surfaceTexture); } - - return result; + return setPreviewWindow(binder, window); } // set the preview callback flag to affect how the received frames from diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 5e2d571..c5fefb8 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -161,6 +161,10 @@ private: int getOrientation(int orientation, bool mirror); + status_t setPreviewWindow( + const sp<IBinder>& binder, + const sp<ANativeWindow>& window); + // these are initialized in the constructor. sp<CameraService> mCameraService; // immutable after constructor sp<ICameraClient> mCameraClient; diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index b2fbcb1..c9fac81 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -120,29 +120,31 @@ static const int32_t keyCodeRotationMap[][4] = { static const size_t keyCodeRotationMapSize = sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]); -int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { +static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) { return rotateValueUsingRotationMap(keyCode, orientation, keyCodeRotationMap, keyCodeRotationMapSize); } -static const int32_t edgeFlagRotationMap[][4] = { - // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first - // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation - { AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT, - AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT }, - { AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP, - AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM }, - { AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT, - AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT }, - { AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM, - AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP }, -}; -static const size_t edgeFlagRotationMapSize = - sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]); +static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) { + float temp; + switch (orientation) { + case DISPLAY_ORIENTATION_90: + temp = *deltaX; + *deltaX = *deltaY; + *deltaY = -temp; + break; + + case DISPLAY_ORIENTATION_180: + *deltaX = -*deltaX; + *deltaY = -*deltaY; + break; -static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) { - return rotateValueUsingRotationMap(edgeFlag, orientation, - edgeFlagRotationMap, edgeFlagRotationMapSize); + case DISPLAY_ORIENTATION_270: + temp = *deltaX; + *deltaX = -*deltaY; + *deltaY = temp; + break; + } } static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) { @@ -1656,25 +1658,7 @@ void CursorInputMapper::sync(nsecs_t when) { orientation = DISPLAY_ORIENTATION_0; } - float temp; - switch (orientation) { - case DISPLAY_ORIENTATION_90: - temp = deltaX; - deltaX = deltaY; - deltaY = -temp; - break; - - case DISPLAY_ORIENTATION_180: - deltaX = -deltaX; - deltaY = -deltaY; - break; - - case DISPLAY_ORIENTATION_270: - temp = deltaX; - deltaX = -deltaY; - deltaY = temp; - break; - } + rotateDelta(orientation, &deltaX, &deltaY); } pointerProperties.clear(); @@ -3834,6 +3818,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, float deltaY = (currentPointer.y - lastPointer.y) * mLocked.pointerGestureYMovementScale; + rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY); mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY); // Move the pointer using a relative motion. @@ -3972,6 +3957,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, float deltaY = (currentPointer.y - lastPointer.y) * mLocked.pointerGestureYMovementScale; + rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY); mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY); // Move the pointer using a relative motion. @@ -4229,6 +4215,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, commonDeltaX *= mLocked.pointerGestureXMovementScale; commonDeltaY *= mLocked.pointerGestureYMovementScale; + + rotateDelta(mLocked.surfaceOrientation, &commonDeltaX, &commonDeltaY); mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); mPointerGesture.referenceGestureX += commonDeltaX; @@ -4236,32 +4224,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, } // Report gestures. - if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) { - // PRESS mode. -#if DEBUG_GESTURES - LOGD("Gestures: PRESS activeTouchId=%d," - "activeGestureId=%d, currentTouchPointerCount=%d", - activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount); -#endif - LOG_ASSERT(mPointerGesture.activeGestureId >= 0); - - mPointerGesture.currentGestureIdBits.clear(); - mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId); - mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0; - mPointerGesture.currentGestureProperties[0].clear(); - mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId; - mPointerGesture.currentGestureProperties[0].toolType = - AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; - mPointerGesture.currentGestureCoords[0].clear(); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, - mPointerGesture.referenceGestureX); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, - mPointerGesture.referenceGestureY); - mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); - } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { - // SWIPE mode. + if (mPointerGesture.currentGestureMode == PointerGesture::PRESS + || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) { + // PRESS or SWIPE mode. #if DEBUG_GESTURES - LOGD("Gestures: SWIPE activeTouchId=%d," + LOGD("Gestures: PRESS or SWIPE activeTouchId=%d," "activeGestureId=%d, currentTouchPointerCount=%d", activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount); #endif @@ -4355,10 +4322,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureIdBits.markBit(gestureId); mPointerGesture.currentGestureIdToIndex[gestureId] = i; - float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX) - * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX; - float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY) - * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY; + float deltaX = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX) + * mLocked.pointerGestureXZoomScale; + float deltaY = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY) + * mLocked.pointerGestureYZoomScale; + rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY); mPointerGesture.currentGestureProperties[i].clear(); mPointerGesture.currentGestureProperties[i].id = gestureId; @@ -4366,9 +4334,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER; mPointerGesture.currentGestureCoords[i].clear(); mPointerGesture.currentGestureCoords[i].setAxisValue( - AMOTION_EVENT_AXIS_X, x); + AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX); mPointerGesture.currentGestureCoords[i].setAxisValue( - AMOTION_EVENT_AXIS_Y, y); + AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY); mPointerGesture.currentGestureCoords[i].setAxisValue( AMOTION_EVENT_AXIS_PRESSURE, 1.0f); } diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 168b894..e9e66cb 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -87,8 +87,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -109,6 +111,8 @@ class BackupManagerService extends IBackupManager.Stub { // Name and current contents version of the full-backup manifest file static final String BACKUP_MANIFEST_FILENAME = "_manifest"; static final int BACKUP_MANIFEST_VERSION = 1; + static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n"; + static final int BACKUP_FILE_VERSION = 1; // How often we perform a backup pass. Privileged external callers can // trigger an immediate pass. @@ -1791,16 +1795,42 @@ class BackupManagerService extends IBackupManager.Stub { } } - // Set up the compression stage FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor()); + + // Set up the compression stage Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION); DeflaterOutputStream out = new DeflaterOutputStream(ofstream, deflater, true); - // !!! TODO: if using encryption, set up the encryption stage - // and emit the tar header stating the password salt. - PackageInfo pkg = null; try { + + // !!! TODO: if using encryption, set up the encryption stage + // and emit the tar header stating the password salt. + + // Write the global file header. All strings are UTF-8 encoded; lines end + // with a '\n' byte. Actual backup data begins immediately following the + // final '\n'. + // + // line 1: "ANDROID BACKUP" + // line 2: backup file format version, currently "1" + // line 3: compressed? "0" if not compressed, "1" if compressed. + // line 4: encryption salt? "-" if not encrypted, otherwise this + // line contains the encryption salt with which the user- + // supplied password is to be expanded, in hexadecimal. + StringBuffer headerbuf = new StringBuffer(256); + // !!! TODO: programmatically build the compressed / encryption salt fields + headerbuf.append(BACKUP_FILE_HEADER_MAGIC); + headerbuf.append("1\n1\n-\n"); + + try { + byte[] header = headerbuf.toString().getBytes("UTF-8"); + ofstream.write(header); + } catch (Exception e) { + // Should never happen! + Slog.e(TAG, "Unable to emit archive header", e); + return; + } + // Now back up the app data via the agent mechanism int N = packagesToBackup.size(); for (int i = 0; i < N; i++) { @@ -2176,7 +2206,46 @@ class BackupManagerService extends IBackupManager.Stub { mBytes = 0; byte[] buffer = new byte[32 * 1024]; FileInputStream rawInStream = new FileInputStream(mInputFile.getFileDescriptor()); - InflaterInputStream in = new InflaterInputStream(rawInStream); + + // First, parse out the unencrypted/uncompressed header + boolean compressed = false; + boolean encrypted = false; + final InputStream in; + + boolean okay = false; + final int headerLen = BACKUP_FILE_HEADER_MAGIC.length(); + byte[] streamHeader = new byte[headerLen]; + try { + int got; + if ((got = rawInStream.read(streamHeader, 0, headerLen)) == headerLen) { + byte[] magicBytes = BACKUP_FILE_HEADER_MAGIC.getBytes("UTF-8"); + if (Arrays.equals(magicBytes, streamHeader)) { + // okay, header looks good. now parse out the rest of the fields. + String s = readHeaderLine(rawInStream); + if (Integer.parseInt(s) == BACKUP_FILE_VERSION) { + // okay, it's a version we recognize + s = readHeaderLine(rawInStream); + compressed = (Integer.parseInt(s) != 0); + s = readHeaderLine(rawInStream); + if (!s.startsWith("-")) { + encrypted = true; + // TODO: parse out the salt here and process with the user pw + } + okay = true; + } else Slog.e(TAG, "Wrong header version: " + s); + } else Slog.e(TAG, "Didn't read the right header magic"); + } else Slog.e(TAG, "Only read " + got + " bytes of header"); + } catch (NumberFormatException e) { + Slog.e(TAG, "Can't parse restore data header"); + } + + if (!okay) { + Slog.e(TAG, "Invalid restore data; aborting."); + return; + } + + // okay, use the right stream layer based on compression + in = (compressed) ? new InflaterInputStream(rawInStream) : rawInStream; boolean didRestore; do { @@ -2184,6 +2253,8 @@ class BackupManagerService extends IBackupManager.Stub { } while (didRestore); if (DEBUG) Slog.v(TAG, "Done consuming input tarfile, total bytes=" + mBytes); + } catch (IOException e) { + Slog.e(TAG, "Unable to read restore input"); } finally { tearDownPipes(); tearDownAgent(mTargetApp); @@ -2207,6 +2278,16 @@ class BackupManagerService extends IBackupManager.Stub { } } + String readHeaderLine(InputStream in) throws IOException { + int c; + StringBuffer buffer = new StringBuffer(80); + while ((c = in.read()) >= 0) { + if (c == '\n') break; // consume and discard the newlines + buffer.append((char)c); + } + return buffer.toString(); + } + boolean restoreOneFile(InputStream instream, byte[] buffer) { FileMetadata info; try { diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 18d393f..2597978 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -35,6 +35,7 @@ import org.xmlpull.v1.XmlSerializer; import android.app.ActivityManagerNative; import android.app.AlertDialog; +import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -47,6 +48,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -160,6 +162,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Ongoing notification private final NotificationManager mNotificationManager; + private final KeyguardManager mKeyguardManager; private final Notification mImeSwitcherNotification; private final PendingIntent mImeSwitchPendingIntent; private final boolean mShowOngoingImeSwitcherForPhones; @@ -520,6 +523,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }); + mKeyguardManager = (KeyguardManager) + mContext.getSystemService(Context.KEYGUARD_SERVICE); mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); mImeSwitcherNotification = new Notification(); @@ -1632,19 +1637,27 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public boolean setAdditionalInputMethodSubtypes(IBinder token, InputMethodSubtype[] subtypes) { - if (token == null || mCurToken != token) { - return false; - } - if (subtypes == null || subtypes.length == 0) return false; + public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) { + // By this IPC call, only a process which shares the same uid with the IME can add + // additional input method subtypes to the IME. + if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return false; synchronized (mMethodMap) { - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + final InputMethodInfo imi = mMethodMap.get(imiId); if (imi == null) return false; - final int N = subtypes.length; - mFileManager.addInputMethodSubtypes(imi, subtypes); - buildInputMethodListLocked(mMethodList, mMethodMap); - return true; + final PackageManager pm = mContext.getPackageManager(); + final String[] packageInfos = pm.getPackagesForUid(Binder.getCallingUid()); + if (packageInfos != null) { + final int packageNum = packageInfos.length; + for (int i = 0; i < packageNum; ++i) { + if (packageInfos[i].equals(imi.getPackageName())) { + mFileManager.addInputMethodSubtypes(imi, subtypes); + buildInputMethodListLocked(mMethodList, mMethodMap); + return true; + } + } + } } + return false; } private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) { @@ -2118,7 +2131,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }); - if (showSubtypes) { + if (showSubtypes && !(mKeyguardManager.isKeyguardLocked() + && mKeyguardManager.isKeyguardSecure())) { mDialogBuilder.setPositiveButton( com.android.internal.R.string.configure_input_methods, new DialogInterface.OnClickListener() { diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 94465fd..7f61c635 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -1339,7 +1339,11 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC String state = mVolumeStates.get(mountPoint); if (state == null) { Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume"); - throw new IllegalArgumentException(); + if (SystemProperties.get("vold.encrypt_progress").length() != 0) { + state = Environment.MEDIA_REMOVED; + } else { + throw new IllegalArgumentException(); + } } return state; diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 5f0922e..7112553 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -35,8 +35,8 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiStateMachine; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiWatchdogStateMachine; import android.net.wifi.WifiConfiguration.KeyMgmt; -import android.net.wifi.WifiWatchdogService; import android.net.wifi.WpsConfiguration; import android.net.wifi.WpsResult; import android.net.ConnectivityManager; @@ -343,7 +343,7 @@ public class WifiService extends IWifiManager.Stub { * Protected by mWifiStateTracker lock. */ private final WorkSource mTmpWorkSource = new WorkSource(); - private WifiWatchdogService mWifiWatchdogService; + private WifiWatchdogStateMachine mWifiWatchdogStateMachine; WifiService(Context context) { mContext = context; @@ -434,8 +434,9 @@ public class WifiService extends IWifiManager.Stub { (wifiEnabled ? "enabled" : "disabled")); setWifiEnabled(wifiEnabled); - //TODO: as part of WWS refactor, create only when needed - mWifiWatchdogService = new WifiWatchdogService(mContext); + mWifiWatchdogStateMachine = WifiWatchdogStateMachine. + makeWifiWatchdogStateMachine(mContext); + } private boolean testAndClearWifiSavedState() { @@ -1162,8 +1163,8 @@ public class WifiService extends IWifiManager.Stub { mLocks.dump(pw); pw.println(); - pw.println("WifiWatchdogService dump"); - mWifiWatchdogService.dump(pw); + pw.println("WifiWatchdogStateMachine dump"); + mWifiWatchdogStateMachine.dump(pw); } private class WifiLock extends DeathRecipient { diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index f99951fa..bb9d15b 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -127,13 +127,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private int mHandledFeedbackTypes = 0; - private boolean mIsEnabled; + private boolean mIsAccessibilityEnabled; + + private boolean mIsTouchExplorationRequested; private AccessibilityInputFilter mInputFilter; private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>(); - private boolean mHasInputFilter; + private boolean mIsTouchExplorationEnabled; private final WindowManagerService mWindowManagerService; @@ -230,16 +232,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) { synchronized (mLock) { populateAccessibilityServiceListLocked(); - // get the accessibility enabled setting on boot - mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(), + // get accessibility enabled setting on boot + mIsAccessibilityEnabled = Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1; - // if accessibility is enabled inform our clients we are on - if (mIsEnabled) { - updateClientsLocked(); + if (mIsAccessibilityEnabled) { + sendAccessibilityEnabledToClientsLocked(); } - manageServicesLocked(); + + // get touch exploration enabled setting on boot + mIsTouchExplorationRequested = Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1; + updateTouchExplorationEnabledLocked(); } return; @@ -264,29 +271,48 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private void registerSettingsContentObservers() { ContentResolver contentResolver = mContext.getContentResolver(); - Uri enabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED); - contentResolver.registerContentObserver(enabledUri, false, + Uri accessibilityEnabledUri = Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_ENABLED); + contentResolver.registerContentObserver(accessibilityEnabledUri, false, new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); synchronized (mLock) { - mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(), + mIsAccessibilityEnabled = Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1; - if (mIsEnabled) { + if (mIsAccessibilityEnabled) { manageServicesLocked(); } else { unbindAllServicesLocked(); } - updateClientsLocked(); + sendAccessibilityEnabledToClientsLocked(); } } }); - Uri providersUri = + Uri touchExplorationRequestedUri = Settings.Secure.getUriFor( + Settings.Secure.TOUCH_EXPLORATION_REQUESTED); + contentResolver.registerContentObserver(touchExplorationRequestedUri, false, + new ContentObserver(new Handler()) { + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + + synchronized (mLock) { + mIsTouchExplorationRequested = Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1; + updateTouchExplorationEnabledLocked(); + } + } + }); + + Uri accessibilityServicesUri = Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); - contentResolver.registerContentObserver(providersUri, false, + contentResolver.registerContentObserver(accessibilityServicesUri, false, new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { @@ -312,7 +338,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } }, 0); - return mIsEnabled; + return mIsAccessibilityEnabled; } } @@ -602,7 +628,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub service.linkToOwnDeath(); mServices.add(service); mComponentNameToServiceMap.put(service.mComponentName, service); - updateInputFilterLocked(); + updateTouchExplorationEnabledLocked(); } catch (RemoteException e) { /* do nothing */ } @@ -622,7 +648,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mComponentNameToServiceMap.remove(service.mComponentName); mHandler.removeMessages(service.mId); service.unlinkToOwnDeath(); - updateInputFilterLocked(); + updateTouchExplorationEnabledLocked(); return removed; } @@ -727,7 +753,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Set<ComponentName> enabledServices) { Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap; - boolean isEnabled = mIsEnabled; + boolean isEnabled = mIsAccessibilityEnabled; for (int i = 0, count = installedServices.size(); i < count; i++) { AccessibilityServiceInfo installedService = installedServices.get(i); @@ -741,7 +767,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub service = new Service(componentName, installedService, false); } service.bind(); - } else if (!enabledServices.contains(componentName)) { + } else { if (service != null) { service.unbind(); } @@ -757,10 +783,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub /** * Updates the state of {@link android.view.accessibility.AccessibilityManager} clients. */ - private void updateClientsLocked() { + private void sendAccessibilityEnabledToClientsLocked() { for (int i = 0, count = mClients.size(); i < count; i++) { try { - mClients.get(i).setEnabled(mIsEnabled); + mClients.get(i).setEnabled(mIsAccessibilityEnabled); } catch (RemoteException re) { mClients.remove(i); count--; @@ -770,29 +796,48 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } /** - * Updates the input filter state. The filter is enabled if accessibility - * is enabled and there is at least one accessibility service providing - * spoken feedback. + * Sends the touch exploration state to clients. */ - private void updateInputFilterLocked() { - if (mIsEnabled) { - final boolean hasSpokenFeedbackServices = !getEnabledAccessibilityServiceList( - AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty(); - if (hasSpokenFeedbackServices) { - if (mHasInputFilter) { - return; + private void sendTouchExplorationEnabledToClientsLocked() { + for (int i = 0, count = mClients.size(); i < count; i++) { + try { + mClients.get(i).setTouchExplorationEnabled(mIsTouchExplorationEnabled); + } catch (RemoteException re) { + mClients.remove(i); + count--; + i--; + } + } + } + + /** + * Updates the touch exploration state. Touch exploration is enabled if it + * is requested, accessibility is on and there is at least one enabled + * accessibility service providing spoken feedback. + */ + private void updateTouchExplorationEnabledLocked() { + if (mIsAccessibilityEnabled && mIsTouchExplorationRequested) { + final boolean hasSpeakingServicesEnabled = !getEnabledAccessibilityServiceList( + AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty(); + if (!mIsTouchExplorationEnabled) { + if (!hasSpeakingServicesEnabled) { + return; } if (mInputFilter == null) { mInputFilter = new AccessibilityInputFilter(mContext); } mWindowManagerService.setInputFilter(mInputFilter); - mHasInputFilter = true; + mIsTouchExplorationEnabled = true; + sendTouchExplorationEnabledToClientsLocked(); + return; + } else if (hasSpeakingServicesEnabled) { return; } } - if (mHasInputFilter) { + if (mIsTouchExplorationEnabled) { mWindowManagerService.setInputFilter(null); - mHasInputFilter = false; + mIsTouchExplorationEnabled = false; + sendTouchExplorationEnabledToClientsLocked(); } } @@ -935,9 +980,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) { + public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) + throws RemoteException { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + mSecurityPolicy.enforceCanRetrieveWindowContent(this); final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this); if (!permissionGranted) { return null; @@ -975,15 +1022,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow( - String text) { + String text) throws RemoteException { return findAccessibilityNodeInfosByViewText(text, mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID); } public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text, - int accessibilityWindowId, int accessibilityViewId) { + int accessibilityWindowId, int accessibilityViewId) throws RemoteException { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + mSecurityPolicy.enforceCanRetrieveWindowContent(this); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId); if (!permissionGranted) { @@ -1026,9 +1074,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId( - int accessibilityWindowId, int accessibilityViewId) { + int accessibilityWindowId, int accessibilityViewId) throws RemoteException { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + mSecurityPolicy.enforceCanRetrieveWindowContent(this); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId); if (!permissionGranted) { @@ -1199,6 +1248,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return service.mCanRetrieveScreenContent; } + public void enforceCanRetrieveWindowContent(Service service) throws RemoteException { + // This happens due to incorrect registration so make it apparent. + if (!canRetrieveWindowContent(service)) { + Slog.e(LOG_TAG, "Accessibility serivce " + service.mComponentName + " does not " + + "declare android:canRetrieveWindowContent."); + throw new RemoteException(); + } + } + private boolean isRetrievalAllowingWindow(int windowId) { return (mRetrievalAlowingWindowId == windowId); } diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index dbd9474..5a3a55d 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -116,9 +116,6 @@ public class TouchExplorer implements Explorer { // which would perform a click and tapping and holding a long press. private final int mTouchExplorationTapSlop; - // Context handle for accessing resources. - private final Context mContext; - // The InputFilter this tracker is associated with i.e. the filter // which delegates event processing to this touch explorer. private final InputFilter mInputFilter; @@ -161,7 +158,6 @@ public class TouchExplorer implements Explorer { ViewConfiguration.get(context).getScaledTouchExplorationTapSlop(); mDraggingDistance = mTouchExplorationTapSlop * COEFFICIENT_DRAGGING_DISTANCE; mPointerTracker = new PointerTracker(context); - mContext = context; mHandler = new Handler(context.getMainLooper()); mSendHoverDelayed = new SendHoverDelayed(); mAccessibilityManager = AccessibilityManager.getInstance(context); @@ -216,7 +212,8 @@ public class TouchExplorer implements Explorer { // Send a hover for every finger down so the user gets feedback // where she is currently touching. mSendHoverDelayed.forceSendAndRemove(); - final int pointerIdBits = (1 << event.getActionIndex()); + final int pointerIndex = event.getActionIndex(); + final int pointerIdBits = (1 << event.getPointerId(pointerIndex)); mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags, DELAY_SEND_HOVER_MOVE); } break; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index f546cf1..94af46d 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3610,8 +3610,10 @@ public final class ActivityManagerService extends ActivityManagerNative String processName = app.processName; try { - thread.asBinder().linkToDeath(new AppDeathRecipient( - app, pid, thread), 0); + AppDeathRecipient adr = new AppDeathRecipient( + app, pid, thread); + thread.asBinder().linkToDeath(adr, 0); + app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(); startProcessLocked(app, "link fail", processName); @@ -3687,6 +3689,7 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, "Exception thrown during bind!", e); app.resetPackageList(); + app.unlinkDeathRecipient(); startProcessLocked(app, "bind fail", processName); return false; } @@ -8885,25 +8888,59 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println("Applications Graphics Acceleration Info:"); pw.println("Uptime: " + uptime + " Realtime: " + realtime); - String callArgs[] = {"graphics"}; for (int i = procs.size() - 1 ; i >= 0 ; i--) { ProcessRecord r = procs.get(i); if (r.thread != null) { pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **"); pw.flush(); try { - TransferPipe.goDump(r.thread.asBinder(), fd, callArgs); + TransferPipe tp = new TransferPipe(); + try { + r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args); + tp.go(fd); + } finally { + tp.kill(); + } } catch (IOException e) { - pw.println("Failure: " + e); + pw.println("Failure while dumping the app: " + r); pw.flush(); } catch (RemoteException e) { - pw.println("Got RemoteException!"); + pw.println("Got a RemoteException while dumping the app " + r); pw.flush(); } } } } + final static class MemItem { + final String label; + final long pss; + + public MemItem(String _label, long _pss) { + label = _label; + pss = _pss; + } + } + + final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) { + Collections.sort(items, new Comparator<MemItem>() { + @Override + public int compare(MemItem lhs, MemItem rhs) { + if (lhs.pss < rhs.pss) { + return 1; + } else if (lhs.pss > rhs.pss) { + return -1; + } + return 0; + } + }); + + for (int i=0; i<items.size(); i++) { + MemItem mi = items.get(i); + pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label); + } + } + final void dumpApplicationMemoryUsage(FileDescriptor fd, PrintWriter pw, String prefix, String[] args) { ArrayList<ProcessRecord> procs = collectProcesses(pw, args); @@ -8923,6 +8960,11 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println("Applications Memory Usage (kB):"); pw.println("Uptime: " + uptime + " Realtime: " + realtime); } + + ArrayList<MemItem> procMems = new ArrayList<MemItem>(); + long nativePss=0, dalvikPss=0, otherPss=0; + long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; + for (int i = procs.size() - 1 ; i >= 0 ; i--) { ProcessRecord r = procs.get(i); if (r.thread != null) { @@ -8930,18 +8972,47 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **"); pw.flush(); } + Debug.MemoryInfo mi = null; try { - TransferPipe.goDump(r.thread.asBinder(), fd, args); - } catch (IOException e) { - pw.println("Failure: " + e); - pw.flush(); + mi = r.thread.dumpMemInfo(fd, args); } catch (RemoteException e) { if (!isCheckinRequest) { pw.println("Got RemoteException!"); pw.flush(); } } + if (!isCheckinRequest && mi != null) { + procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")", + mi.getTotalPss())); + + nativePss += mi.nativePss; + dalvikPss += mi.dalvikPss; + otherPss += mi.otherPss; + for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) { + long mem = mi.getOtherPss(j); + miscPss[j] += mem; + otherPss -= mem; + } + } + } + } + + if (!isCheckinRequest && procs.size() > 1) { + ArrayList<MemItem> catMems = new ArrayList<MemItem>(); + + catMems.add(new MemItem("Native", nativePss)); + catMems.add(new MemItem("Dalvik", dalvikPss)); + catMems.add(new MemItem("Unknown", otherPss)); + for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) { + catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j])); } + + pw.println(); + pw.println("Total PSS by process:"); + dumpMemItems(pw, " ", procMems); + pw.println(); + pw.println("Total PSS by category:"); + dumpMemItems(pw, " ", catMems); } } @@ -9142,6 +9213,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.notResponding = false; app.resetPackageList(); + app.unlinkDeathRecipient(); app.thread = null; app.forcingToForeground = null; app.foregroundServices = false; @@ -9259,7 +9331,6 @@ public final class ActivityManagerService extends ActivityManagerNative // This app is persistent, so we need to keep its record around. // If it is not already on the pending app list, add it there // and start a new process for it. - app.thread = null; app.forcingToForeground = null; app.foregroundServices = false; if (mPersistentStartingProcesses.indexOf(app) < 0) { diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index 99830f9..9e597aa 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -73,6 +73,7 @@ class ProcessRecord { int adjSeq; // Sequence id for identifying oom_adj assignment cycles int lruSeq; // Sequence id for identifying LRU update cycles CompatibilityInfo compat; // last used compatibility mode + IBinder.DeathRecipient deathRecipient; // Who is watching for the death. ComponentName instrumentationClass;// class installed to instrument app ApplicationInfo instrumentationInfo; // the application being instrumented String instrumentationProfileFile; // where to save profiling @@ -297,6 +298,13 @@ class ProcessRecord { } } + public void unlinkDeathRecipient() { + if (deathRecipient != null && thread != null) { + thread.asBinder().unlinkToDeath(deathRecipient, 0); + } + deathRecipient = null; + } + public String toShortString() { if (shortStringName != null) { return shortStringName; diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 0c78fe7..435c394 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -22,6 +22,7 @@ import static android.Manifest.permission.MANAGE_APP_TOKENS; import static android.Manifest.permission.MANAGE_NETWORK_POLICY; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.READ_PHONE_STATE; +import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED; @@ -174,10 +175,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Current policy for network templates. */ private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList(); + /** Current derived network rules for ifaces. */ + private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap(); /** Current policy for each UID. */ private SparseIntArray mUidPolicy = new SparseIntArray(); - /** Current derived network rules for each UID. */ + /** Current derived rules for each UID. */ private SparseIntArray mUidRules = new SparseIntArray(); /** Set of ifaces that are metered. */ @@ -199,8 +202,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // TODO: keep whitelist of system-critical services that should never have // rules enforced, such as system, phone, and radio UIDs. - // TODO: watch for package added broadcast to catch new UIDs. - public NetworkPolicyManagerService(Context context, IActivityManager activityManager, IPowerManager powerManager, INetworkStatsService networkStats, INetworkManagementService networkManagement) { @@ -242,7 +243,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { synchronized (mRulesLock) { // read policy from disk readPolicyLocked(); - updateNotificationsLocked(); } updateScreenOn(); @@ -268,9 +268,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); - // listen for uid removal to clean policy - final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED); - mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler); + // listen for package/uid changes to update policy + final IntentFilter packageFilter = new IntentFilter(); + packageFilter.addAction(ACTION_PACKAGE_ADDED); + packageFilter.addAction(ACTION_UID_REMOVED); + packageFilter.addDataScheme("package"); + mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler); // listen for stats update events final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); @@ -331,17 +334,28 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() { + private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // on background handler thread, and UID_REMOVED is protected - // broadcast. + // on background handler thread, and PACKAGE_ADDED and UID_REMOVED + // are protected broadcasts. + + final String action = intent.getAction(); final int uid = intent.getIntExtra(EXTRA_UID, 0); synchronized (mRulesLock) { - // remove any policy and update rules to clean up - mUidPolicy.delete(uid); - updateRulesForUidLocked(uid); - writePolicyLocked(); + if (ACTION_PACKAGE_ADDED.equals(action)) { + // update rules for UID, since it might be subject to + // global background data policy. + if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid); + updateRulesForUidLocked(uid); + + } else if (ACTION_UID_REMOVED.equals(action)) { + // remove any policy and update rules to clean up. + if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid); + mUidPolicy.delete(uid); + updateRulesForUidLocked(uid); + writePolicyLocked(); + } } } }; @@ -396,8 +410,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // TODO: when switching to kernel notifications, compute next future // cycle boundary to recompute notifications. - // examine stats for each policy defined - for (NetworkPolicy policy : mNetworkPolicy) { + // examine stats for each active policy + for (NetworkPolicy policy : mNetworkRules.keySet()) { final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; @@ -424,6 +438,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { cancelNotification(policy, TYPE_WARNING); } } + + } + + // clear notifications for non-active policies + for (NetworkPolicy policy : mNetworkPolicy) { + if (!mNetworkRules.containsKey(policy)) { + cancelNotification(policy, TYPE_WARNING); + cancelNotification(policy, TYPE_LIMIT); + } } } @@ -531,7 +554,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // permission above. synchronized (mRulesLock) { ensureActiveMobilePolicyLocked(); - updateIfacesLocked(); + updateNetworkRulesLocked(); + updateNotificationsLocked(); } } }; @@ -541,7 +565,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * {@link NetworkPolicy} that need to be enforced. When matches found, set * remaining quota based on usage cycle and historical stats. */ - private void updateIfacesLocked() { + private void updateNetworkRulesLocked() { if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); final NetworkState[] states; @@ -565,7 +589,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // build list of rules and ifaces to enforce them against - final HashMap<NetworkPolicy, String[]> rules = Maps.newHashMap(); + mNetworkRules.clear(); final ArrayList<String> ifaceList = Lists.newArrayList(); for (NetworkPolicy policy : mNetworkPolicy) { @@ -580,7 +604,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (ifaceList.size() > 0) { final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); - rules.put(policy, ifaces); + mNetworkRules.put(policy, ifaces); } } @@ -596,8 +620,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // apply each policy that we found ifaces for; compute remaining data // based on current cycle and historical stats, and push to kernel. - for (NetworkPolicy policy : rules.keySet()) { - final String[] ifaces = rules.get(policy); + for (NetworkPolicy policy : mNetworkRules.keySet()) { + final String[] ifaces = mNetworkRules.get(policy); final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; @@ -670,17 +694,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (!mobileDefined) { Slog.i(TAG, "no policy for active mobile network; generating default policy"); - // default mobile policy has combined 4GB warning, and assume usage - // cycle starts today today. + // build default mobile policy, and assume usage cycle starts today + final long warningBytes = mContext.getResources().getInteger( + com.android.internal.R.integer.config_networkPolicyDefaultWarning) + * MB_IN_BYTES; - // TODO: move this policy definition to overlay or secure setting final Time time = new Time(Time.TIMEZONE_UTC); time.setToNow(); final int cycleDay = time.monthDay; final NetworkTemplate template = buildTemplateMobileAll(subscriberId); - mNetworkPolicy.add( - new NetworkPolicy(template, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED)); + mNetworkPolicy.add(new NetworkPolicy(template, cycleDay, warningBytes, LIMIT_DISABLED)); writePolicyLocked(); } } @@ -859,7 +883,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mNetworkPolicy.add(policy); } - updateIfacesLocked(); + updateNetworkRulesLocked(); updateNotificationsLocked(); writePolicyLocked(); } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 7ec6b81..6cc01f4 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -60,6 +60,7 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.INetworkManagementService; +import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; @@ -112,6 +113,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final TrustedTime mTime; private final NetworkStatsSettings mSettings; + private final PowerManager.WakeLock mWakeLock; + private IConnectivityManager mConnManager; // @VisibleForTesting @@ -191,6 +194,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mTime = checkNotNull(time, "missing TrustedTime"); mSettings = checkNotNull(settings, "missing NetworkStatsSettings"); + final PowerManager powerManager = (PowerManager) context.getSystemService( + Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); @@ -408,7 +415,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // on background handler thread, and verified CONNECTIVITY_INTERNAL // permission above. synchronized (mStatsLock) { - updateIfacesLocked(); + mWakeLock.acquire(); + try { + updateIfacesLocked(); + } finally { + mWakeLock.release(); + } } } }; @@ -419,8 +431,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // on background handler thread, and verified UPDATE_DEVICE_STATS // permission above. synchronized (mStatsLock) { - // TODO: acquire wakelock while performing poll - performPollLocked(true, false); + mWakeLock.acquire(); + try { + performPollLocked(true, false); + } finally { + mWakeLock.release(); + } } } }; @@ -433,7 +449,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int uid = intent.getIntExtra(EXTRA_UID, 0); synchronized (mStatsLock) { // TODO: perform one last stats poll for UID - removeUidLocked(uid); + mWakeLock.acquire(); + try { + removeUidLocked(uid); + } finally { + mWakeLock.release(); + } } } }; diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index 3139798..c80cd0a 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -473,10 +473,7 @@ public class UsbDeviceManager { case MSG_SET_CURRENT_FUNCTION: String function = (String)msg.obj; boolean makeDefault = (msg.arg1 == 1); - if (makeDefault) { - if (function == null) { - throw new NullPointerException(); - } + if (function != null && makeDefault) { if (mAdbEnabled) { function = addFunction(function, UsbManager.USB_FUNCTION_ADB); } diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index 118cd55..8146fca 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -51,6 +51,8 @@ class DragState { float mCurrentX, mCurrentY; float mThumbOffsetX, mThumbOffsetY; InputChannel mServerChannel, mClientChannel; + InputApplicationHandle mDragApplicationHandle; + InputWindowHandle mDragWindowHandle; WindowState mTargetWindow; ArrayList<WindowState> mNotifiedWindows; boolean mDragInProgress; @@ -91,6 +93,38 @@ class DragState { mService.mInputManager.registerInputChannel(mServerChannel, null); InputQueue.registerInputChannel(mClientChannel, mService.mDragInputHandler, mService.mH.getLooper().getQueue()); + + mDragApplicationHandle = new InputApplicationHandle(null); + mDragApplicationHandle.name = "drag"; + mDragApplicationHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + + mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null); + mDragWindowHandle.name = "drag"; + mDragWindowHandle.inputChannel = mServerChannel; + mDragWindowHandle.layer = getDragLayerLw(); + mDragWindowHandle.layoutParamsFlags = 0; + mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; + mDragWindowHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + mDragWindowHandle.visible = true; + mDragWindowHandle.canReceiveKeys = false; + mDragWindowHandle.hasFocus = true; + mDragWindowHandle.hasWallpaper = false; + mDragWindowHandle.paused = false; + mDragWindowHandle.ownerPid = Process.myPid(); + mDragWindowHandle.ownerUid = Process.myUid(); + mDragWindowHandle.inputFeatures = 0; + mDragWindowHandle.scaleFactor = 1.0f; + + // The drag window cannot receive new touches. + mDragWindowHandle.touchableRegion.setEmpty(); + + // The drag window covers the entire display + mDragWindowHandle.frameLeft = 0; + mDragWindowHandle.frameTop = 0; + mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth(); + mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight(); } } diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 08a3560..12ef238 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -42,10 +42,6 @@ final class InputMonitor { // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; - // Fake handles for the drag surface, lazily initialized. - private InputApplicationHandle mDragApplicationHandle; - private InputWindowHandle mDragWindowHandle; - // Array of window handles to provide to the input dispatcher. private InputWindowHandle[] mInputWindowHandles; private int mInputWindowHandleCount; @@ -121,44 +117,6 @@ final class InputMonitor { return 0; // abort dispatching } - private void addDragInputWindowLw() { - if (mDragWindowHandle == null) { - mDragApplicationHandle = new InputApplicationHandle(null); - mDragApplicationHandle.name = "drag"; - mDragApplicationHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - - mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null); - mDragWindowHandle.name = "drag"; - mDragWindowHandle.layoutParamsFlags = 0; - mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; - mDragWindowHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - mDragWindowHandle.visible = true; - mDragWindowHandle.canReceiveKeys = false; - mDragWindowHandle.hasFocus = true; - mDragWindowHandle.hasWallpaper = false; - mDragWindowHandle.paused = false; - mDragWindowHandle.ownerPid = Process.myPid(); - mDragWindowHandle.ownerUid = Process.myUid(); - mDragWindowHandle.inputFeatures = 0; - mDragWindowHandle.scaleFactor = 1.0f; - - // The drag window cannot receive new touches. - mDragWindowHandle.touchableRegion.setEmpty(); - } - - mDragWindowHandle.layer = mService.mDragState.getDragLayerLw(); - - // The drag window covers the entire display - mDragWindowHandle.frameLeft = 0; - mDragWindowHandle.frameTop = 0; - mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth(); - mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight(); - - addInputWindowHandleLw(mDragWindowHandle); - } - private void addInputWindowHandleLw(InputWindowHandle windowHandle) { if (mInputWindowHandles == null) { mInputWindowHandles = new InputWindowHandle[16]; @@ -202,7 +160,7 @@ final class InputMonitor { if (WindowManagerService.DEBUG_DRAG) { Log.d(WindowManagerService.TAG, "Inserting drag window"); } - addDragInputWindowLw(); + addInputWindowHandleLw(mService.mDragState.mDragWindowHandle); } final int N = windows.size(); @@ -429,4 +387,4 @@ final class InputMonitor { private void updateInputDispatchModeLw() { mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen); } -}
\ No newline at end of file +} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b0881a4..680814c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1551,8 +1551,18 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) * Dump SurfaceFlinger global state */ - snprintf(buffer, SIZE, "SurfaceFlinger global state\n"); + snprintf(buffer, SIZE, "SurfaceFlinger global state:\n"); result.append(buffer); + + const GLExtensions& extensions(GLExtensions::getInstance()); + snprintf(buffer, SIZE, "GLES: %s, %s, %s\n", + extensions.getVendor(), + extensions.getRenderer(), + extensions.getVersion()); + result.append(buffer); + snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension()); + result.append(buffer); + mWormholeRegion.dump(result, "WormholeRegion"); const DisplayHardware& hw(graphicPlane(0).displayHardware()); snprintf(buffer, SIZE, diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java index 302a2d6..1234bfd 100644 --- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java @@ -542,6 +542,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase { public void setEnabled(boolean enabled) { mIsEnabled = enabled; } + + public void setTouchExplorationEnabled(boolean enabled) { + } } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 66120a1..f7e0c66 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -61,7 +61,7 @@ public class TelephonyManager { /** @hide */ public TelephonyManager(Context context) { if (sContext == null) { - sContext = context; + sContext = context.getApplicationContext(); sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java index 8427d14..f0d2fba 100644 --- a/telephony/java/com/android/internal/telephony/BaseCommands.java +++ b/telephony/java/com/android/internal/telephony/BaseCommands.java @@ -857,22 +857,28 @@ public abstract class BaseCommands implements CommandsInterface { */ public static int getLteOnCdmaModeStatic() { int retVal; - String productType; - - Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine); - if (matcher.find()) { - productType = matcher.group(1); - if (sLteOnCdmaProductType.equals(productType)) { - retVal = Phone.LTE_ON_CDMA_TRUE; + int curVal; + String productType = ""; + + curVal = SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE, + Phone.LTE_ON_CDMA_UNKNOWN); + retVal = curVal; + if (retVal == Phone.LTE_ON_CDMA_UNKNOWN) { + Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine); + if (matcher.find()) { + productType = matcher.group(1); + if (sLteOnCdmaProductType.equals(productType)) { + retVal = Phone.LTE_ON_CDMA_TRUE; + } else { + retVal = Phone.LTE_ON_CDMA_FALSE; + } } else { retVal = Phone.LTE_ON_CDMA_FALSE; } - } else { - retVal = Phone.LTE_ON_CDMA_FALSE; - productType = ""; } - Log.d(LOG_TAG, "getLteOnCdmaMode=" + retVal + " product_type='" + productType + + Log.d(LOG_TAG, "getLteOnCdmaMode=" + retVal + " curVal=" + curVal + + " product_type='" + productType + "' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'"); return retVal; } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 60cf9b7..abb4523 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -79,6 +79,15 @@ public interface TelephonyProperties */ static final String PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE = "telephony.lteOnCdmaProductType"; + /** + * The contents of this property is the one of {@link Phone#LTE_ON_CDMA_TRUE} or + * {@link Phone#LTE_ON_CDMA_FALSE}. If absent the value will assumed to be false + * and the {@see #PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE} will be used to determine its + * final value which could also be {@link Phone#LTE_ON_CDMA_FALSE}. + * {@see BaseCommands#getLteOnCdmaMode()} + */ + static final String PROPERTY_LTE_ON_CDMA_DEVICE = "telephony.lteOnCdmaDevice"; + static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type"; //****** SIM Card diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml index d438b2c..ed91c49 100644 --- a/tests/BiDiTests/res/layout/basic.xml +++ b/tests/BiDiTests/res/layout/basic.xml @@ -40,7 +40,7 @@ android:textSize="32dip" android:text="@string/textview_text" /> - + <EditText android:id="@+id/edittext" android:layout_height="wrap_content" android:layout_width="match_parent" @@ -49,6 +49,40 @@ </LinearLayout> + <Button android:id="@+id/button_alert_dialog" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="@string/button_alert_dialog_text" + android:textSize="32dip" + /> + </LinearLayout> + + <LinearLayout + android:layout_width="600dip" + android:layout_height="128dip" + android:layout_gravity="center_vertical" + android:orientation="horizontal" + style="@android:style/Widget.Holo.Spinner" + > + <LinearLayout + android:layout_width="0dip" + android:layout_weight="1" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:orientation="vertical" + > + <TextView + android:id="@+id/spinner_line_1" + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_weight="1" + android:textSize="16dip" + android:singleLine="true" + android:ellipsize="end" + android:gravity="left|center_vertical" + android:text="@string/button_text" + /> + </LinearLayout> </LinearLayout> -</FrameLayout>
\ No newline at end of file +</FrameLayout> diff --git a/tests/BiDiTests/res/layout/canvas2.xml b/tests/BiDiTests/res/layout/canvas2.xml new file mode 100644 index 0000000..b3e038f --- /dev/null +++ b/tests/BiDiTests/res/layout/canvas2.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/canvas2" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <LinearLayout + xmlns:local="http://schemas.android.com/apk/res/com.android.bidi" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <TextView + android:text="@string/ltr" + android:textSize="40dip" + android:gravity="center" + android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + + <com.android.bidi.BiDiTestViewDrawText + local:text="@string/ltr" + android:layout_width="fill_parent" + android:layout_height="64dp" /> + + <TextView + android:text="@string/rtl" + android:textSize="40dip" + android:gravity="center" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> + + <com.android.bidi.BiDiTestViewDrawText + local:text="@string/rtl" + android:layout_width="fill_parent" + android:layout_height="64dp" /> + + <TextView + android:text="@string/composing" + android:textSize="40dip" + android:gravity="center" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> + + <com.android.bidi.BiDiTestViewDrawText + local:text="@string/composing" + android:layout_width="fill_parent" + android:layout_height="64dp" /> + + </LinearLayout> + +</FrameLayout>
\ No newline at end of file diff --git a/tests/BiDiTests/res/values/attrs.xml b/tests/BiDiTests/res/values/attrs.xml new file mode 100644 index 0000000..7f8a1d8 --- /dev/null +++ b/tests/BiDiTests/res/values/attrs.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <declare-styleable name="DrawTextTestView"> + <attr name="size" format="dimension" /> + <attr name="color" format="color" /> + <attr name="text" format="string" /> + </declare-styleable> +</resources>
\ No newline at end of file diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml index 9a486c1..1f6be7f 100644 --- a/tests/BiDiTests/res/values/strings.xml +++ b/tests/BiDiTests/res/values/strings.xml @@ -23,6 +23,7 @@ <string name="button_left_text">Left</string> <string name="button_before_text">Start</string> <string name="button_requestlayout_text">Request Layout</string> + <string name="button_alert_dialog_text">AlertDialog</string> <string name="textview_text">This is a text for a TextView</string> <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string> <string name="normal_text">Normal String</string> @@ -41,5 +42,8 @@ <string name="textview_hebrew_text">םמab?!</string> <string name="textview_latin_text">abםמ?!</string> <string name="textview_multiline_text">םמ?!\nab?!\n?!</string> + <string name="ltr">Left to right text"</string> + <string name="rtl">"والحق أن تترك ونص"</string> + <string name="composing">"\u0644\u0627"</string> </resources> diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java index 68f75c0..b45b98f 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java @@ -102,6 +102,7 @@ public class BiDiTestActivity extends Activity { addItem(result, "Basic", BiDiTestBasic.class, R.id.basic); addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas); + addItem(result, "Canvas2", BiDiTestCanvas2.class, R.id.canvas2); addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr); addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl); @@ -148,4 +149,4 @@ public class BiDiTestActivity extends Activity { inflater.inflate(R.menu.main_menu, menu); return true; } -}
\ No newline at end of file +} diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java index 9b3918d..f0b7438 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestBasic.java @@ -16,17 +16,42 @@ package com.android.bidi; +import android.app.AlertDialog; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; public class BiDiTestBasic extends Fragment { - + + private View currentView; + private Button alertDialogButton; + private String[] items = {"This is a very very very very very very very very very very very long Item1", "Item2"}; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.basic, container, false); + currentView = inflater.inflate(R.layout.basic, container, false); + return currentView; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + alertDialogButton = (Button) currentView.findViewById(R.id.button_alert_dialog); + alertDialogButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + showDialog(); + } + }); + } + + private void showDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(currentView.getContext()); + builder.setSingleChoiceItems(items, 0, null); + builder.show(); } } diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java new file mode 100644 index 0000000..b801f0e --- /dev/null +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bidi; + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.SeekBar; + +import static com.android.bidi.BiDiTestConstants.FONT_MAX_SIZE; +import static com.android.bidi.BiDiTestConstants.FONT_MIN_SIZE; + +public class BiDiTestCanvas2 extends Fragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.canvas2, container, false); + } +} diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java index 4f17e52..0126dea 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java @@ -21,7 +21,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.Typeface; +import android.text.TextPaint; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -37,7 +37,6 @@ public class BiDiTestView extends View { private static final float DEFAULT_ITALIC_SKEW_X = -0.25f; - private Paint paint = new Paint(); private Rect rect = new Rect(); private String NORMAL_TEXT; @@ -51,8 +50,7 @@ public class BiDiTestView extends View { private String CHINESE_TEXT; private String MIXED_TEXT_1; private String HEBREW_TEXT; - - private Typeface typeface; + private String RTL_TEXT; private int currentTextSize; @@ -83,9 +81,7 @@ public class BiDiTestView extends View { CHINESE_TEXT = context.getString(R.string.chinese_text); MIXED_TEXT_1 = context.getString(R.string.mixed_text_1); HEBREW_TEXT = context.getString(R.string.hebrew_text); - - typeface = paint.getTypeface(); - paint.setAntiAlias(true); + RTL_TEXT = context.getString(R.string.rtl); } public void setCurrentTextSize(int size) { @@ -95,54 +91,56 @@ public class BiDiTestView extends View { @Override public void onDraw(Canvas canvas) { - drawInsideRect(canvas, Color.BLACK); + drawInsideRect(canvas, new Paint(), Color.BLACK); int deltaX = 0; deltaX = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN, - paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize); + false, false, Paint.DIRECTION_LTR, currentTextSize); deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN, - paint, typeface, true, false, Paint.DIRECTION_LTR, currentTextSize); + true, false, Paint.DIRECTION_LTR, currentTextSize); deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN, - paint, typeface, false, true, Paint.DIRECTION_LTR, currentTextSize); + false, true, Paint.DIRECTION_LTR, currentTextSize); deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN, - paint, typeface, true, true, Paint.DIRECTION_LTR, currentTextSize); + true, true, Paint.DIRECTION_LTR, currentTextSize); // Test with a long string deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize); + false, false, Paint.DIRECTION_LTR, currentTextSize); // Test with a long string deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize); + false, false, Paint.DIRECTION_LTR, currentTextSize); // Test with a long string deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize); + false, false, Paint.DIRECTION_LTR, currentTextSize); // Test Arabic ligature deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_RTL, currentTextSize); + false, false, Paint.DIRECTION_RTL, currentTextSize); // Test Chinese deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize); + false, false, Paint.DIRECTION_LTR, currentTextSize); // Test Mixed (English and Arabic) deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize); + false, false, Paint.DIRECTION_LTR, currentTextSize); // Test Hebrew - deltaX = testString(canvas, HEBREW_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize, - paint, typeface, false, false, Paint.DIRECTION_RTL, currentTextSize); + deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize, + false, false, Paint.DIRECTION_RTL, currentTextSize); } - private int testString(Canvas canvas, String text, int x, int y, Paint paint, Typeface typeface, + private int testString(Canvas canvas, String text, int x, int y, boolean isItalic, boolean isBold, int dir, int textSize) { - paint.setTypeface(typeface); + + TextPaint paint = new TextPaint(); + paint.setAntiAlias(true); // Set paint properties boolean oldFakeBold = paint.isFakeBoldText(); @@ -153,9 +151,9 @@ public class BiDiTestView extends View { paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X); } - Log.v(TAG, "START -- drawTextWithCanvasDrawText"); - drawTextWithCanvasDrawText(text, canvas, x, y, textSize, Color.WHITE, dir); - Log.v(TAG, "END -- drawTextWithCanvasDrawText"); + paint.setTextSize(textSize); + paint.setColor(Color.WHITE); + canvas.drawText(text, x, y, paint); int length = text.length(); float[] advances = new float[length]; @@ -167,17 +165,6 @@ public class BiDiTestView extends View { logAdvances(text, textWidthHB, textWidthICU, advances); drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN); - paint.setColor(Color.WHITE); -// char[] glyphs = new char[2*length]; -// int count = getGlyphs(text, glyphs, dir); -// -// logGlypths(glyphs, count); -// drawTextWithDrawGlyph(canvas, glyphs, count, x, y + currentTextSize); - - Log.v(TAG, "START -- drawTextWithGlyphs"); - drawTextWithGlyphs(canvas, text, x, y + currentTextSize, dir); - Log.v(TAG, "END -- drawTextWithGlyphs"); - // Restore old paint properties paint.setFakeBoldText(oldFakeBold); paint.setTextSkewX(oldTextSkewX); @@ -190,27 +177,7 @@ public class BiDiTestView extends View { paint.setBidiFlags(dir); } - private void drawTextWithDrawGlyph(Canvas canvas, char[] glyphs, int count, int x, int y) { - canvas.drawGlyphs(glyphs, 0, count, x, y, paint); - } - - private void drawTextWithGlyphs(Canvas canvas, String text, int x, int y, int dir) { - setPaintDir(paint, dir); - canvas.drawTextWithGlyphs(text, x, y, paint); - } - - private void logGlypths(char[] glyphs, int count) { - Log.v(TAG, "GlyphIds - count=" + count); - for (int n = 0; n < count; n++) { - Log.v(TAG, "GlyphIds - Id[" + n + "]="+ (int)glyphs[n]); - } - } - - private int getGlyphs(String text, char[] glyphs, int dir) { - return paint.getTextGlypths(text, 0, text.length(), 0, text.length(), dir, glyphs); - } - - private void drawInsideRect(Canvas canvas, int color) { + private void drawInsideRect(Canvas canvas, Paint paint, int color) { paint.setColor(color); int width = getWidth(); int height = getHeight(); @@ -218,16 +185,9 @@ public class BiDiTestView extends View { canvas.drawRect(rect, paint); } - private void drawTextWithCanvasDrawText(String text, Canvas canvas, - float x, float y, float textSize, int color, int dir) { - setPaintDir(paint, dir); - paint.setColor(color); - paint.setTextSize(textSize); - canvas.drawText(text, x, y, paint); - } - private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB, float textWidthICU, int textSize, int color, int colorICU) { + Paint paint = new Paint(); paint.setColor(color); canvas.drawLine(x, y - textSize, x, y + 8, paint); canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint); diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java new file mode 100644 index 0000000..dfdb807 --- /dev/null +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bidi; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint.Align; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.view.View; + +public class BiDiTestViewDrawText extends View { + private float mSize; + private int mColor; + private String mText; + + public BiDiTestViewDrawText(Context context) { + this(context, null); + } + + public BiDiTestViewDrawText(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BiDiTestViewDrawText(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + final TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.DrawTextTestView, defStyle, 0); + mSize = a.getDimension(R.styleable.DrawTextTestView_size, 40.0f); + mColor = a.getColor(R.styleable.DrawTextTestView_color, Color.YELLOW); + final CharSequence text = a.getText(R.styleable.DrawTextTestView_text); + mText = (text != null) ? text.toString() : "(empty)"; + a.recycle(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + final int width = getWidth(); + final int height = getHeight(); + + final TextPaint paint = new TextPaint(); + paint.setTextSize(mSize); + paint.setColor(mColor); + paint.setTextAlign(Align.CENTER); + + canvas.drawText(mText, width / 2, height * 2 / 3, paint); + } +}
\ No newline at end of file diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java index af5006f..38a85a3 100644 --- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java +++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java @@ -95,9 +95,7 @@ public class Activity2 extends Activity { } { Space v = new Space(context); - { - vg.addView(v, new LayoutParams(row5, col3)); - } + vg.addView(v, new LayoutParams(row5, col3)); } { Button v = new Button(context); diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 32a6a65..9fcd05a 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -94,6 +94,15 @@ </activity> <activity + android:name="CanvasTextureViewActivity" + android:label="_CanvasTextureView"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="GLTextureViewActivity" android:label="_TextureViewGL"> <intent-filter> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java new file mode 100644 index 0000000..81c22b8 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.hwui; + +import android.app.Activity; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.SurfaceTexture; +import android.os.Bundle; +import android.view.Gravity; +import android.view.TextureView; +import android.widget.FrameLayout; + +@SuppressWarnings({"UnusedDeclaration"}) +public class CanvasTextureViewActivity extends Activity + implements TextureView.SurfaceTextureListener { + private TextureView mTextureView; + private CanvasTextureViewActivity.RenderingThread mThread; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + FrameLayout content = new FrameLayout(this); + + mTextureView = new TextureView(this); + mTextureView.setSurfaceTextureListener(this); + mTextureView.setOpaque(false); + + content.addView(mTextureView, new FrameLayout.LayoutParams(500, 500, Gravity.CENTER)); + setContentView(content); + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mThread = new RenderingThread(mTextureView); + mThread.start(); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + // Ignored + } + + @Override + public void onSurfaceTextureDestroyed(SurfaceTexture surface) { + if (mThread != null) mThread.stopRendering(); + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + // Ignored + } + + private static class RenderingThread extends Thread { + private final TextureView mSurface; + private volatile boolean mRunning = true; + + public RenderingThread(TextureView surface) { + mSurface = surface; + } + + @Override + public void run() { + float x = 0.0f; + float y = 0.0f; + float speedX = 5.0f; + float speedY = 3.0f; + + Paint paint = new Paint(); + paint.setColor(0xff00ff00); + + while (mRunning && !Thread.interrupted()) { + final Canvas canvas = mSurface.lockCanvas(null); + try { + canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); + canvas.drawRect(x, y, x + 20.0f, y + 20.0f, paint); + } finally { + mSurface.unlockCanvasAndPost(canvas); + } + + if (x + 20.0f + speedX >= mSurface.getWidth() || x + speedX <= 0.0f) { + speedX = -speedX; + } + if (y + 20.0f + speedY >= mSurface.getHeight() || y + speedY <= 0.0f) { + speedY = -speedY; + } + + x += speedX; + y += speedY; + + try { + Thread.sleep(15); + } catch (InterruptedException e) { + // Interrupted + } + } + } + + void stopRendering() { + interrupt(); + mRunning = false; + } + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java index 1394c32..2519ebc 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java @@ -107,7 +107,7 @@ public class BridgeIInputMethodManager implements IInputMethodManager { } - public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1) + public boolean setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1) throws RemoteException { // TODO Auto-generated method stub return false; diff --git a/wifi/java/android/net/wifi/WifiWatchdogService.java b/wifi/java/android/net/wifi/WifiWatchdogService.java deleted file mode 100644 index bce4b3a..0000000 --- a/wifi/java/android/net/wifi/WifiWatchdogService.java +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi; - -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.ConnectivityManager; -import android.net.DnsPinger; -import android.net.NetworkInfo; -import android.net.Uri; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.SystemClock; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Slog; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.HashSet; -import java.util.List; -import java.util.Scanner; - -/** - * {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi - * network with multiple access points. After the framework successfully - * connects to an access point, the watchdog verifies connectivity by 'pinging' - * the configured DNS server using {@link DnsPinger}. - * <p> - * On DNS check failure, the BSSID is blacklisted if it is reasonably likely - * that another AP might have internet access; otherwise the SSID is disabled. - * <p> - * On DNS success, the WatchdogService initiates a walled garden check via an - * http get. A browser windows is activated if a walled garden is detected. - * - * @hide - */ -public class WifiWatchdogService { - - private static final String WWS_TAG = "WifiWatchdogService"; - - private static final boolean VDBG = true; - private static final boolean DBG = true; - - // Used for verbose logging - private String mDNSCheckLogStr; - - private Context mContext; - private ContentResolver mContentResolver; - private WifiManager mWifiManager; - - private WifiWatchdogHandler mHandler; - - private DnsPinger mDnsPinger; - - private IntentFilter mIntentFilter; - private BroadcastReceiver mBroadcastReceiver; - private boolean mBroadcastsEnabled; - - private static final int WIFI_SIGNAL_LEVELS = 4; - - /** - * Low signal is defined as less than or equal to cut off - */ - private static final int LOW_SIGNAL_CUTOFF = 0; - - private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL = 2 * 60 * 1000; - private static final long MIN_SINGLE_DNS_CHECK_INTERVAL = 10 * 60 * 1000; - private static final long MIN_WALLED_GARDEN_INTERVAL = 15 * 60 * 1000; - - private static final int MAX_CHECKS_PER_SSID = 9; - private static final int NUM_DNS_PINGS = 7; - private static double MIN_RESPONSE_RATE = 0.50; - - // TODO : Adjust multiple DNS downward to 250 on repeated failure - // private static final int MULTI_DNS_PING_TIMEOUT_MS = 250; - - private static final int DNS_PING_TIMEOUT_MS = 800; - private static final long DNS_PING_INTERVAL = 250; - - private static final long BLACKLIST_FOLLOWUP_INTERVAL = 15 * 1000; - - private Status mStatus = new Status(); - - private static class Status { - String bssid = ""; - String ssid = ""; - - HashSet<String> allBssids = new HashSet<String>(); - int numFullDNSchecks = 0; - - long lastSingleCheckTime = -24 * 60 * 60 * 1000; - long lastWalledGardenCheckTime = -24 * 60 * 60 * 1000; - - WatchdogState state = WatchdogState.INACTIVE; - - // Info for dns check - int dnsCheckTries = 0; - int dnsCheckSuccesses = 0; - - public int signal = -200; - - } - - private enum WatchdogState { - /** - * Full DNS check in progress - */ - DNS_FULL_CHECK, - - /** - * Walled Garden detected, will pop up browser next round. - */ - WALLED_GARDEN_DETECTED, - - /** - * DNS failed, will blacklist/disable AP next round - */ - DNS_CHECK_FAILURE, - - /** - * Online or displaying walled garden auth page - */ - CHECKS_COMPLETE, - - /** - * Watchdog idle, network has been blacklisted or received disconnect - * msg - */ - INACTIVE, - - BLACKLISTED_AP - } - - public WifiWatchdogService(Context context) { - mContext = context; - mContentResolver = context.getContentResolver(); - mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context, - ConnectivityManager.TYPE_WIFI); - - HandlerThread handlerThread = new HandlerThread("WifiWatchdogServiceThread"); - handlerThread.start(); - mHandler = new WifiWatchdogHandler(handlerThread.getLooper()); - - setupNetworkReceiver(); - - // The content observer to listen needs a handler, which createThread - // creates - registerForSettingsChanges(); - - // Start things off - if (isWatchdogEnabled()) { - mHandler.sendEmptyMessage(WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT); - } - } - - /** - * - */ - private void setupNetworkReceiver() { - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - mHandler.sendMessage(mHandler.obtainMessage( - WifiWatchdogHandler.MESSAGE_NETWORK_EVENT, - intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO) - )); - } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { - mHandler.sendEmptyMessage(WifiWatchdogHandler.RSSI_CHANGE_EVENT); - } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { - mHandler.sendEmptyMessage(WifiWatchdogHandler.SCAN_RESULTS_AVAILABLE); - } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - mHandler.sendMessage(mHandler.obtainMessage( - WifiWatchdogHandler.WIFI_STATE_CHANGE, - intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 4))); - } - } - }; - - mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); - mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - } - - /** - * Observes the watchdog on/off setting, and takes action when changed. - */ - private void registerForSettingsChanges() { - ContentObserver contentObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange) { - mHandler.sendEmptyMessage((WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT)); - } - }; - - mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), - false, contentObserver); - } - - private void handleNewConnection() { - WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); - String newSsid = wifiInfo.getSSID(); - String newBssid = wifiInfo.getBSSID(); - - if (VDBG) { - Slog.v(WWS_TAG, String.format("handleConnected:: old (%s, %s) ==> new (%s, %s)", - mStatus.ssid, mStatus.bssid, newSsid, newBssid)); - } - - if (TextUtils.isEmpty(newSsid) || TextUtils.isEmpty(newBssid)) { - return; - } - - if (!TextUtils.equals(mStatus.ssid, newSsid)) { - mStatus = new Status(); - mStatus.ssid = newSsid; - } - - mStatus.bssid = newBssid; - mStatus.allBssids.add(newBssid); - mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS); - - initDnsFullCheck(); - } - - public void updateRssi() { - WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); - if (!TextUtils.equals(mStatus.ssid, wifiInfo.getSSID()) || - !TextUtils.equals(mStatus.bssid, wifiInfo.getBSSID())) { - return; - } - - mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS); - } - - /** - * Single step in state machine - */ - private void handleStateStep() { - // Slog.v(WWS_TAG, "handleStateStep:: " + mStatus.state); - - switch (mStatus.state) { - case DNS_FULL_CHECK: - if (VDBG) { - Slog.v(WWS_TAG, "DNS_FULL_CHECK: " + mDNSCheckLogStr); - } - - long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), - DNS_PING_TIMEOUT_MS); - - mStatus.dnsCheckTries++; - if (pingResponseTime >= 0) - mStatus.dnsCheckSuccesses++; - - if (DBG) { - if (pingResponseTime >= 0) { - mDNSCheckLogStr += " | " + pingResponseTime; - } else { - mDNSCheckLogStr += " | " + "x"; - } - } - - switch (currentDnsCheckStatus()) { - case SUCCESS: - if (DBG) { - Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Success"); - } - doWalledGardenCheck(); - break; - case FAILURE: - if (DBG) { - Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Failure"); - } - mStatus.state = WatchdogState.DNS_CHECK_FAILURE; - break; - case INCOMPLETE: - // Taking no action - break; - } - break; - case DNS_CHECK_FAILURE: - WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); - if (!mStatus.ssid.equals(wifiInfo.getSSID()) || - !mStatus.bssid.equals(wifiInfo.getBSSID())) { - Slog.i(WWS_TAG, "handleState DNS_CHECK_FAILURE:: network has changed!"); - mStatus.state = WatchdogState.INACTIVE; - break; - } - - if (mStatus.numFullDNSchecks >= mStatus.allBssids.size() || - mStatus.numFullDNSchecks >= MAX_CHECKS_PER_SSID) { - disableAP(wifiInfo); - } else { - blacklistAP(); - } - break; - case WALLED_GARDEN_DETECTED: - popUpBrowser(); - mStatus.state = WatchdogState.CHECKS_COMPLETE; - break; - case BLACKLISTED_AP: - WifiInfo wifiInfo2 = mWifiManager.getConnectionInfo(); - if (wifiInfo2.getSupplicantState() != SupplicantState.COMPLETED) { - Slog.d(WWS_TAG, - "handleState::BlacklistedAP - offline, but didn't get disconnect!"); - mStatus.state = WatchdogState.INACTIVE; - break; - } - if (mStatus.bssid.equals(wifiInfo2.getBSSID())) { - Slog.d(WWS_TAG, "handleState::BlacklistedAP - connected to same bssid"); - if (!handleSingleDnsCheck()) { - disableAP(wifiInfo2); - break; - } - } - - Slog.d(WWS_TAG, "handleState::BlacklistedAP - Simiulating a new connection"); - handleNewConnection(); - break; - } - } - - private void doWalledGardenCheck() { - if (!isWalledGardenTestEnabled()) { - if (VDBG) - Slog.v(WWS_TAG, "Skipping walled garden check - disabled"); - mStatus.state = WatchdogState.CHECKS_COMPLETE; - return; - } - long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL, - mStatus.lastWalledGardenCheckTime); - if (waitTime > 0) { - if (VDBG) { - Slog.v(WWS_TAG, "Skipping walled garden check - wait " + - waitTime + " ms."); - } - mStatus.state = WatchdogState.CHECKS_COMPLETE; - return; - } - - mStatus.lastWalledGardenCheckTime = SystemClock.elapsedRealtime(); - if (isWalledGardenConnection()) { - if (DBG) - Slog.d(WWS_TAG, - "Walled garden test complete - walled garden detected"); - mStatus.state = WatchdogState.WALLED_GARDEN_DETECTED; - } else { - if (DBG) - Slog.d(WWS_TAG, "Walled garden test complete - online"); - mStatus.state = WatchdogState.CHECKS_COMPLETE; - } - } - - private boolean handleSingleDnsCheck() { - mStatus.lastSingleCheckTime = SystemClock.elapsedRealtime(); - long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), - DNS_PING_TIMEOUT_MS); - if (DBG) { - Slog.d(WWS_TAG, "Ran a single DNS ping. Response time: " + responseTime); - } - if (responseTime < 0) { - return false; - } - return true; - - } - - /** - * @return Delay in MS before next single DNS check can proceed. - */ - private long timeToNextScheduledDNSCheck() { - if (mStatus.signal > LOW_SIGNAL_CUTOFF) { - return waitTime(MIN_SINGLE_DNS_CHECK_INTERVAL, mStatus.lastSingleCheckTime); - } else { - return waitTime(MIN_LOW_SIGNAL_CHECK_INTERVAL, mStatus.lastSingleCheckTime); - } - } - - /** - * Helper to return wait time left given a min interval and last run - * - * @param interval minimum wait interval - * @param lastTime last time action was performed in - * SystemClock.elapsedRealtime() - * @return non negative time to wait - */ - private static long waitTime(long interval, long lastTime) { - long wait = interval + lastTime - SystemClock.elapsedRealtime(); - return wait > 0 ? wait : 0; - } - - private void popUpBrowser() { - Uri uri = Uri.parse("http://www.google.com"); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | - Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent); - } - - private void disableAP(WifiInfo info) { - // TODO : Unban networks if they had low signal ? - Slog.i(WWS_TAG, String.format("Disabling current SSID, %s [bssid %s]. " + - "numChecks %d, numAPs %d", mStatus.ssid, mStatus.bssid, - mStatus.numFullDNSchecks, mStatus.allBssids.size())); - mWifiManager.disableNetwork(info.getNetworkId()); - mStatus.state = WatchdogState.INACTIVE; - } - - private void blacklistAP() { - Slog.i(WWS_TAG, String.format("Blacklisting current BSSID %s [ssid %s]. " + - "numChecks %d, numAPs %d", mStatus.bssid, mStatus.ssid, - mStatus.numFullDNSchecks, mStatus.allBssids.size())); - - mWifiManager.addToBlacklist(mStatus.bssid); - mWifiManager.reassociate(); - mStatus.state = WatchdogState.BLACKLISTED_AP; - } - - /** - * Checks the scan for new BBIDs using current mSsid - */ - private void updateBssids() { - String curSsid = mStatus.ssid; - HashSet<String> bssids = mStatus.allBssids; - List<ScanResult> results = mWifiManager.getScanResults(); - int oldNumBssids = bssids.size(); - - if (results == null) { - if (VDBG) { - Slog.v(WWS_TAG, "updateBssids: Got null scan results!"); - } - return; - } - - for (ScanResult result : results) { - if (result != null && curSsid.equals(result.SSID)) - bssids.add(result.BSSID); - } - - // if (VDBG && bssids.size() - oldNumBssids > 0) { - // Slog.v(WWS_TAG, - // String.format("updateBssids:: Found %d new APs (total %d) on SSID %s", - // bssids.size() - oldNumBssids, bssids.size(), curSsid)); - // } - } - - enum DnsCheckStatus { - SUCCESS, - FAILURE, - INCOMPLETE - } - - /** - * Computes the current results of the dns check, ends early if outcome is - * assured. - */ - private DnsCheckStatus currentDnsCheckStatus() { - /** - * After a full ping count, if we have more responses than this cutoff, - * the outcome is success; else it is 'failure'. - */ - double pingResponseCutoff = MIN_RESPONSE_RATE * NUM_DNS_PINGS; - int remainingChecks = NUM_DNS_PINGS - mStatus.dnsCheckTries; - - /** - * Our final success count will be at least this big, so we're - * guaranteed to succeed. - */ - if (mStatus.dnsCheckSuccesses >= pingResponseCutoff) { - return DnsCheckStatus.SUCCESS; - } - - /** - * Our final count will be at most the current count plus the remaining - * pings - we're guaranteed to fail. - */ - if (remainingChecks + mStatus.dnsCheckSuccesses < pingResponseCutoff) { - return DnsCheckStatus.FAILURE; - } - - return DnsCheckStatus.INCOMPLETE; - } - - private void initDnsFullCheck() { - if (DBG) { - Slog.d(WWS_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime()); - } - mStatus.numFullDNSchecks++; - mStatus.dnsCheckSuccesses = 0; - mStatus.dnsCheckTries = 0; - mStatus.state = WatchdogState.DNS_FULL_CHECK; - - if (DBG) { - mDNSCheckLogStr = String.format("Dns Check %d. Pinging %s on ssid [%s]: ", - mStatus.numFullDNSchecks, mDnsPinger.getDns(), - mStatus.ssid); - } - } - - /** - * DNS based detection techniques do not work at all hotspots. The one sure - * way to check a walled garden is to see if a URL fetch on a known address - * fetches the data we expect - */ - private boolean isWalledGardenConnection() { - InputStream in = null; - HttpURLConnection urlConnection = null; - try { - URL url = new URL(getWalledGardenUrl()); - urlConnection = (HttpURLConnection) url.openConnection(); - in = new BufferedInputStream(urlConnection.getInputStream()); - Scanner scanner = new Scanner(in); - if (scanner.findInLine(getWalledGardenPattern()) != null) { - return false; - } else { - return true; - } - } catch (IOException e) { - return false; - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - } - } - if (urlConnection != null) - urlConnection.disconnect(); - } - } - - /** - * There is little logic inside this class, instead methods of the form - * "handle___" are called in the main {@link WifiWatchdogService}. - */ - private class WifiWatchdogHandler extends Handler { - /** - * Major network event, object is NetworkInfo - */ - static final int MESSAGE_NETWORK_EVENT = 1; - /** - * Change in settings, no object - */ - static final int MESSAGE_CONTEXT_EVENT = 2; - - /** - * Change in signal strength - */ - static final int RSSI_CHANGE_EVENT = 3; - static final int SCAN_RESULTS_AVAILABLE = 4; - - static final int WIFI_STATE_CHANGE = 5; - - /** - * Single step of state machine. One DNS check, or one WalledGarden - * check, or one external action. We separate out external actions to - * increase chance of detecting that a check failure is caused by change - * in network status. Messages should have an arg1 which to sync status - * messages. - */ - static final int CHECK_SEQUENCE_STEP = 10; - static final int SINGLE_DNS_CHECK = 11; - - /** - * @param looper - */ - public WifiWatchdogHandler(Looper looper) { - super(looper); - } - - boolean singleCheckQueued = false; - long queuedSingleDnsCheckArrival; - - /** - * Sends a singleDnsCheck message with shortest time - guards against - * multiple. - */ - private boolean queueSingleDnsCheck() { - long delay = timeToNextScheduledDNSCheck(); - long newArrival = delay + SystemClock.elapsedRealtime(); - if (singleCheckQueued && queuedSingleDnsCheckArrival <= newArrival) - return true; - queuedSingleDnsCheckArrival = newArrival; - singleCheckQueued = true; - removeMessages(SINGLE_DNS_CHECK); - return sendMessageDelayed(obtainMessage(SINGLE_DNS_CHECK), delay); - } - - boolean checkSequenceQueued = false; - long queuedCheckSequenceArrival; - - /** - * Sends a state_machine_step message if the delay requested is lower - * than the current delay. - */ - private boolean sendCheckSequenceStep(long delay) { - long newArrival = delay + SystemClock.elapsedRealtime(); - if (checkSequenceQueued && queuedCheckSequenceArrival <= newArrival) - return true; - queuedCheckSequenceArrival = newArrival; - checkSequenceQueued = true; - removeMessages(CHECK_SEQUENCE_STEP); - return sendMessageDelayed(obtainMessage(CHECK_SEQUENCE_STEP), delay); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case CHECK_SEQUENCE_STEP: - checkSequenceQueued = false; - handleStateStep(); - if (mStatus.state == WatchdogState.CHECKS_COMPLETE) { - queueSingleDnsCheck(); - } else if (mStatus.state == WatchdogState.DNS_FULL_CHECK) { - sendCheckSequenceStep(DNS_PING_INTERVAL); - } else if (mStatus.state == WatchdogState.BLACKLISTED_AP) { - sendCheckSequenceStep(BLACKLIST_FOLLOWUP_INTERVAL); - } else if (mStatus.state != WatchdogState.INACTIVE) { - sendCheckSequenceStep(0); - } - return; - case MESSAGE_NETWORK_EVENT: - if (!mBroadcastsEnabled) { - Slog.e(WWS_TAG, - "MessageNetworkEvent - WatchdogService not enabled... returning"); - return; - } - NetworkInfo info = (NetworkInfo) msg.obj; - switch (info.getState()) { - case DISCONNECTED: - mStatus.state = WatchdogState.INACTIVE; - return; - case CONNECTED: - handleNewConnection(); - sendCheckSequenceStep(0); - } - return; - case SINGLE_DNS_CHECK: - singleCheckQueued = false; - if (mStatus.state != WatchdogState.CHECKS_COMPLETE) { - Slog.d(WWS_TAG, "Single check returning, curState: " + mStatus.state); - break; - } - - if (!handleSingleDnsCheck()) { - initDnsFullCheck(); - sendCheckSequenceStep(0); - } else { - queueSingleDnsCheck(); - } - - break; - case RSSI_CHANGE_EVENT: - updateRssi(); - if (mStatus.state == WatchdogState.CHECKS_COMPLETE) - queueSingleDnsCheck(); - break; - case SCAN_RESULTS_AVAILABLE: - updateBssids(); - break; - case WIFI_STATE_CHANGE: - if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) { - Slog.i(WWS_TAG, "WifiStateDisabling -- Resetting WatchdogState"); - mStatus = new Status(); - } - break; - case MESSAGE_CONTEXT_EVENT: - if (isWatchdogEnabled() && !mBroadcastsEnabled) { - mContext.registerReceiver(mBroadcastReceiver, mIntentFilter); - mBroadcastsEnabled = true; - Slog.i(WWS_TAG, "WifiWatchdogService enabled"); - } else if (!isWatchdogEnabled() && mBroadcastsEnabled) { - mContext.unregisterReceiver(mBroadcastReceiver); - removeMessages(SINGLE_DNS_CHECK); - removeMessages(CHECK_SEQUENCE_STEP); - mBroadcastsEnabled = false; - Slog.i(WWS_TAG, "WifiWatchdogService disabled"); - } - break; - } - } - } - - public void dump(PrintWriter pw) { - pw.print("WatchdogStatus: "); - pw.print("State " + mStatus.state); - pw.println(", network [" + mStatus.ssid + ", " + mStatus.bssid + "]"); - pw.print("checkCount " + mStatus.numFullDNSchecks); - pw.println(", bssids: " + mStatus.allBssids); - pw.print(", hasCheckMessages? " + - mHandler.hasMessages(WifiWatchdogHandler.CHECK_SEQUENCE_STEP)); - pw.println(" hasSingleCheckMessages? " + - mHandler.hasMessages(WifiWatchdogHandler.SINGLE_DNS_CHECK)); - pw.println("DNS check log str: " + mDNSCheckLogStr); - pw.println("lastSingleCheck: " + mStatus.lastSingleCheckTime); - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED - */ - private Boolean isWalledGardenTestEnabled() { - return Settings.Secure.getInt(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1; - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL - */ - private String getWalledGardenUrl() { - String url = Settings.Secure.getString(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL); - if (TextUtils.isEmpty(url)) - return "http://www.google.com/"; - return url; - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN - */ - private String getWalledGardenPattern() { - String pattern = Settings.Secure.getString(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN); - if (TextUtils.isEmpty(pattern)) - return "<title>.*Google.*</title>"; - return pattern; - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON - */ - private boolean isWatchdogEnabled() { - return Settings.Secure.getInt(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1; - } -} diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java new file mode 100644 index 0000000..0eb73b7 --- /dev/null +++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java @@ -0,0 +1,825 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +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.ConnectivityManager; +import android.net.DnsPinger; +import android.net.NetworkInfo; +import android.net.Uri; +import android.os.Message; +import android.os.SystemClock; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Slog; + +import com.android.internal.util.Protocol; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashSet; +import java.util.List; +import java.util.Scanner; + +/** + * {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi + * network with multiple access points. After the framework successfully + * connects to an access point, the watchdog verifies connectivity by 'pinging' + * the configured DNS server using {@link DnsPinger}. + * <p> + * On DNS check failure, the BSSID is blacklisted if it is reasonably likely + * that another AP might have internet access; otherwise the SSID is disabled. + * <p> + * On DNS success, the WatchdogService initiates a walled garden check via an + * http get. A browser window is activated if a walled garden is detected. + * + * @hide + */ +public class WifiWatchdogStateMachine extends StateMachine { + + private static final boolean VDBG = false; + private static final boolean DBG = true; + private static final String WWSM_TAG = "WifiWatchdogStateMachine"; + + private static final int WIFI_SIGNAL_LEVELS = 4; + /** + * Low signal is defined as less than or equal to cut off + */ + private static final int LOW_SIGNAL_CUTOFF = 1; + + private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL_MS = 2 * 60 * 1000; + private static final long MIN_SINGLE_DNS_CHECK_INTERVAL_MS = 10 * 60 * 1000; + private static final long MIN_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000; + + private static final int MAX_CHECKS_PER_SSID = 7; + private static final int NUM_DNS_PINGS = 5; + private static final double MIN_DNS_RESPONSE_RATE = 0.50; + + private static final int DNS_PING_TIMEOUT_MS = 800; + private static final long DNS_PING_INTERVAL_MS = 100; + + private static final long BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000; + + private static final int BASE = Protocol.BASE_WIFI_WATCHDOG; + + /** + * Indicates the enable setting of WWS may have changed + */ + private static final int EVENT_WATCHDOG_TOGGLED = BASE + 1; + + /** + * Indicates the wifi network state has changed. Passed w/ original intent + * which has a non-null networkInfo object + */ + private static final int EVENT_NETWORK_STATE_CHANGE = BASE + 2; + /** + * Indicates the signal has changed. Passed with arg1 + * {@link #mNetEventCounter} and arg2 [raw signal strength] + */ + private static final int EVENT_RSSI_CHANGE = BASE + 3; + private static final int EVENT_SCAN_RESULTS_AVAILABLE = BASE + 4; + private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5; + + private static final int MESSAGE_CHECK_STEP = BASE + 100; + private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 101; + private static final int MESSAGE_HANDLE_BAD_AP = BASE + 102; + /** + * arg1 == mOnlineWatchState.checkCount + */ + private static final int MESSAGE_SINGLE_DNS_CHECK = BASE + 103; + private static final int MESSAGE_NETWORK_FOLLOWUP = BASE + 104; + + private Context mContext; + private ContentResolver mContentResolver; + private WifiManager mWifiManager; + private DnsPinger mDnsPinger; + private IntentFilter mIntentFilter; + private BroadcastReceiver mBroadcastReceiver; + + private DefaultState mDefaultState = new DefaultState(); + private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState(); + private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState(); + private NotConnectedState mNotConnectedState = new NotConnectedState(); + private ConnectedState mConnectedState = new ConnectedState(); + private DnsCheckingState mDnsCheckingState = new DnsCheckingState(); + private OnlineWatchState mOnlineWatchState = new OnlineWatchState(); + private DnsCheckFailureState mDnsCheckFailureState = new DnsCheckFailureState(); + private WalledGardenState mWalledGardenState = new WalledGardenState(); + private BlacklistedApState mBlacklistedApState = new BlacklistedApState(); + + /** + * The {@link WifiInfo} object passed to WWSM on network broadcasts + */ + private WifiInfo mInitialConnInfo; + private int mNetEventCounter = 0; + + /** + * Currently maintained but not used, TODO + */ + private HashSet<String> mBssids = new HashSet<String>(); + private int mNumFullDNSchecks = 0; + + private Long mLastWalledGardenCheckTime = null; + + /** + * This is set by the blacklisted state and reset when connected to a new AP. + * It triggers a disableNetwork call if a DNS check fails. + */ + public boolean mDisableAPNextFailure = false; + + /** + * STATE MAP + * Default + * / \ + * Disabled Enabled + * / \ + * Disconnected Connected + * /---------\ + * (all other states) + */ + private WifiWatchdogStateMachine(Context context) { + super(WWSM_TAG); + mContext = context; + mContentResolver = context.getContentResolver(); + mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context, + ConnectivityManager.TYPE_WIFI); + + setupNetworkReceiver(); + + // The content observer to listen needs a handler + registerForSettingsChanges(); + addState(mDefaultState); + addState(mWatchdogDisabledState, mDefaultState); + addState(mWatchdogEnabledState, mDefaultState); + addState(mNotConnectedState, mWatchdogEnabledState); + addState(mConnectedState, mWatchdogEnabledState); + addState(mDnsCheckingState, mConnectedState); + addState(mDnsCheckFailureState, mConnectedState); + addState(mWalledGardenState, mConnectedState); + addState(mBlacklistedApState, mConnectedState); + addState(mOnlineWatchState, mConnectedState); + + setInitialState(mWatchdogDisabledState); + } + + public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) { + WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context); + wwsm.start(); + wwsm.sendMessage(EVENT_WATCHDOG_TOGGLED); + return wwsm; + } + + /** + * + */ + private void setupNetworkReceiver() { + mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + sendMessage(EVENT_NETWORK_STATE_CHANGE, intent); + } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { + obtainMessage(EVENT_RSSI_CHANGE, mNetEventCounter, + intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200)).sendToTarget(); + } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { + sendMessage(EVENT_SCAN_RESULTS_AVAILABLE); + } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE, + intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_UNKNOWN)); + } + } + }; + + mIntentFilter = new IntentFilter(); + mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); + mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + } + + /** + * Observes the watchdog on/off setting, and takes action when changed. + */ + private void registerForSettingsChanges() { + ContentObserver contentObserver = new ContentObserver(this.getHandler()) { + @Override + public void onChange(boolean selfChange) { + sendMessage(EVENT_WATCHDOG_TOGGLED); + } + }; + + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), + false, contentObserver); + } + + /** + * DNS based detection techniques do not work at all hotspots. The one sure + * way to check a walled garden is to see if a URL fetch on a known address + * fetches the data we expect + */ + private boolean isWalledGardenConnection() { + InputStream in = null; + HttpURLConnection urlConnection = null; + try { + URL url = new URL(getWalledGardenUrl()); + urlConnection = (HttpURLConnection) url.openConnection(); + in = new BufferedInputStream(urlConnection.getInputStream()); + Scanner scanner = new Scanner(in); + if (scanner.findInLine(getWalledGardenPattern()) != null) { + return false; + } else { + return true; + } + } catch (IOException e) { + return false; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + if (urlConnection != null) + urlConnection.disconnect(); + } + } + + private boolean rssiStrengthAboveCutoff(int rssi) { + return WifiManager.calculateSignalLevel(rssi, WIFI_SIGNAL_LEVELS) > LOW_SIGNAL_CUTOFF; + } + + public void dump(PrintWriter pw) { + pw.print("WatchdogStatus: "); + pw.print("State " + getCurrentState()); + pw.println(", network [" + mInitialConnInfo + "]"); + pw.print("checkCount " + mNumFullDNSchecks); + pw.println(", bssids: " + mBssids); + pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime); + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED + */ + private Boolean isWalledGardenTestEnabled() { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL + */ + private String getWalledGardenUrl() { + String url = Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL); + if (TextUtils.isEmpty(url)) + return "http://www.google.com/"; + return url; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN + */ + private String getWalledGardenPattern() { + String pattern = Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN); + if (TextUtils.isEmpty(pattern)) + return "<title>.*Google.*</title>"; + return pattern; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON + */ + private boolean isWatchdogEnabled() { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1; + } + + + /** + * Helper to return wait time left given a min interval and last run + * + * @param interval minimum wait interval + * @param lastTime last time action was performed in + * SystemClock.elapsedRealtime(). Null if never. + * @return non negative time to wait + */ + private static long waitTime(long interval, Long lastTime) { + if (lastTime == null) + return 0; + long wait = interval + lastTime - SystemClock.elapsedRealtime(); + return wait > 0 ? wait : 0; + } + + private static String wifiInfoToStr(WifiInfo wifiInfo) { + if (wifiInfo == null) + return "null"; + return "(" + wifiInfo.getSSID() + ", " + wifiInfo.getBSSID() + ")"; + } + + /** + * + */ + private void resetWatchdogState() { + mInitialConnInfo = null; + mDisableAPNextFailure = false; + mLastWalledGardenCheckTime = null; + mNumFullDNSchecks = 0; + mBssids.clear(); + } + + private void popUpBrowser() { + Uri uri = Uri.parse("http://www.google.com"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | + Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + + private void sendCheckStepMessage(long delay) { + sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay); + } + + class DefaultState extends State { + @Override + public boolean processMessage(Message msg) { + if (VDBG) { + Slog.v(WWSM_TAG, "Caught message " + msg.what + " in state " + + getCurrentState().getName()); + } + return HANDLED; + } + } + + class WatchdogDisabledState extends State { + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case EVENT_WATCHDOG_TOGGLED: + if (isWatchdogEnabled()) + transitionTo(mNotConnectedState); + return HANDLED; + } + return NOT_HANDLED; + } + } + + class WatchdogEnabledState extends State { + @Override + public void enter() { + resetWatchdogState(); + mContext.registerReceiver(mBroadcastReceiver, mIntentFilter); + Slog.i(WWSM_TAG, "WifiWatchdogService enabled"); + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case EVENT_WATCHDOG_TOGGLED: + if (!isWatchdogEnabled()) + transitionTo(mWatchdogDisabledState); + return HANDLED; + case EVENT_NETWORK_STATE_CHANGE: + Intent stateChangeIntent = (Intent) msg.obj; + NetworkInfo networkInfo = (NetworkInfo) + stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + + switch (networkInfo.getState()) { + case CONNECTED: + // WifiInfo wifiInfo = (WifiInfo) + // stateChangeIntent + // .getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); + // TODO : Replace with above code when API is changed + WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + if (wifiInfo == null) { + Slog.e(WWSM_TAG, "Connected --> WifiInfo object null!"); + return HANDLED; + } + + if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) { + Slog.e(WWSM_TAG, "Received wifiInfo object with null elts: " + + wifiInfoToStr(wifiInfo)); + return HANDLED; + } + + initConnection(wifiInfo); + transitionTo(mDnsCheckingState); + mNetEventCounter++; + return HANDLED; + case DISCONNECTED: + case DISCONNECTING: + mNetEventCounter++; + transitionTo(mNotConnectedState); + return HANDLED; + } + return HANDLED; + case EVENT_WIFI_RADIO_STATE_CHANGE: + if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) { + Slog.i(WWSM_TAG, "WifiStateDisabling -- Resetting WatchdogState"); + resetWatchdogState(); + mNetEventCounter++; + transitionTo(mNotConnectedState); + } + return HANDLED; + } + + return NOT_HANDLED; + } + + /** + * @param wifiInfo Info object with non-null ssid and bssid + */ + private void initConnection(WifiInfo wifiInfo) { + if (VDBG) { + Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mInitialConnInfo) + + " ==> new " + wifiInfoToStr(wifiInfo)); + } + + if (mInitialConnInfo == null || !wifiInfo.getSSID().equals(mInitialConnInfo.getSSID())) { + resetWatchdogState(); + } else if (!wifiInfo.getBSSID().equals(mInitialConnInfo.getBSSID())) { + mDisableAPNextFailure = false; + } + mInitialConnInfo = wifiInfo; + } + + @Override + public void exit() { + mContext.unregisterReceiver(mBroadcastReceiver); + Slog.i(WWSM_TAG, "WifiWatchdogService disabled"); + } + } + + class NotConnectedState extends State { + } + + class ConnectedState extends State { + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case EVENT_SCAN_RESULTS_AVAILABLE: + String curSsid = mInitialConnInfo.getSSID(); + List<ScanResult> results = mWifiManager.getScanResults(); + int oldNumBssids = mBssids.size(); + + if (results == null) { + if (DBG) { + Slog.d(WWSM_TAG, "updateBssids: Got null scan results!"); + } + return HANDLED; + } + + for (ScanResult result : results) { + if (result == null || result.SSID == null) { + if (VDBG) { + Slog.v(WWSM_TAG, "Received invalid scan result: " + result); + } + continue; + } + if (curSsid.equals(result.SSID)) + mBssids.add(result.BSSID); + } + return HANDLED; + } + return NOT_HANDLED; + } + + } + + class DnsCheckingState extends State { + int dnsCheckTries = 0; + int dnsCheckSuccesses = 0; + String dnsCheckLogStr = ""; + + @Override + public void enter() { + mNumFullDNSchecks++; + dnsCheckSuccesses = 0; + dnsCheckTries = 0; + if (DBG) { + Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime()); + dnsCheckLogStr = String.format("Dns Check %d. Pinging %s on ssid [%s]: ", + mNumFullDNSchecks, mDnsPinger.getDns(), mInitialConnInfo.getSSID()); + } + + sendCheckStepMessage(0); + } + + @Override + public boolean processMessage(Message msg) { + if (msg.what != MESSAGE_CHECK_STEP) { + return NOT_HANDLED; + } + if (msg.arg1 != mNetEventCounter) { + Slog.d(WWSM_TAG, "Check step out of sync, ignoring..."); + return HANDLED; + } + + long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), + DNS_PING_TIMEOUT_MS); + + dnsCheckTries++; + if (pingResponseTime >= 0) + dnsCheckSuccesses++; + + if (DBG) { + if (pingResponseTime >= 0) { + dnsCheckLogStr += "|" + pingResponseTime; + } else { + dnsCheckLogStr += "|x"; + } + } + + if (VDBG) { + Slog.v(WWSM_TAG, dnsCheckLogStr); + } + + /** + * After a full ping count, if we have more responses than this + * cutoff, the outcome is success; else it is 'failure'. + */ + double pingResponseCutoff = MIN_DNS_RESPONSE_RATE * NUM_DNS_PINGS; + int remainingChecks = NUM_DNS_PINGS - dnsCheckTries; + + /** + * Our final success count will be at least this big, so we're + * guaranteed to succeed. + */ + if (dnsCheckSuccesses >= pingResponseCutoff) { + // DNS CHECKS OK, NOW WALLED GARDEN + if (DBG) { + Slog.d(WWSM_TAG, dnsCheckLogStr + "| SUCCESS"); + } + + if (!shouldCheckWalledGarden()) { + transitionTo(mOnlineWatchState); + return HANDLED; + } + + mLastWalledGardenCheckTime = SystemClock.elapsedRealtime(); + if (isWalledGardenConnection()) { + if (DBG) + Slog.d(WWSM_TAG, + "Walled garden test complete - walled garden detected"); + transitionTo(mWalledGardenState); + } else { + if (DBG) + Slog.d(WWSM_TAG, "Walled garden test complete - online"); + transitionTo(mOnlineWatchState); + } + return HANDLED; + } + + /** + * Our final count will be at most the current count plus the + * remaining pings - we're guaranteed to fail. + */ + if (remainingChecks + dnsCheckSuccesses < pingResponseCutoff) { + if (DBG) { + Slog.d(WWSM_TAG, dnsCheckLogStr + "| FAILURE"); + } + transitionTo(mDnsCheckFailureState); + return HANDLED; + } + + // Still in dns check step + sendCheckStepMessage(DNS_PING_INTERVAL_MS); + return HANDLED; + } + + private boolean shouldCheckWalledGarden() { + if (!isWalledGardenTestEnabled()) { + if (VDBG) + Slog.v(WWSM_TAG, "Skipping walled garden check - disabled"); + return false; + } + long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL_MS, + mLastWalledGardenCheckTime); + if (waitTime > 0) { + if (DBG) { + Slog.d(WWSM_TAG, "Skipping walled garden check - wait " + + waitTime + " ms."); + } + return false; + } + return true; + } + + } + + class OnlineWatchState extends State { + /** + * Signals a short-wait message is enqueued for the current 'guard' counter + */ + boolean unstableSignalChecks = false; + + /** + * The signal is unstable. We should enqueue a short-wait check, if one is enqueued + * already + */ + boolean signalUnstable = false; + + /** + * A monotonic counter to ensure that at most one check message will be processed from any + * set of check messages currently enqueued. Avoids duplicate checks when a low-signal + * event is observed. + */ + int checkGuard = 0; + Long lastCheckTime = null; + + @Override + public void enter() { + lastCheckTime = SystemClock.elapsedRealtime(); + signalUnstable = false; + checkGuard++; + unstableSignalChecks = false; + triggerSingleDnsCheck(); + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case EVENT_RSSI_CHANGE: + if (msg.arg1 != mNetEventCounter) { + if (DBG) { + Slog.d(WWSM_TAG, "Rssi change message out of sync, ignoring"); + } + return HANDLED; + } + int newRssi = msg.arg2; + signalUnstable = !rssiStrengthAboveCutoff(newRssi); + if (VDBG) { + Slog.v(WWSM_TAG, "OnlineWatchState:: new rssi " + newRssi + " --> level " + + WifiManager.calculateSignalLevel(newRssi, WIFI_SIGNAL_LEVELS)); + } + + if (signalUnstable && !unstableSignalChecks) { + if (VDBG) { + Slog.v(WWSM_TAG, "Sending triggered check msg"); + } + triggerSingleDnsCheck(); + } + return HANDLED; + case MESSAGE_SINGLE_DNS_CHECK: + if (msg.arg1 != checkGuard) { + if (VDBG) { + Slog.v(WWSM_TAG, "Single check msg out of sync, ignoring."); + } + return HANDLED; + } + lastCheckTime = SystemClock.elapsedRealtime(); + long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), + DNS_PING_TIMEOUT_MS); + if (responseTime >= 0) { + if (VDBG) { + Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: " + + responseTime); + } + + checkGuard++; + unstableSignalChecks = false; + triggerSingleDnsCheck(); + } else { + if (DBG) { + Slog.d(WWSM_TAG, "Single dns ping failure. Starting full checks."); + } + transitionTo(mDnsCheckingState); + } + return HANDLED; + } + return NOT_HANDLED; + } + + /** + * Times a dns check with an interval based on {@link #curSignalStable} + */ + private void triggerSingleDnsCheck() { + long waitInterval; + if (signalUnstable) { + waitInterval = MIN_LOW_SIGNAL_CHECK_INTERVAL_MS; + unstableSignalChecks = true; + } else { + waitInterval = MIN_SINGLE_DNS_CHECK_INTERVAL_MS; + } + sendMessageDelayed(obtainMessage(MESSAGE_SINGLE_DNS_CHECK, checkGuard, 0), + waitTime(waitInterval, lastCheckTime)); + } + } + + class DnsCheckFailureState extends State { + @Override + public void enter() { + obtainMessage(MESSAGE_HANDLE_BAD_AP, mNetEventCounter, 0).sendToTarget(); + } + + @Override + public boolean processMessage(Message msg) { + if (msg.what != MESSAGE_HANDLE_BAD_AP) { + return NOT_HANDLED; + } + + if (msg.arg1 != mNetEventCounter) { + if (VDBG) { + Slog.v(WWSM_TAG, "Msg out of sync, ignoring..."); + } + return HANDLED; + } + + if (mDisableAPNextFailure || mNumFullDNSchecks >= MAX_CHECKS_PER_SSID) { + // TODO : Unban networks if they had low signal ? + Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo) + + ". " + + "numChecks " + mNumFullDNSchecks + ", numAPs " + mBssids.size()); + mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId()); + transitionTo(mNotConnectedState); + } else { + Slog.i(WWSM_TAG, "Blacklisting current BSSID. " + wifiInfoToStr(mInitialConnInfo) + + "numChecks " + mNumFullDNSchecks + ", numAPs " + mBssids.size()); + + mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID()); + mWifiManager.reassociate(); + transitionTo(mBlacklistedApState); + } + return HANDLED; + } + } + + class WalledGardenState extends State { + @Override + public void enter() { + obtainMessage(MESSAGE_HANDLE_WALLED_GARDEN, mNetEventCounter, 0).sendToTarget(); + } + + @Override + public boolean processMessage(Message msg) { + if (msg.what != MESSAGE_HANDLE_WALLED_GARDEN) { + return NOT_HANDLED; + } + + if (msg.arg1 != mNetEventCounter) { + if (VDBG) { + Slog.v(WWSM_TAG, "WalledGardenState::Msg out of sync, ignoring..."); + } + return HANDLED; + } + popUpBrowser(); + transitionTo(mOnlineWatchState); + return HANDLED; + } + } + + class BlacklistedApState extends State { + @Override + public void enter() { + mDisableAPNextFailure = true; + sendMessageDelayed(obtainMessage(MESSAGE_NETWORK_FOLLOWUP, mNetEventCounter, 0), + BLACKLIST_FOLLOWUP_INTERVAL_MS); + } + + @Override + public boolean processMessage(Message msg) { + if (msg.what != MESSAGE_NETWORK_FOLLOWUP) { + return NOT_HANDLED; + } + + if (msg.arg1 != mNetEventCounter) { + if (VDBG) { + Slog.v(WWSM_TAG, "BlacklistedApState::Msg out of sync, ignoring..."); + } + return HANDLED; + } + + transitionTo(mDnsCheckingState); + return HANDLED; + } + } +} |