diff options
94 files changed, 3721 insertions, 1642 deletions
diff --git a/api/current.txt b/api/current.txt index bbcf6fbafa39..a3f2ffffc208 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10504,6 +10504,7 @@ package android.location { method public float getAccuracy(); method public double getAltitude(); method public float getBearing(); + method public long getElapsedRealtimeNano(); method public android.os.Bundle getExtras(); method public double getLatitude(); method public double getLongitude(); @@ -10523,6 +10524,7 @@ package android.location { method public void setAccuracy(float); method public void setAltitude(double); method public void setBearing(float); + method public void setElapsedRealtimeNano(long); method public void setExtras(android.os.Bundle); method public void setLatitude(double); method public void setLongitude(double); @@ -16347,6 +16349,7 @@ package android.os { public final class SystemClock { method public static long currentThreadTimeMillis(); method public static long elapsedRealtime(); + method public static long elapsedRealtimeNano(); method public static boolean setCurrentTimeMillis(long); method public static void sleep(long); method public static long uptimeMillis(); @@ -22828,6 +22831,17 @@ package android.util { method public void set(T, V); } + public class PropertyValueModel extends android.util.ValueModel { + method public T get(); + method public H getHost(); + method public android.util.Property<H, T> getProperty(); + method public java.lang.Class<T> getType(); + method public static android.util.PropertyValueModel<H, T> of(H, android.util.Property<H, T>); + method public static android.util.PropertyValueModel<H, T> of(H, java.lang.Class<T>, java.lang.String); + method public static android.util.PropertyValueModel of(java.lang.Object, java.lang.String); + method public void set(T); + } + public class SparseArray implements java.lang.Cloneable { ctor public SparseArray(); ctor public SparseArray(int); @@ -22976,6 +22990,14 @@ package android.util { field public int type; } + public abstract class ValueModel { + ctor protected ValueModel(); + method public abstract T get(); + method public abstract java.lang.Class<T> getType(); + method public abstract void set(T); + field public static final android.util.ValueModel EMPTY; + } + public class Xml { method public static android.util.AttributeSet asAttributeSet(org.xmlpull.v1.XmlPullParser); method public static android.util.Xml.Encoding findEncodingByName(java.lang.String) throws java.io.UnsupportedEncodingException; @@ -26617,6 +26639,7 @@ package android.webkit { method public boolean getLightTouchEnabled(); method public boolean getLoadWithOverviewMode(); method public synchronized boolean getLoadsImagesAutomatically(); + method public boolean getMediaPlaybackRequiresUserGesture(); method public synchronized int getMinimumFontSize(); method public synchronized int getMinimumLogicalFontSize(); method public deprecated boolean getNavDump(); @@ -26666,6 +26689,7 @@ package android.webkit { method public void setLightTouchEnabled(boolean); method public void setLoadWithOverviewMode(boolean); method public synchronized void setLoadsImagesAutomatically(boolean); + method public void setMediaPlaybackRequiresUserGesture(boolean); method public synchronized void setMinimumFontSize(int); method public synchronized void setMinimumLogicalFontSize(int); method public deprecated void setNavDump(boolean); @@ -27395,10 +27419,12 @@ package android.widget { method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int); } - public class CheckBox extends android.widget.CompoundButton { + public class CheckBox extends android.widget.CompoundButton implements android.widget.ValueEditor { ctor public CheckBox(android.content.Context); ctor public CheckBox(android.content.Context, android.util.AttributeSet); ctor public CheckBox(android.content.Context, android.util.AttributeSet, int); + method public android.util.ValueModel<java.lang.Boolean> getValueModel(); + method public void setValueModel(android.util.ValueModel<java.lang.Boolean>); } public abstract interface Checkable { @@ -27571,14 +27597,16 @@ package android.widget { method public void setSize(int, int); } - public class EditText extends android.widget.TextView { + public class EditText extends android.widget.TextView implements android.widget.ValueEditor { ctor public EditText(android.content.Context); ctor public EditText(android.content.Context, android.util.AttributeSet); ctor public EditText(android.content.Context, android.util.AttributeSet, int); method public void extendSelection(int); + method public android.util.ValueModel<java.lang.CharSequence> getValueModel(); method public void selectAll(); method public void setSelection(int, int); method public void setSelection(int); + method public void setValueModel(android.util.ValueModel<java.lang.CharSequence>); } public abstract interface ExpandableListAdapter { @@ -28595,11 +28623,13 @@ package android.widget { method public abstract java.lang.Object[] getSections(); } - public class SeekBar extends android.widget.AbsSeekBar { + public class SeekBar extends android.widget.AbsSeekBar implements android.widget.ValueEditor { ctor public SeekBar(android.content.Context); ctor public SeekBar(android.content.Context, android.util.AttributeSet); ctor public SeekBar(android.content.Context, android.util.AttributeSet, int); + method public android.util.ValueModel<java.lang.Integer> getValueModel(); method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener); + method public void setValueModel(android.util.ValueModel<java.lang.Integer>); } public static abstract interface SeekBar.OnSeekBarChangeListener { @@ -29171,6 +29201,11 @@ package android.widget { method public android.widget.TextView getText2(); } + public abstract interface ValueEditor { + method public abstract android.util.ValueModel<T> getValueModel(); + method public abstract void setValueModel(android.util.ValueModel<T>); + } + public class VideoView extends android.view.SurfaceView implements android.widget.MediaController.MediaPlayerControl { ctor public VideoView(android.content.Context); ctor public VideoView(android.content.Context, android.util.AttributeSet); diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index f5f6f3b087f2..5878619220c0 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -79,7 +79,7 @@ int install(const char *pkgname, uid_t uid, gid_t gid) #ifdef HAVE_SELINUX if (selinux_android_setfilecon(libdir, pkgname, AID_SYSTEM) < 0) { - LOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno)); + ALOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno)); unlink(libdir); unlink(pkgdir); return -errno; @@ -95,7 +95,7 @@ int install(const char *pkgname, uid_t uid, gid_t gid) #ifdef HAVE_SELINUX if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) { - LOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); + ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(libdir); unlink(pkgdir); return -errno; @@ -202,7 +202,7 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona) #ifdef HAVE_SELINUX if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) { - LOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); + ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; } @@ -404,7 +404,7 @@ int protect(char *pkgname, gid_t gid) #ifdef HAVE_SELINUX if (selinux_android_setfilecon(pkgpath, pkgname, s.st_uid) < 0) { - LOGE("cannot setfilecon dir '%s': %s\n", pkgpath, strerror(errno)); + ALOGE("cannot setfilecon dir '%s': %s\n", pkgpath, strerror(errno)); return -1; } #endif diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f20fd337695f..809acac8f7ea 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2708,7 +2708,12 @@ public class Activity extends ContextThemeWrapper // metadata is available. Intent upIntent = getParentActivityIntent(); if (upIntent != null) { - if (shouldUpRecreateTask(upIntent)) { + if (mActivityInfo.taskAffinity == null) { + // Activities with a null affinity are special; they really shouldn't + // specify a parent activity intent in the first place. Just finish + // the current activity and call it a day. + finish(); + } else if (shouldUpRecreateTask(upIntent)) { TaskStackBuilder b = TaskStackBuilder.create(this); onCreateNavigateUpTaskStack(b); onPrepareNavigateUpTaskStack(b); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7242029a7c03..7011bc172264 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -70,6 +70,7 @@ import android.util.Log; import android.util.LogPrinter; import android.util.PrintWriterPrinter; import android.util.Slog; +import android.view.CompatibilityInfoHolder; import android.view.Display; import android.view.HardwareRenderer; import android.view.View; @@ -1527,7 +1528,9 @@ public final class ActivityThread { dm = new DisplayMetrics(); mDisplayMetrics.put(ci, dm); } - Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay(); + CompatibilityInfoHolder cih = new CompatibilityInfoHolder(); + cih.set(ci); + Display d = WindowManagerImpl.getDefault().makeCompatible(cih).getDefaultDisplay(); d.getMetrics(dm); //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h=" // + metrics.heightPixels + " den=" + metrics.density diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4a75c05b2516..9364a575ebb1 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -489,7 +489,8 @@ class ContextImpl extends Context { registerService(WINDOW_SERVICE, new ServiceFetcher() { public Object getService(ContextImpl ctx) { - return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo); + return WindowManagerImpl.getDefault().makeCompatible( + ctx.mPackageInfo.mCompatibilityInfo); }}); } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index b0cc37b90e85..1bf7785bc668 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -22,6 +22,8 @@ import android.animation.AnimatorListenerAdapter; import android.content.res.Configuration; import android.content.res.TypedArray; import android.os.Bundle; +// TODO(cmautner): remove after fixing 6829431. +import android.os.Debug; import android.os.Handler; import android.os.Looper; import android.os.Parcel; @@ -383,7 +385,8 @@ final class FragmentManagerState implements Parcelable { * Container for fragments associated with an activity. */ final class FragmentManagerImpl extends FragmentManager { - static boolean DEBUG = false; + // TODO(cmautner): restore to false after fixing 6829431. + static boolean DEBUG = true; static final String TAG = "FragmentManager"; static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state"; @@ -732,6 +735,10 @@ final class FragmentManagerImpl extends FragmentManager { void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { + // TODO(cmautner): remove after fixing 6829431. + if (DEBUG) Log.v(TAG, "moveToState: " + f + + " oldState=" + f.mState + " newState=" + newState + + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5)); // Fragments that are not currently added will sit in the onCreate() state. if (!f.mAdded && newState > Fragment.CREATED) { newState = Fragment.CREATED; diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 46153e7634bf..c2cb1ffaf0da 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1674,9 +1674,6 @@ public class InputMethodService extends AbstractInputMethodService { /** * Show the input method. This is a call back to the * IMF to handle showing the input method. - * Close this input method's soft input area, removing it from the display. - * The input method will continue running, but the user can no longer use - * it to generate input by touching the screen. * @param flags Provides additional operating flags. Currently may be * 0 or have the {@link InputMethodManager#SHOW_FORCED * InputMethodManager.} bit set. diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 318c0ae00bbb..b6e606c50bae 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -542,14 +542,18 @@ public final class PowerManager { private void acquireLocked() { if (!mRefCounted || mCount++ == 0) { + // Do this even if the wake lock is already thought to be held (mHeld == true) + // because non-reference counted wake locks are not always properly released. + // For example, the keyguard's wake lock might be forcibly released by the + // power manager without the keyguard knowing. A subsequent call to acquire + // should immediately acquire the wake lock once again despite never having + // been explicitly released by the keyguard. mHandler.removeCallbacks(mReleaser); - if (!mHeld) { - try { - mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource); - } catch (RemoteException e) { - } - mHeld = true; + try { + mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource); + } catch (RemoteException e) { } + mHeld = true; } } diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 72917394139d..a54c25bed910 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -46,15 +46,16 @@ package android.os; * such as {@link Thread#sleep(long) Thread.sleep(millls)}, * {@link Object#wait(long) Object.wait(millis)}, and * {@link System#nanoTime System.nanoTime()}. This clock is guaranteed - * to be monotonic, and is the recommended basis for the general purpose - * interval timing of user interface events, performance measurements, - * and anything else that does not need to measure elapsed time during - * device sleep. Most methods that accept a timestamp value expect the - * {@link #uptimeMillis} clock. + * to be monotonic, and is suitable for interval timing when the + * interval does not span device sleep. Most methods that accept a + * timestamp value currently expect the {@link #uptimeMillis} clock. + * + * <li> <p> {@link #elapsedRealtime} and {@link #elapsedRealtimeNano} + * return the time since the system was booted, and include deep sleep. + * This clock is guaranteed to be monotonic, and continues to tick even + * when the CPU is in power saving modes, so is the recommend basis + * for general purpose interval timing. * - * <li> <p> {@link #elapsedRealtime} is counted in milliseconds since the - * system was booted, including deep sleep. This clock should be used - * when measuring time intervals that may span periods of system sleep. * </ul> * * There are several mechanisms for controlling the timing of events: @@ -150,7 +151,14 @@ public final class SystemClock { * @return elapsed milliseconds since boot. */ native public static long elapsedRealtime(); - + + /** + * Returns nanoseconds since boot, including time spent in sleep. + * + * @return elapsed nanoseconds since boot. + */ + public static native long elapsedRealtimeNano(); + /** * Returns milliseconds running in the current thread. * diff --git a/core/java/android/util/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java new file mode 100755 index 000000000000..eb9c47d0c379 --- /dev/null +++ b/core/java/android/util/PropertyValueModel.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012 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; + +/** + * A value model for a {@link Property property} of a host object. This class can be used for + * both reflective and non-reflective property implementations. + * + * @param <H> the host type, where the host is the object that holds this property + * @param <T> the value type + * + * @see Property + * @see ValueModel + */ +public class PropertyValueModel<H, T> extends ValueModel<T> { + private final H mHost; + private final Property<H, T> mProperty; + + private PropertyValueModel(H host, Property<H, T> property) { + mProperty = property; + mHost = host; + } + + /** + * Returns the host. + * + * @return the host + */ + public H getHost() { + return mHost; + } + + /** + * Returns the property. + * + * @return the property + */ + public Property<H, T> getProperty() { + return mProperty; + } + + @Override + public Class<T> getType() { + return mProperty.getType(); + } + + @Override + public T get() { + return mProperty.get(mHost); + } + + @Override + public void set(T value) { + mProperty.set(mHost, value); + } + + /** + * Return an appropriate PropertyValueModel for this host and property. + * + * @param host the host + * @param property the property + * @return the value model + */ + public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) { + return new PropertyValueModel<H, T>(host, property); + } + + /** + * Return a PropertyValueModel for this {@code host} and a + * reflective property, constructed from this {@code propertyType} and {@code propertyName}. + * + * @param host + * @param propertyType the property type + * @param propertyName the property name + * @return a value model with this host and a reflective property with this type and name + * + * @see Property#of + */ + public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType, + String propertyName) { + return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName)); + } + + private static Class getNullaryMethodReturnType(Class c, String name) { + try { + return c.getMethod(name).getReturnType(); + } catch (NoSuchMethodException e) { + return null; + } + } + + private static Class getFieldType(Class c, String name) { + try { + return c.getField(name).getType(); + } catch (NoSuchFieldException e) { + return null; + } + } + + private static String capitalize(String name) { + if (name.isEmpty()) { + return name; + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + + /** + * Return a PropertyValueModel for this {@code host} and and {@code propertyName}. + * + * @param host the host + * @param propertyName the property name + * @return a value model with this host and a reflective property with this name + */ + public static PropertyValueModel of(Object host, String propertyName) { + Class clazz = host.getClass(); + String suffix = capitalize(propertyName); + Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix); + if (propertyType == null) { + propertyType = getNullaryMethodReturnType(clazz, "is" + suffix); + } + if (propertyType == null) { + propertyType = getFieldType(clazz, propertyName); + } + if (propertyType == null) { + throw new NoSuchPropertyException(propertyName); + } + return of(host, propertyType, propertyName); + } +} diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index c4ebec45bc04..7d33ff4af5ba 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -18,8 +18,10 @@ package android.util; import android.content.res.Resources; import android.content.res.XmlResourceParser; +import android.text.format.DateUtils; + +import com.android.internal.util.XmlUtils; -import libcore.util.ZoneInfoDB; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -28,10 +30,10 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; -import java.util.TimeZone; import java.util.Date; +import java.util.TimeZone; -import com.android.internal.util.XmlUtils; +import libcore.util.ZoneInfoDB; /** * A class containing utility methods related to time zones. @@ -245,6 +247,8 @@ public class TimeUtils { private static final Object sFormatSync = new Object(); private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5]; + private static final long LARGEST_DURATION = (1000 * DateUtils.DAY_IN_MILLIS) - 1; + static private int accumField(int amt, int suffix, boolean always, int zeropad) { if (amt > 99 || (always && zeropad >= 3)) { return 3+suffix; @@ -307,6 +311,10 @@ public class TimeUtils { duration = -duration; } + if (duration > LARGEST_DURATION) { + duration = LARGEST_DURATION; + } + int millis = (int)(duration%1000); int seconds = (int) Math.floor(duration / 1000); int days = 0, hours = 0, minutes = 0; diff --git a/core/java/android/util/ValueModel.java b/core/java/android/util/ValueModel.java new file mode 100755 index 000000000000..4789682ea496 --- /dev/null +++ b/core/java/android/util/ValueModel.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2012 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; + +/** + * A ValueModel is an abstraction for a 'slot' or place in memory in which a value + * may be stored and retrieved. A common implementation of ValueModel is a regular property of + * an object, whose value may be retrieved by calling the appropriate <em>getter</em> + * method and set by calling the corresponding <em>setter</em> method. + * + * @param <T> the value type + * + * @see PropertyValueModel + */ +public abstract class ValueModel<T> { + /** + * The empty model should be used in place of {@code null} to indicate that a + * model has not been set. The empty model has no value and does nothing when it is set. + */ + public static final ValueModel EMPTY = new ValueModel() { + @Override + public Class getType() { + return Object.class; + } + + @Override + public Object get() { + return null; + } + + @Override + public void set(Object value) { + + } + }; + + protected ValueModel() { + } + + /** + * Returns the type of this property. + * + * @return the property type + */ + public abstract Class<T> getType(); + + /** + * Returns the value of this property. + * + * @return the property value + */ + public abstract T get(); + + /** + * Sets the value of this property. + * + * @param value the new value for this property + */ + public abstract void set(T value); +}
\ No newline at end of file diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 78dc86f4dd94..6288ce514a50 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -164,8 +164,9 @@ public final class Choreographer { mHandler = new FrameHandler(looper); mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null; mLastFrameTimeNanos = Long.MIN_VALUE; - mFrameIntervalNanos = (long)(1000000000 / - new Display(Display.DEFAULT_DISPLAY, null).getRefreshRate()); + + Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); + mFrameIntervalNanos = (long)(1000000000 / d.getRefreshRate()); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index c94731201349..ce49268fec72 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -450,13 +450,5 @@ public class Display { private static final Object sStaticInit = new Object(); private static boolean sInitialized = false; private static IWindowManager sWindowManager; - - /** - * Returns a display object which uses the metric's width/height instead. - * @hide - */ - public static Display createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat) { - return new Display(displayId, compat); - } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 043d1d49fa11..697f38e8ad27 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6387,7 +6387,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, case IMPORTANT_FOR_ACCESSIBILITY_NO: return false; case IMPORTANT_FOR_ACCESSIBILITY_AUTO: - return isActionableForAccessibility() || hasListenersForAccessibility(); + return isActionableForAccessibility() || hasListenersForAccessibility() + || getAccessibilityNodeProvider() != null; default: throw new IllegalArgumentException("Unknow important for accessibility mode: " + mode); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fb0a8a4d157e..d5d1b7432c03 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -251,8 +251,6 @@ public final class ViewRootImpl implements ViewParent, CompatibilityInfoHolder mCompatibilityInfo; - /*package*/ int mAddNesting; - // These are accessed by multiple threads. final Rect mWinFrame; // frame given by window manager. diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index ec4114e6a59d..f57f05677bbf 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -18,7 +18,6 @@ package android.view; import android.app.Application; import android.content.Context; -import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.PixelFormat; @@ -27,7 +26,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.SystemProperties; -import android.util.Slog; import android.view.accessibility.AccessibilityEvent; /** @@ -119,6 +117,8 @@ public abstract class Window { */ public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content; + private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw"; + private final Context mContext; private TypedArray mWindowStyle; @@ -126,6 +126,7 @@ public abstract class Window { private WindowManager mWindowManager; private IBinder mAppToken; private String mAppName; + private boolean mHardwareAccelerated; private Window mContainer; private Window mActiveChild; private boolean mIsActive = false; @@ -471,80 +472,63 @@ public abstract class Window { boolean hardwareAccelerated) { mAppToken = appToken; mAppName = appName; + mHardwareAccelerated = hardwareAccelerated + || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false); if (wm == null) { wm = WindowManagerImpl.getDefault(); } - mWindowManager = new LocalWindowManager(wm, hardwareAccelerated); + mWindowManager = ((WindowManagerImpl)wm).makeLocal(this); } - static CompatibilityInfoHolder getCompatInfo(Context context) { - Application app = (Application)context.getApplicationContext(); - return app != null ? app.mLoadedApk.mCompatibilityInfo : new CompatibilityInfoHolder(); + CompatibilityInfoHolder getCompatibilityInfo() { + Application app = (Application)mContext.getApplicationContext(); + return app != null ? app.mLoadedApk.mCompatibilityInfo : null; } - private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper { - private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw"; - - private final boolean mHardwareAccelerated; - - LocalWindowManager(WindowManager wm, boolean hardwareAccelerated) { - super(wm, getCompatInfo(mContext)); - mHardwareAccelerated = hardwareAccelerated || - SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false); - } - - public boolean isHardwareAccelerated() { - return mHardwareAccelerated; - } - - public final void addView(View view, ViewGroup.LayoutParams params) { - // Let this throw an exception on a bad params. - WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params; - CharSequence curTitle = wp.getTitle(); - if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && - wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { - if (wp.token == null) { - View decor = peekDecorView(); - if (decor != null) { - wp.token = decor.getWindowToken(); - } + void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) { + CharSequence curTitle = wp.getTitle(); + if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && + wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + if (wp.token == null) { + View decor = peekDecorView(); + if (decor != null) { + wp.token = decor.getWindowToken(); } - if (curTitle == null || curTitle.length() == 0) { - String title; - if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) { - title="Media"; - } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) { - title="MediaOvr"; - } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - title="Panel"; - } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) { - title="SubPanel"; - } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) { - title="AtchDlg"; - } else { - title=Integer.toString(wp.type); - } - if (mAppName != null) { - title += ":" + mAppName; - } - wp.setTitle(title); - } - } else { - if (wp.token == null) { - wp.token = mContainer == null ? mAppToken : mContainer.mAppToken; + } + if (curTitle == null || curTitle.length() == 0) { + String title; + if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) { + title="Media"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) { + title="MediaOvr"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { + title="Panel"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) { + title="SubPanel"; + } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) { + title="AtchDlg"; + } else { + title=Integer.toString(wp.type); } - if ((curTitle == null || curTitle.length() == 0) - && mAppName != null) { - wp.setTitle(mAppName); + if (mAppName != null) { + title += ":" + mAppName; } - } - if (wp.packageName == null) { - wp.packageName = mContext.getPackageName(); + wp.setTitle(title); + } + } else { + if (wp.token == null) { + wp.token = mContainer == null ? mAppToken : mContainer.mAppToken; } - if (mHardwareAccelerated) { - wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; + if ((curTitle == null || curTitle.length() == 0) + && mAppName != null) { + wp.setTitle(mAppName); } - super.addView(view, params); + } + if (wp.packageName == null) { + wp.packageName = mContext.getPackageName(); + } + if (mHardwareAccelerated) { + wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 0336b2fbc7b9..123d9e76071b 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -64,15 +64,7 @@ public interface WindowManager extends ViewManager { * @param view The view to be removed. */ public void removeViewImmediate(View view); - - /** - * Return true if this window manager is configured to request hardware - * accelerated windows. This does <em>not</em> guarantee that they will - * actually be accelerated, since that depends on the device supporting them. - * @hide - */ - public boolean isHardwareAccelerated(); - + public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable { /** diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index dd6b5371d479..dedee97fa5b1 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -18,9 +18,7 @@ package android.view; import android.app.ActivityManager; import android.content.ComponentCallbacks2; -import android.content.res.CompatibilityInfo; import android.content.res.Configuration; -import android.graphics.PixelFormat; import android.opengl.ManagedEGLContext; import android.os.IBinder; import android.os.SystemProperties; @@ -31,7 +29,6 @@ import android.view.inputmethod.InputMethodManager; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.PrintWriter; -import java.util.HashMap; final class WindowLeaked extends AndroidRuntimeException { public WindowLeaked(String msg) { @@ -44,7 +41,7 @@ final class WindowLeaked extends AndroidRuntimeException { * the ViewManager interface, allowing you to add any View subclass as a * top-level window on the screen. Additional window manager specific layout * parameters are defined for control over how windows are displayed. - * It also implemens the WindowManager interface, allowing you to control the + * It also implements the WindowManager interface, allowing you to control the * displays attached to the device. * * <p>Applications will not normally use WindowManager directly, instead relying @@ -60,20 +57,25 @@ final class WindowLeaked extends AndroidRuntimeException { * @hide */ public class WindowManagerImpl implements WindowManager { + private static final String TAG = "WindowManager"; + /** * The user is navigating with keys (not the touch screen), so * navigational focus should be shown. */ public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1; + /** * This is the first time the window is being drawn, * so the client must call drawingFinished() when done */ public static final int RELAYOUT_RES_FIRST_TIME = 0x2; + /** * The window manager has changed the surface from the last call. */ public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4; + /** * The window manager is currently animating. It will call * IWindow.doneAnimating() when done. @@ -108,262 +110,268 @@ public class WindowManagerImpl implements WindowManager { public static final int ADD_MULTIPLE_SINGLETON = -7; public static final int ADD_PERMISSION_DENIED = -8; - private View[] mViews; - private ViewRootImpl[] mRoots; - private WindowManager.LayoutParams[] mParams; - private boolean mNeedsEglTerminate; + private static WindowManagerImpl sDefaultWindowManager; - private Runnable mSystemPropertyUpdater = null; + private final WindowManagerState mState; + private final Window mParentWindow; + private final CompatibilityInfoHolder mCompatibilityInfo; + private final Display mDefaultDisplay; - private final static Object sLock = new Object(); - private final static WindowManagerImpl sWindowManager = new WindowManagerImpl(); - private final static HashMap<CompatibilityInfo, WindowManager> sCompatWindowManagers - = new HashMap<CompatibilityInfo, WindowManager>(); + private WindowManagerImpl(WindowManagerState state, Window parentWindow, + CompatibilityInfoHolder compatibilityInfo) { + mState = state; + mParentWindow = parentWindow; + mCompatibilityInfo = compatibilityInfo; + mDefaultDisplay = mState.getDefaultDisplay(mCompatibilityInfo); + } - static class CompatModeWrapper implements WindowManager { - private final WindowManagerImpl mWindowManager; - private final Display mDefaultDisplay; - private final CompatibilityInfoHolder mCompatibilityInfo; - - CompatModeWrapper(WindowManager wm, CompatibilityInfoHolder ci) { - mWindowManager = wm instanceof CompatModeWrapper - ? ((CompatModeWrapper)wm).mWindowManager : (WindowManagerImpl)wm; - - // Use the original display if there is no compatibility mode - // to apply, or the underlying window manager is already a - // compatibility mode wrapper. (We assume that if it is a - // wrapper, it is applying the same compatibility mode.) - if (ci == null) { - mDefaultDisplay = mWindowManager.getDefaultDisplay(); - } else { - //mDefaultDisplay = mWindowManager.getDefaultDisplay(); - mDefaultDisplay = Display.createCompatibleDisplay( - mWindowManager.getDefaultDisplay().getDisplayId(), ci); + public static WindowManagerImpl getDefault() { + synchronized (WindowManagerImpl.class) { + if (sDefaultWindowManager == null) { + sDefaultWindowManager = new WindowManagerImpl( + new WindowManagerState(), null, null); } - - mCompatibilityInfo = ci; - } - - @Override - public void addView(View view, android.view.ViewGroup.LayoutParams params) { - mWindowManager.addView(view, params, mCompatibilityInfo); + return sDefaultWindowManager; } + } - @Override - public void updateViewLayout(View view, android.view.ViewGroup.LayoutParams params) { - mWindowManager.updateViewLayout(view, params); + public WindowManagerImpl makeLocal(Window parentWindow) { + return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo()); + } + public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) { + if (compatInfo == mCompatibilityInfo) { + return this; } - - @Override - public void removeView(View view) { - mWindowManager.removeView(view); + if (compatInfo == null && mParentWindow == null) { + return getDefault(); } + return new WindowManagerImpl(mState, mParentWindow, compatInfo); + } - @Override - public Display getDefaultDisplay() { - return mDefaultDisplay; - } + @Override + public void addView(View view, ViewGroup.LayoutParams params) { + mState.addView(view, params, mParentWindow, mCompatibilityInfo); + } - @Override - public void removeViewImmediate(View view) { - mWindowManager.removeViewImmediate(view); - } + @Override + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + mState.updateViewLayout(view, params); + } - @Override - public boolean isHardwareAccelerated() { - return mWindowManager.isHardwareAccelerated(); - } + @Override + public void removeView(View view) { + mState.removeView(view, false); + } + @Override + public void removeViewImmediate(View view) { + mState.removeView(view, true); } - public static WindowManagerImpl getDefault() { - return sWindowManager; + @Override + public Display getDefaultDisplay() { + return mDefaultDisplay; } - public static WindowManager getDefault(CompatibilityInfo compatInfo) { - CompatibilityInfoHolder cih = new CompatibilityInfoHolder(); - cih.set(compatInfo); - if (cih.getIfNeeded() == null) { - return sWindowManager; - } + public void closeAll(IBinder token, String who, String what) { + mState.closeAll(token, who, what); + } - synchronized (sLock) { - // NOTE: It would be cleaner to move the implementation of - // WindowManagerImpl into a static inner class, and have this - // public impl just call into that. Then we can make multiple - // instances of WindowManagerImpl for compat mode rather than - // having to make wrappers. - WindowManager wm = sCompatWindowManagers.get(compatInfo); - if (wm == null) { - wm = new CompatModeWrapper(sWindowManager, cih); - sCompatWindowManagers.put(compatInfo, wm); - } - return wm; - } + public void startTrimMemory(int level) { + mState.startTrimMemory(level); } - public static WindowManager getDefault(CompatibilityInfoHolder compatInfo) { - return new CompatModeWrapper(sWindowManager, compatInfo); + public void endTrimMemory() { + mState.endTrimMemory(); } - - public boolean isHardwareAccelerated() { - return false; + + public void trimLocalMemory() { + mState.trimLocalMemory(); } - - public void addView(View view) { - addView(view, new WindowManager.LayoutParams( - WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE)); + + public void dumpGfxInfo(FileDescriptor fd) { + mState.dumpGfxInfo(fd); } - public void addView(View view, ViewGroup.LayoutParams params) { - addView(view, params, null, false); + public void setStoppedState(IBinder token, boolean stopped) { + mState.setStoppedState(token, stopped); } - - public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih) { - addView(view, params, cih, false); + + public void reportNewConfiguration(Configuration config) { + mState.reportNewConfiguration(config); } - - private void addView(View view, ViewGroup.LayoutParams params, - CompatibilityInfoHolder cih, boolean nest) { - if (false) Log.v("WindowManager", "addView view=" + view); - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException( - "Params must be WindowManager.LayoutParams"); + static final class WindowManagerState { + private final Display mDefaultDisplay; + + private View[] mViews; + private ViewRootImpl[] mRoots; + private WindowManager.LayoutParams[] mParams; + private boolean mNeedsEglTerminate; + + private Runnable mSystemPropertyUpdater; + + public WindowManagerState() { + mDefaultDisplay = new Display(Display.DEFAULT_DISPLAY, null); } - final WindowManager.LayoutParams wparams - = (WindowManager.LayoutParams)params; - - ViewRootImpl root; - View panelParentView = null; - - synchronized (this) { - // Start watching for system property changes. - if (mSystemPropertyUpdater == null) { - mSystemPropertyUpdater = new Runnable() { - @Override public void run() { - synchronized (this) { + public Display getDefaultDisplay(CompatibilityInfoHolder compatInfo) { + if (compatInfo == null) { + return mDefaultDisplay; + } + return new Display(Display.DEFAULT_DISPLAY, compatInfo); + } + + public void addView(View view, ViewGroup.LayoutParams params, Window parentWindow, + CompatibilityInfoHolder cih) { + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + + final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; + if (parentWindow != null) { + parentWindow.adjustLayoutParamsForSubWindow(wparams); + } + + ViewRootImpl root; + View panelParentView = null; + + synchronized (this) { + // Start watching for system property changes. + if (mSystemPropertyUpdater == null) { + mSystemPropertyUpdater = new Runnable() { + @Override public void run() { synchronized (this) { - for (ViewRootImpl root : mRoots) { - root.loadSystemProperties(); + synchronized (this) { + for (ViewRootImpl root : mRoots) { + root.loadSystemProperties(); + } } } } - } - }; - SystemProperties.addChangeCallback(mSystemPropertyUpdater); - } + }; + SystemProperties.addChangeCallback(mSystemPropertyUpdater); + } - // Here's an odd/questionable case: if someone tries to add a - // view multiple times, then we simply bump up a nesting count - // and they need to remove the view the corresponding number of - // times to have it actually removed from the window manager. - // This is useful specifically for the notification manager, - // which can continually add/remove the same view as a - // notification gets updated. - int index = findViewLocked(view, false); - if (index >= 0) { - if (!nest) { + int index = findViewLocked(view, false); + if (index >= 0) { throw new IllegalStateException("View " + view + " has already been added to the window manager."); } - root = mRoots[index]; - root.mAddNesting++; - // Update layout parameters. - view.setLayoutParams(wparams); - root.setLayoutParams(wparams, true); - return; - } - - // If this is a panel window, then find the window it is being - // attached to for future reference. - if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && - wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { - final int count = mViews != null ? mViews.length : 0; - for (int i=0; i<count; i++) { - if (mRoots[i].mWindow.asBinder() == wparams.token) { - panelParentView = mViews[i]; + + // If this is a panel window, then find the window it is being + // attached to for future reference. + if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && + wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + final int count = mViews != null ? mViews.length : 0; + for (int i=0; i<count; i++) { + if (mRoots[i].mWindow.asBinder() == wparams.token) { + panelParentView = mViews[i]; + } } } + + root = new ViewRootImpl(view.getContext()); + if (cih == null) { + root.mCompatibilityInfo = new CompatibilityInfoHolder(); + } else { + root.mCompatibilityInfo = cih; + } + + view.setLayoutParams(wparams); + + if (mViews == null) { + index = 1; + mViews = new View[1]; + mRoots = new ViewRootImpl[1]; + mParams = new WindowManager.LayoutParams[1]; + } else { + index = mViews.length + 1; + Object[] old = mViews; + mViews = new View[index]; + System.arraycopy(old, 0, mViews, 0, index-1); + old = mRoots; + mRoots = new ViewRootImpl[index]; + System.arraycopy(old, 0, mRoots, 0, index-1); + old = mParams; + mParams = new WindowManager.LayoutParams[index]; + System.arraycopy(old, 0, mParams, 0, index-1); + } + index--; + + mViews[index] = view; + mRoots[index] = root; + mParams[index] = wparams; } - - root = new ViewRootImpl(view.getContext()); - root.mAddNesting = 1; - if (cih == null) { - root.mCompatibilityInfo = new CompatibilityInfoHolder(); - } else { - root.mCompatibilityInfo = cih; + + // do this last because it fires off messages to start doing things + root.setView(view, wparams, panelParentView); + } + + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } + final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; + view.setLayoutParams(wparams); - - if (mViews == null) { - index = 1; - mViews = new View[1]; - mRoots = new ViewRootImpl[1]; - mParams = new WindowManager.LayoutParams[1]; - } else { - index = mViews.length + 1; - Object[] old = mViews; - mViews = new View[index]; - System.arraycopy(old, 0, mViews, 0, index-1); - old = mRoots; - mRoots = new ViewRootImpl[index]; - System.arraycopy(old, 0, mRoots, 0, index-1); - old = mParams; - mParams = new WindowManager.LayoutParams[index]; - System.arraycopy(old, 0, mParams, 0, index-1); - } - index--; - mViews[index] = view; - mRoots[index] = root; - mParams[index] = wparams; + synchronized (this) { + int index = findViewLocked(view, true); + ViewRootImpl root = mRoots[index]; + mParams[index] = wparams; + root.setLayoutParams(wparams, false); + } } - // do this last because it fires off messages to start doing things - root.setView(view, wparams, panelParentView); - } - public void updateViewLayout(View view, ViewGroup.LayoutParams params) { - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + public void removeView(View view, boolean immediate) { + synchronized (this) { + int index = findViewLocked(view, true); + View curView = removeViewLocked(index, immediate); + if (curView == view) { + return; + } + + throw new IllegalStateException("Calling with view " + view + + " but the ViewAncestor is attached to " + curView); + } } - final WindowManager.LayoutParams wparams - = (WindowManager.LayoutParams)params; - - view.setLayoutParams(wparams); + public void closeAll(IBinder token, String who, String what) { + synchronized (this) { + if (mViews == null) + return; + + int count = mViews.length; + //Log.i("foo", "Closing all windows of " + token); + for (int i=0; i<count; i++) { + //Log.i("foo", "@ " + i + " token " + mParams[i].token + // + " view " + mRoots[i].getView()); + if (token == null || mParams[i].token == token) { + ViewRootImpl root = mRoots[i]; - synchronized (this) { - int index = findViewLocked(view, true); - ViewRootImpl root = mRoots[index]; - mParams[index] = wparams; - root.setLayoutParams(wparams, false); - } - } + //Log.i("foo", "Force closing " + root); + if (who != null) { + WindowLeaked leak = new WindowLeaked( + what + " " + who + " has leaked window " + + root.getView() + " that was originally added here"); + leak.setStackTrace(root.getLocation().getStackTrace()); + Log.e(TAG, leak.getMessage(), leak); + } - public void removeView(View view) { - synchronized (this) { - int index = findViewLocked(view, true); - View curView = removeViewLocked(index); - if (curView == view) { - return; + removeViewLocked(i, false); + i--; + count--; + } + } } - - throw new IllegalStateException("Calling with view " + view - + " but the ViewAncestor is attached to " + curView); } - } - public void removeViewImmediate(View view) { - synchronized (this) { - int index = findViewLocked(view, true); + private View removeViewLocked(int index, boolean immediate) { ViewRootImpl root = mRoots[index]; - View curView = root.getView(); - - root.mAddNesting = 0; + View view = root.getView(); if (view != null) { InputMethodManager imm = InputMethodManager.getInstance(view.getContext()); @@ -371,289 +379,191 @@ public class WindowManagerImpl implements WindowManager { imm.windowDismissed(mViews[index].getWindowToken()); } } + root.die(immediate); - root.die(true); - finishRemoveViewLocked(curView, index); - if (curView == view) { - return; - } - - throw new IllegalStateException("Calling with view " + view - + " but the ViewAncestor is attached to " + curView); - } - } - - View removeViewLocked(int index) { - ViewRootImpl root = mRoots[index]; - View view = root.getView(); + final int count = mViews.length; + + // remove it from the list + View[] tmpViews = new View[count-1]; + removeItem(tmpViews, mViews, index); + mViews = tmpViews; + + ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1]; + removeItem(tmpRoots, mRoots, index); + mRoots = tmpRoots; + + WindowManager.LayoutParams[] tmpParams + = new WindowManager.LayoutParams[count-1]; + removeItem(tmpParams, mParams, index); + mParams = tmpParams; - // Don't really remove until we have matched all calls to add(). - root.mAddNesting--; - if (root.mAddNesting > 0) { + if (view != null) { + view.assignParent(null); + // func doesn't allow null... does it matter if we clear them? + //view.setLayoutParams(null); + } return view; } - if (view != null) { - InputMethodManager imm = InputMethodManager.getInstance(view.getContext()); - if (imm != null) { - imm.windowDismissed(mViews[index].getWindowToken()); + private static void removeItem(Object[] dst, Object[] src, int index) { + if (dst.length > 0) { + if (index > 0) { + System.arraycopy(src, 0, dst, 0, index); + } + if (index < dst.length) { + System.arraycopy(src, index+1, dst, index, src.length-index-1); + } } } - root.die(false); - finishRemoveViewLocked(view, index); - return view; - } - - void finishRemoveViewLocked(View view, int index) { - final int count = mViews.length; - - // remove it from the list - View[] tmpViews = new View[count-1]; - removeItem(tmpViews, mViews, index); - mViews = tmpViews; - - ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1]; - removeItem(tmpRoots, mRoots, index); - mRoots = tmpRoots; - - WindowManager.LayoutParams[] tmpParams - = new WindowManager.LayoutParams[count-1]; - removeItem(tmpParams, mParams, index); - mParams = tmpParams; - - if (view != null) { - view.assignParent(null); - // func doesn't allow null... does it matter if we clear them? - //view.setLayoutParams(null); - } - } - public void closeAll(IBinder token, String who, String what) { - synchronized (this) { - if (mViews == null) - return; - - int count = mViews.length; - //Log.i("foo", "Closing all windows of " + token); - for (int i=0; i<count; i++) { - //Log.i("foo", "@ " + i + " token " + mParams[i].token - // + " view " + mRoots[i].getView()); - if (token == null || mParams[i].token == token) { - ViewRootImpl root = mRoots[i]; - root.mAddNesting = 1; - - //Log.i("foo", "Force closing " + root); - if (who != null) { - WindowLeaked leak = new WindowLeaked( - what + " " + who + " has leaked window " - + root.getView() + " that was originally added here"); - leak.setStackTrace(root.getLocation().getStackTrace()); - Log.e("WindowManager", leak.getMessage(), leak); + private int findViewLocked(View view, boolean required) { + synchronized (this) { + if (mViews != null) { + final int count = mViews.length; + for (int i = 0; i < count; i++) { + if (mViews[i] == view) { + return i; + } } - - removeViewLocked(i); - i--; - count--; } + if (required) { + throw new IllegalArgumentException("View not attached to window manager"); + } + return -1; } } - } - /** - * @param level See {@link android.content.ComponentCallbacks} - * - * @hide - */ - public void startTrimMemory(int level) { - if (HardwareRenderer.isAvailable()) { - // On low-end gfx devices we trim when memory is moderate; - // on high-end devices we do this when low. - if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE - || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE - && !ActivityManager.isHighEndGfx(getDefaultDisplay()))) { - // Destroy all hardware surfaces and resources associated to - // known windows - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; - for (int i = 0; i < count; i++) { - mRoots[i].terminateHardwareResources(); + public void startTrimMemory(int level) { + if (HardwareRenderer.isAvailable()) { + // On low-end gfx devices we trim when memory is moderate; + // on high-end devices we do this when low. + if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE + || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE + && !ActivityManager.isHighEndGfx(mDefaultDisplay))) { + // Destroy all hardware surfaces and resources associated to + // known windows + synchronized (this) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].terminateHardwareResources(); + } } + // Force a full memory flush + mNeedsEglTerminate = true; + HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); + return; } - // Force a full memory flush - mNeedsEglTerminate = true; - HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); - return; - } - HardwareRenderer.startTrimMemory(level); + HardwareRenderer.startTrimMemory(level); + } } - } - /** - * @hide - */ - public void endTrimMemory() { - HardwareRenderer.endTrimMemory(); + public void endTrimMemory() { + HardwareRenderer.endTrimMemory(); - if (mNeedsEglTerminate) { - ManagedEGLContext.doTerminate(); - mNeedsEglTerminate = false; + if (mNeedsEglTerminate) { + ManagedEGLContext.doTerminate(); + mNeedsEglTerminate = false; + } } - } - /** - * @hide - */ - public void trimLocalMemory() { - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; - for (int i = 0; i < count; i++) { - mRoots[i].destroyHardwareLayers(); + public void trimLocalMemory() { + synchronized (this) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].destroyHardwareLayers(); + } } } - } - /** - * @hide - */ - public void dumpGfxInfo(FileDescriptor fd) { - FileOutputStream fout = new FileOutputStream(fd); - PrintWriter pw = new PrintWriter(fout); - try { - synchronized (this) { - if (mViews != null) { - final int count = mViews.length; - - pw.println("Profile data in ms:"); + public void dumpGfxInfo(FileDescriptor fd) { + FileOutputStream fout = new FileOutputStream(fd); + PrintWriter pw = new PrintWriter(fout); + try { + synchronized (this) { + if (mViews != null) { + final int count = mViews.length; - for (int i = 0; i < count; i++) { - ViewRootImpl root = mRoots[i]; - String name = getWindowName(root); - pw.printf("\n\t%s", name); + pw.println("Profile data in ms:"); - HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer; - if (renderer != null) { - renderer.dumpGfxInfo(pw); - } - } + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + String name = getWindowName(root); + pw.printf("\n\t%s", name); - pw.println("\nView hierarchy:\n"); + HardwareRenderer renderer = + root.getView().mAttachInfo.mHardwareRenderer; + if (renderer != null) { + renderer.dumpGfxInfo(pw); + } + } - int viewsCount = 0; - int displayListsSize = 0; - int[] info = new int[2]; + pw.println("\nView hierarchy:\n"); - for (int i = 0; i < count; i++) { - ViewRootImpl root = mRoots[i]; - root.dumpGfxInfo(info); - - String name = getWindowName(root); - pw.printf(" %s\n %d views, %.2f kB of display lists", - name, info[0], info[1] / 1024.0f); - HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer; - if (renderer != null) { - pw.printf(", %d frames rendered", renderer.getFrameCount()); - } - pw.printf("\n\n"); + int viewsCount = 0; + int displayListsSize = 0; + int[] info = new int[2]; - viewsCount += info[0]; - displayListsSize += info[1]; - } + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + root.dumpGfxInfo(info); - pw.printf("\nTotal ViewRootImpl: %d\n", count); - pw.printf("Total Views: %d\n", viewsCount); - pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f); - } - } - } finally { - pw.flush(); - } - } + String name = getWindowName(root); + pw.printf(" %s\n %d views, %.2f kB of display lists", + name, info[0], info[1] / 1024.0f); + HardwareRenderer renderer = + root.getView().mAttachInfo.mHardwareRenderer; + if (renderer != null) { + pw.printf(", %d frames rendered", renderer.getFrameCount()); + } + pw.printf("\n\n"); - private static String getWindowName(ViewRootImpl root) { - return root.mWindowAttributes.getTitle() + "/" + - root.getClass().getName() + '@' + Integer.toHexString(root.hashCode()); - } + viewsCount += info[0]; + displayListsSize += info[1]; + } - public void setStoppedState(IBinder token, boolean stopped) { - synchronized (this) { - if (mViews == null) - return; - int count = mViews.length; - for (int i=0; i<count; i++) { - if (token == null || mParams[i].token == token) { - ViewRootImpl root = mRoots[i]; - root.setStopped(stopped); + pw.printf("\nTotal ViewRootImpl: %d\n", count); + pw.printf("Total Views: %d\n", viewsCount); + pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f); + } } + } finally { + pw.flush(); } } - } - - public void reportNewConfiguration(Configuration config) { - synchronized (this) { - int count = mViews.length; - config = new Configuration(config); - for (int i=0; i<count; i++) { - ViewRootImpl root = mRoots[i]; - root.requestUpdateConfiguration(config); - } - } - } - public WindowManager.LayoutParams getRootViewLayoutParameter(View view) { - ViewParent vp = view.getParent(); - while (vp != null && !(vp instanceof ViewRootImpl)) { - vp = vp.getParent(); - } - - if (vp == null) return null; - - ViewRootImpl vr = (ViewRootImpl)vp; - - int N = mRoots.length; - for (int i = 0; i < N; ++i) { - if (mRoots[i] == vr) { - return mParams[i]; - } + private static String getWindowName(ViewRootImpl root) { + return root.mWindowAttributes.getTitle() + "/" + + root.getClass().getName() + '@' + Integer.toHexString(root.hashCode()); } - - return null; - } - - public void closeAll() { - closeAll(null, null, null); - } - - public Display getDefaultDisplay() { - return new Display(Display.DEFAULT_DISPLAY, null); - } - private static void removeItem(Object[] dst, Object[] src, int index) { - if (dst.length > 0) { - if (index > 0) { - System.arraycopy(src, 0, dst, 0, index); - } - if (index < dst.length) { - System.arraycopy(src, index+1, dst, index, src.length-index-1); + public void setStoppedState(IBinder token, boolean stopped) { + synchronized (this) { + if (mViews != null) { + int count = mViews.length; + for (int i=0; i < count; i++) { + if (token == null || mParams[i].token == token) { + ViewRootImpl root = mRoots[i]; + root.setStopped(stopped); + } + } + } } } - } - private int findViewLocked(View view, boolean required) { - synchronized (this) { - final int count = mViews != null ? mViews.length : 0; - for (int i=0; i<count; i++) { - if (mViews[i] == view) { - return i; + public void reportNewConfiguration(Configuration config) { + synchronized (this) { + if (mViews != null) { + int count = mViews.length; + config = new Configuration(config); + for (int i=0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + root.requestUpdateConfiguration(config); + } } } - if (required) { - throw new IllegalArgumentException( - "View not attached to window manager"); - } - return -1; } } } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 8705d20552bb..58f0b85ea501 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -355,6 +355,9 @@ public final class InputMethodManager { } case MSG_BIND: { final InputBindResult res = (InputBindResult)msg.obj; + if (DEBUG) { + Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id); + } synchronized (mH) { if (mBindSequence < 0 || mBindSequence != res.sequence) { Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence @@ -371,6 +374,9 @@ public final class InputMethodManager { } case MSG_UNBIND: { final int sequence = msg.arg1; + if (DEBUG) { + Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence); + } boolean startInput = false; synchronized (mH) { if (mBindSequence == sequence) { @@ -403,6 +409,9 @@ public final class InputMethodManager { } case MSG_SET_ACTIVE: { final boolean active = msg.arg1 != 0; + if (DEBUG) { + Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive); + } synchronized (mH) { mActive = active; mFullscreenMode = false; @@ -420,7 +429,16 @@ public final class InputMethodManager { // Check focus again in case that "onWindowFocus" is called before // handling this message. if (mServedView != null && mServedView.hasWindowFocus()) { - checkFocus(mHasBeenInactive); + // "finishComposingText" has been already called above. So we + // should not call mServedInputConnection.finishComposingText here. + // Also, please note that this handler thread could be different + // from a thread that created mServedView. That could happen + // the current activity is running in the system process. + // In that case, we really should not call + // mServedInputConnection.finishComposingText. + if (checkFocusNoStartInput(mHasBeenInactive, false)) { + startInputInner(null, 0, 0, 0); + } } } } @@ -1231,20 +1249,16 @@ public final class InputMethodManager { } } - private void checkFocus(boolean forceNewFocus) { - if (checkFocusNoStartInput(forceNewFocus)) { - startInputInner(null, 0, 0, 0); - } - } - /** * @hide */ public void checkFocus() { - checkFocus(false); + if (checkFocusNoStartInput(false, true)) { + startInputInner(null, 0, 0, 0); + } } - private boolean checkFocusNoStartInput(boolean forceNewFocus) { + private boolean checkFocusNoStartInput(boolean forceNewFocus, boolean finishComposingText) { // This is called a lot, so short-circuit before locking. if (mServedView == mNextServedView && !forceNewFocus) { return false; @@ -1278,7 +1292,7 @@ public final class InputMethodManager { mServedConnecting = true; } - if (ic != null) { + if (finishComposingText && ic != null) { ic.finishComposingText(); } @@ -1323,7 +1337,7 @@ public final class InputMethodManager { controlFlags |= CONTROL_WINDOW_FIRST; } - if (checkFocusNoStartInput(forceNewFocus)) { + if (checkFocusNoStartInput(forceNewFocus, true)) { // We need to restart input on the current focus view. This // should be done in conjunction with telling the system service // about the window gaining focus, to help make the transition diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 1a868d5b4bf9..7a67a146f0ff 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -199,6 +199,26 @@ public abstract class WebSettings { } /** + * Sets whether the WebView requires a user gesture to play media. + * The default is true. + * + * @param require whether the WebView requires a user gesture to play media + */ + public void setMediaPlaybackRequiresUserGesture(boolean require) { + throw new MustOverrideException(); + } + + /** + * Gets whether the WebView requires a user gesture to play media. + * + * @return true if the WebView requires a user gesture to play media + * @see #setMediaPlaybackRequiresUserGesture + */ + public boolean getMediaPlaybackRequiresUserGesture() { + throw new MustOverrideException(); + } + + /** * Sets whether the WebView should use its built-in zoom mechanisms. The * built-in zoom mechanisms comprise on-screen zoom controls, which are * displayed over the WebView's content, and the use of a pinch gesture to diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java index 1288613a3918..66651f7be2a3 100644 --- a/core/java/android/webkit/WebSettingsClassic.java +++ b/core/java/android/webkit/WebSettingsClassic.java @@ -34,7 +34,7 @@ import java.util.Locale; */ public class WebSettingsClassic extends WebSettings { // TODO: Keep this up to date - private static final String PREVIOUS_VERSION = "4.0.4"; + private static final String PREVIOUS_VERSION = "4.1.1"; // WebView associated with this WebSettings. private WebViewClassic mWebView; @@ -116,6 +116,7 @@ public class WebSettingsClassic extends WebSettings { private boolean mNeedInitialFocus = true; private boolean mNavDump = false; private boolean mSupportZoom = true; + private boolean mMediaPlaybackRequiresUserGesture = true; private boolean mBuiltInZoomControls = false; private boolean mDisplayZoomControls = true; private boolean mAllowFileAccess = true; @@ -459,6 +460,25 @@ public class WebSettingsClassic extends WebSettings { } /** + * @see android.webkit.WebSettings#setMediaPlaybackRequiresUserGesture(boolean) + */ + @Override + public void setMediaPlaybackRequiresUserGesture(boolean support) { + if (mMediaPlaybackRequiresUserGesture != support) { + mMediaPlaybackRequiresUserGesture = support; + postSync(); + } + } + + /** + * @see android.webkit.WebSettings#getMediaPlaybackRequiresUserGesture() + */ + @Override + public boolean getMediaPlaybackRequiresUserGesture() { + return mMediaPlaybackRequiresUserGesture; + } + + /** * @see android.webkit.WebSettings#setBuiltInZoomControls(boolean) */ @Override diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index ad25704ff19d..6d1a423629cc 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -582,12 +582,16 @@ public class WebView extends AbsoluteLayout //------------------------------------------------------------------------- /** - * Saves the username and password for a particular host in this WebView's - * internal database. + * Sets a username and password pair for the specified host. This data is + * used by the Webview to autocomplete username and password fields in web + * forms. Note that this is unrelated to the credentials used for HTTP + * authentication. * * @param host the host that required the credentials * @param username the username for the given host * @param password the password for the given host + * @see WebViewDatabase#clearUsernamePassword + * @see WebViewDatabase#hasUsernamePassword */ public void savePassword(String host, String username, String password) { checkThread(); @@ -1254,8 +1258,10 @@ public class WebView extends AbsoluteLayout } /** - * Makes sure that clearing the form data removes the adapter from the - * currently focused textfield if there is one. + * Removes the autocomplete popup from the currently focused form field, if + * present. Note this only affects the display of the autocomplete popup, + * it does not remove any saved form data from this WebView's store. To do + * that, use {@link WebViewDatabase#clearFormData}. */ public void clearFormData() { checkThread(); diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java index 9d10d67be0f7..4f8c36e7634f 100644 --- a/core/java/android/webkit/WebViewDatabase.java +++ b/core/java/android/webkit/WebViewDatabase.java @@ -23,7 +23,7 @@ import android.content.Context; * application has stored any of the following types of browsing data and * to clear any such stored data for all WebViews in the application. * <ul> - * <li>Username/password pairs entered into web forms</li> + * <li>Username/password pairs for web forms</li> * <li>HTTP authentication username/password pairs</li> * <li>Data entered into text fields (e.g. for autocomplete suggestions)</li> * </ul> @@ -43,18 +43,23 @@ public class WebViewDatabase { } /** - * Gets whether there are any username/password combinations - * from web pages saved. + * Gets whether there are any saved username/password pairs for web forms. + * Note that these are unrelated to HTTP authentication credentials. * - * @return true if there are any username/passwords used in web - * forms saved + * @return true if there are any saved username/password pairs + * @see WebView#savePassword + * @see clearUsernamePassword */ public boolean hasUsernamePassword() { throw new MustOverrideException(); } /** - * Clears any username/password combinations saved from web forms. + * Clears any saved username/password pairs for web forms. + * Note that these are unrelated to HTTP authentication credentials. + * + * @see WebView#savePassword + * @see hasUsernamePassword */ public void clearUsernamePassword() { throw new MustOverrideException(); @@ -77,16 +82,19 @@ public class WebViewDatabase { } /** - * Gets whether there is any previously-entered form data saved. + * Gets whether there is any saved data for web forms. * - * @return true if there is form data saved + * @return whether there is any saved data for web forms + * @see clearFormData */ public boolean hasFormData() { throw new MustOverrideException(); } /** - * Clears any stored previously-entered form data. + * Clears any saved data for web forms. + * + * @see hasFormData */ public void clearFormData() { throw new MustOverrideException(); diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 73ae9109b517..2fc9b39d91da 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -16,14 +16,23 @@ package android.webkit; +import android.os.Build; +import android.os.StrictMode; +import android.os.SystemProperties; import android.util.Log; +import dalvik.system.PathClassLoader; + /** * Top level factory, used creating all the main WebView implementation classes. */ class WebViewFactory { // Default Provider factory class name. - private static final String DEFAULT_WEB_VIEW_FACTORY = "android.webkit.WebViewClassic$Factory"; + // TODO: When the Chromium powered WebView is ready, it should be the default factory class. + private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory"; + private static final String CHROMIUM_WEBVIEW_FACTORY = + "com.android.webviewchromium.WebViewChromiumFactoryProvider"; + private static final String CHROMIUM_WEBVIEW_JAR = "/system/framework/webviewchromium.jar"; private static final String LOGTAG = "WebViewFactory"; @@ -38,18 +47,45 @@ class WebViewFactory { // us honest and minimize usage of WebViewClassic internals when binding the proxy. if (sProviderInstance != null) return sProviderInstance; - sProviderInstance = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY); + // For debug builds, we allow a system property to specify that we should use the + // Chromium powered WebView. This enables us to switch between implementations + // at runtime. For user (release) builds, don't allow this. + if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("webview.use_chromium", false)) { + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + sProviderInstance = loadChromiumProvider(); + if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + } + if (sProviderInstance == null) { - if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage"); - sProviderInstance = new WebViewClassic.Factory(); + if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: " + + DEFAULT_WEBVIEW_FACTORY); + sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY, + WebViewFactory.class.getClassLoader()); + if (sProviderInstance == null) { + if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage"); + sProviderInstance = new WebViewClassic.Factory(); + } } return sProviderInstance; } - private static WebViewFactoryProvider getFactoryByName(String providerName) { + // TODO: This allows us to have the legacy and Chromium WebView coexist for development + // and side-by-side testing. After transition, remove this when no longer required. + private static WebViewFactoryProvider loadChromiumProvider() { + ClassLoader clazzLoader = new PathClassLoader(CHROMIUM_WEBVIEW_JAR, null, + WebViewFactory.class.getClassLoader()); + return getFactoryByName(CHROMIUM_WEBVIEW_FACTORY, clazzLoader); + } + + private static WebViewFactoryProvider getFactoryByName(String providerName, + ClassLoader loader) { try { if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName); - Class<?> c = Class.forName(providerName); + Class<?> c = Class.forName(providerName, true, loader); if (DEBUG) Log.v(LOGTAG, "instantiating factory"); return (WebViewFactoryProvider) c.newInstance(); } catch (ClassNotFoundException e) { diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java index 858c415d0f08..6d292dcafa83 100644 --- a/core/java/android/widget/CheckBox.java +++ b/core/java/android/widget/CheckBox.java @@ -20,6 +20,7 @@ import android.content.Context; import android.util.AttributeSet; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import android.util.ValueModel; /** @@ -55,7 +56,9 @@ import android.view.accessibility.AccessibilityNodeInfo; * {@link android.R.styleable#View View Attributes} * </p> */ -public class CheckBox extends CompoundButton { +public class CheckBox extends CompoundButton implements ValueEditor<Boolean> { + private ValueModel<Boolean> mValueModel = ValueModel.EMPTY; + public CheckBox(Context context) { this(context, null); } @@ -79,4 +82,22 @@ public class CheckBox extends CompoundButton { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(CheckBox.class.getName()); } + + @Override + public ValueModel<Boolean> getValueModel() { + return mValueModel; + } + + @Override + public void setValueModel(ValueModel<Boolean> valueModel) { + mValueModel = valueModel; + setChecked(mValueModel.get()); + } + + @Override + public boolean performClick() { + boolean handled = super.performClick(); + mValueModel.set(isChecked()); + return handled; + } } diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java index 2fd876822368..8686177c6247 100644 --- a/core/java/android/widget/EditText.java +++ b/core/java/android/widget/EditText.java @@ -17,6 +17,7 @@ package android.widget; import android.content.Context; +import android.graphics.Rect; import android.text.Editable; import android.text.Selection; import android.text.Spannable; @@ -24,6 +25,7 @@ import android.text.TextUtils; import android.text.method.ArrowKeyMovementMethod; import android.text.method.MovementMethod; import android.util.AttributeSet; +import android.util.ValueModel; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @@ -47,7 +49,9 @@ import android.view.accessibility.AccessibilityNodeInfo; * {@link android.R.styleable#TextView TextView Attributes}, * {@link android.R.styleable#View View Attributes} */ -public class EditText extends TextView { +public class EditText extends TextView implements ValueEditor<CharSequence> { + private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY; + public EditText(Context context) { this(context, null); } @@ -128,4 +132,21 @@ public class EditText extends TextView { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(EditText.class.getName()); } + + @Override + public ValueModel<CharSequence> getValueModel() { + return mValueModel; + } + + @Override + public void setValueModel(ValueModel<CharSequence> valueModel) { + mValueModel = valueModel; + setText(mValueModel.get()); + } + + @Override + void sendAfterTextChanged(Editable text) { + super.sendAfterTextChanged(text); + mValueModel.set(text); + } } diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java index 2737f9414c46..a6486a827af5 100644 --- a/core/java/android/widget/SeekBar.java +++ b/core/java/android/widget/SeekBar.java @@ -18,6 +18,7 @@ package android.widget; import android.content.Context; import android.util.AttributeSet; +import android.util.ValueModel; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @@ -33,7 +34,7 @@ import android.view.accessibility.AccessibilityNodeInfo; * * @attr ref android.R.styleable#SeekBar_thumb */ -public class SeekBar extends AbsSeekBar { +public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> { /** * A callback that notifies clients when the progress level has been @@ -69,8 +70,9 @@ public class SeekBar extends AbsSeekBar { void onStopTrackingTouch(SeekBar seekBar); } + private ValueModel<Integer> mValueModel = ValueModel.EMPTY; private OnSeekBarChangeListener mOnSeekBarChangeListener; - + public SeekBar(Context context) { this(context, null); } @@ -89,9 +91,23 @@ public class SeekBar extends AbsSeekBar { if (mOnSeekBarChangeListener != null) { mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser); + if (fromUser) { + mValueModel.set(getProgress()); + } } } + @Override + public ValueModel<Integer> getValueModel() { + return mValueModel; + } + + @Override + public void setValueModel(ValueModel<Integer> valueModel) { + mValueModel = valueModel; + setProgress(mValueModel.get()); + } + /** * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also * provides notifications of when the user starts and stops a touch gesture within the SeekBar. diff --git a/core/java/android/widget/ValueEditor.java b/core/java/android/widget/ValueEditor.java new file mode 100755 index 000000000000..2b91abf9b8ff --- /dev/null +++ b/core/java/android/widget/ValueEditor.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 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.widget; + +import android.util.ValueModel; + +/** + * An interface for editors of simple values. Classes implementing this interface are normally + * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable + * user interface to display and edit values of the specified type. This interface is + * intended to describe editors for simple types, like {@code boolean}, {@code int} or + * {@code String}, where the values themselves are immutable. + * <p> + * For example, {@link android.widget.CheckBox CheckBox} implements + * this interface for the Boolean type as it is capable of providing an appropriate + * mechanism for displaying and changing the value of a Boolean property. + * + * @param <T> the value type that this editor supports + */ +public interface ValueEditor<T> { + /** + * Return the last value model that was set. If no value model has been set, the editor + * should return the value {@link android.util.ValueModel#EMPTY}. + * + * @return the value model + */ + public ValueModel<T> getValueModel(); + + /** + * Sets the value model for this editor. When the value model is set, the editor should + * retrieve the value from the value model, using {@link android.util.ValueModel#get()}, + * and set its internal state accordingly. Likewise, when the editor's internal state changes + * it should update the value model by calling {@link android.util.ValueModel#set(T)} + * with the appropriate value. + * + * @param valueModel the new value model for this editor. + */ + public void setValueModel(ValueModel<T> valueModel); +} diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 7334ac304af1..84fe8cefa784 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -76,6 +76,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte private int mIconDpi; private int mIconSize; private int mMaxColumns; + private int mLastSelected = GridView.INVALID_POSITION; private boolean mRegistered; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @@ -247,6 +248,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte if (mAlwaysUseOption) { final int checkedPos = mGrid.getCheckedItemPosition(); final boolean enabled = checkedPos != GridView.INVALID_POSITION; + mLastSelected = checkedPos; mAlwaysButton.setEnabled(enabled); mOnceButton.setEnabled(enabled); if (enabled) { @@ -257,14 +259,15 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - if (mAlwaysUseOption) { - final int checkedPos = mGrid.getCheckedItemPosition(); - final boolean enabled = checkedPos != GridView.INVALID_POSITION; - mAlwaysButton.setEnabled(enabled); - mOnceButton.setEnabled(enabled); - if (enabled) { + final int checkedPos = mGrid.getCheckedItemPosition(); + final boolean hasValidSelection = checkedPos != GridView.INVALID_POSITION; + if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) { + mAlwaysButton.setEnabled(hasValidSelection); + mOnceButton.setEnabled(hasValidSelection); + if (hasValidSelection) { mGrid.smoothScrollToPosition(checkedPos); } + mLastSelected = checkedPos; } else { startSelected(position, false); } @@ -371,7 +374,8 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte void showAppDetails(ResolveInfo ri) { Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS") - .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)); + .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(in); } diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java new file mode 100644 index 000000000000..154b16bf5bb5 --- /dev/null +++ b/core/java/com/android/internal/net/VpnProfile.java @@ -0,0 +1,123 @@ +/* + * 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.internal.net; + +import java.nio.charset.Charsets; + +/** + * Parcel-like entity class for VPN profiles. To keep things simple, all + * fields are package private. Methods are provided for serialization, so + * storage can be implemented easily. Two rules are set for this class. + * First, all fields must be kept non-null. Second, always make a copy + * using clone() before modifying. + * + * @hide + */ +public class VpnProfile implements Cloneable { + // Match these constants with R.array.vpn_types. + public static final int TYPE_PPTP = 0; + public static final int TYPE_L2TP_IPSEC_PSK = 1; + public static final int TYPE_L2TP_IPSEC_RSA = 2; + public static final int TYPE_IPSEC_XAUTH_PSK = 3; + public static final int TYPE_IPSEC_XAUTH_RSA = 4; + public static final int TYPE_IPSEC_HYBRID_RSA = 5; + public static final int TYPE_MAX = 5; + + // Entity fields. + public final String key; // -1 + public String name = ""; // 0 + public int type = TYPE_PPTP; // 1 + public String server = ""; // 2 + public String username = ""; // 3 + public String password = ""; // 4 + public String dnsServers = ""; // 5 + public String searchDomains = ""; // 6 + public String routes = ""; // 7 + public boolean mppe = true; // 8 + public String l2tpSecret = ""; // 9 + public String ipsecIdentifier = "";// 10 + public String ipsecSecret = ""; // 11 + public String ipsecUserCert = ""; // 12 + public String ipsecCaCert = ""; // 13 + public String ipsecServerCert = "";// 14 + + // Helper fields. + public boolean saveLogin = false; + + public VpnProfile(String key) { + this.key = key; + } + + public static VpnProfile decode(String key, byte[] value) { + try { + if (key == null) { + return null; + } + + String[] values = new String(value, Charsets.UTF_8).split("\0", -1); + // There can be 14 or 15 values in ICS MR1. + if (values.length < 14 || values.length > 15) { + return null; + } + + VpnProfile profile = new VpnProfile(key); + profile.name = values[0]; + profile.type = Integer.valueOf(values[1]); + if (profile.type < 0 || profile.type > TYPE_MAX) { + return null; + } + profile.server = values[2]; + profile.username = values[3]; + profile.password = values[4]; + profile.dnsServers = values[5]; + profile.searchDomains = values[6]; + profile.routes = values[7]; + profile.mppe = Boolean.valueOf(values[8]); + profile.l2tpSecret = values[9]; + profile.ipsecIdentifier = values[10]; + profile.ipsecSecret = values[11]; + profile.ipsecUserCert = values[12]; + profile.ipsecCaCert = values[13]; + profile.ipsecServerCert = (values.length > 14) ? values[14] : ""; + + profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty(); + return profile; + } catch (Exception e) { + // ignore + } + return null; + } + + public byte[] encode() { + StringBuilder builder = new StringBuilder(name); + builder.append('\0').append(type); + builder.append('\0').append(server); + builder.append('\0').append(saveLogin ? username : ""); + builder.append('\0').append(saveLogin ? password : ""); + builder.append('\0').append(dnsServers); + builder.append('\0').append(searchDomains); + builder.append('\0').append(routes); + builder.append('\0').append(mppe); + builder.append('\0').append(l2tpSecret); + builder.append('\0').append(ipsecIdentifier); + builder.append('\0').append(ipsecSecret); + builder.append('\0').append(ipsecUserCert); + builder.append('\0').append(ipsecCaCert); + builder.append('\0').append(ipsecServerCert); + return builder.toString().getBytes(Charsets.UTF_8); + } +} diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 7da8d4659646..8ff39d69d8cb 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -1370,6 +1370,7 @@ public class ActionBarView extends AbsActionBarView { int upOffset = 0; if (mUpView.getVisibility() != GONE) { final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); + upLp.onResolveLayoutDirection(layoutDirection); final int upHeight = mUpView.getMeasuredHeight(); final int upWidth = mUpView.getMeasuredWidth(); upOffset = upLp.leftMargin + upWidth + upLp.rightMargin; diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp index eb99d2bbce43..40443ffa0c4f 100644 --- a/core/jni/android_os_SELinux.cpp +++ b/core/jni/android_os_SELinux.cpp @@ -90,14 +90,14 @@ namespace android { int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionOccurred() != NULL) { - LOGE("There was an issue with retrieving the file descriptor"); + ALOGE("There was an issue with retrieving the file descriptor"); goto bail; } if (getpeercon(fd, &context) == -1) goto bail; - LOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context); + ALOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context); securityString = env->NewStringUTF(context); @@ -139,7 +139,7 @@ namespace android { if ((ret = setfscreatecon(securityContext)) == -1) goto bail; - LOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context); + ALOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context); bail: if (constant_securityContext != NULL) @@ -185,7 +185,7 @@ namespace android { if ((ret = setfilecon(objectPath, newCon)) == -1) goto bail; - LOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath); + ALOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath); bail: env->ReleaseStringUTFChars(path, objectPath); @@ -224,7 +224,7 @@ namespace android { if (getfilecon(objectPath, &context) == -1) goto bail; - LOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath); + ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath); securityString = env->NewStringUTF(context); @@ -259,7 +259,7 @@ namespace android { if (getcon(&context) == -1) goto bail; - LOGV("getCon: Successfully retrieved context '%s'", context); + ALOGV("getCon: Successfully retrieved context '%s'", context); securityString = env->NewStringUTF(context); @@ -295,7 +295,7 @@ namespace android { if (getpidcon(checkPid, &context) == -1) goto bail; - LOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid); + ALOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid); securityString = env->NewStringUTF(context); @@ -442,7 +442,7 @@ namespace android { accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL); - LOGV("selinux_check_access returned %d", accessGranted); + ALOGV("selinux_check_access returned %d", accessGranted); env->ReleaseStringUTFChars(scon, const_scon); env->ReleaseStringUTFChars(tcon, const_tcon); diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp index 66d58cd4a470..78f989a2974f 100644 --- a/core/jni/android_os_SystemClock.cpp +++ b/core/jni/android_os_SystemClock.cpp @@ -112,6 +112,15 @@ static jlong android_os_SystemClock_currentTimeMicro(JNIEnv* env, } /* + * public static native long elapsedRealtimeNano(); + */ +static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env, + jobject clazz) +{ + return (jlong)elapsedRealtimeNano(); +} + +/* * JNI registration. */ static JNINativeMethod gMethods[] = { @@ -128,6 +137,8 @@ static JNINativeMethod gMethods[] = { (void*) android_os_SystemClock_currentThreadTimeMicro }, { "currentTimeMicro", "()J", (void*) android_os_SystemClock_currentTimeMicro }, + { "elapsedRealtimeNano", "()J", + (void*) android_os_SystemClock_elapsedRealtimeNano }, }; int register_android_os_SystemClock(JNIEnv* env) { diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index ee3b4375de32..cae9a5bca8a3 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -246,7 +246,7 @@ <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"استرداد معلومات النوافذ"</string> <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"للسماح لأحد التطبيقات باستعادة معلومات حول النوافذ من مدير النوافذ. يمكن أن تستعيد التطبيقات الضارة معلومات الغرض منها استخدام النظام الداخلي."</string> <string name="permlab_filter_events" msgid="8675535648807427389">"تصفية الأحداث"</string> - <string name="permdesc_filter_events" msgid="8006236315888347680">"للسماح لأحد التطبيقات بتسجيل فلتر إدخال يعمل على تصفية مجموعة البث من جميع أحداث المستخدمين قبل إرسالها. يمكن أن يتحكم برنامج ضار في واجهة المستخدم النظام بدون تدخل المستخدم."</string> + <string name="permdesc_filter_events" msgid="8006236315888347680">"للسماح لأحد التطبيقات بتسجيل فلتر إدخال يعمل على تصفية مجموعة البث من جميع أحداث المستخدمين قبل إرسالها. يمكن أن يتحكم برنامج ضار في واجهة المستخدم النظام دون تدخل المستخدم."</string> <string name="permlab_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string> <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index b8a5e84c6056..95f894451818 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -246,7 +246,7 @@ <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupera informació de les finestres"</string> <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet que una aplicació recuperi informació sobre les finestres del gestor de finestres. Aplicacions malicioses podrien recuperar informació dirigida a la utilització per part del sistema intern."</string> <string name="permlab_filter_events" msgid="8675535648807427389">"filtra els esdeveniments"</string> - <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet que una aplicació registre un filtre d\'entrada per a l\'emissió de tots els esdeveniments d\'usuari abans no s\'enviïn. Aplicacions malicioses podrien controlar la IU del sistema sense la intervenció de l\'usuari."</string> + <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet que una aplicació registri un filtre d\'entrada per a l\'emissió de tots els esdeveniments d\'usuari abans no s\'enviïn. Aplicacions malicioses podrien controlar la IU del sistema sense la intervenció de l\'usuari."</string> <string name="permlab_shutdown" msgid="7185747824038909016">"apagar parcialment"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"Posa el gestor d\'activitats en estat d\'apagada. No fa una apagada completa."</string> <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 6763ed70a849..e6e85ed53274 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1294,7 +1294,7 @@ <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string> <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string> <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> - <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phones"</string> + <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> <string name="default_audio_route_name_hdmi" msgid="7986404173839007682">"HDMI audio"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 941d5c3843c8..fa98e56f3fec 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -44,7 +44,7 @@ <string name="passwordIncorrect" msgid="7612208839450128715">"رمز ورود اشتباه است."</string> <string name="mmiComplete" msgid="8232527495411698359">"MMI کامل شد."</string> <string name="badPin" msgid="9015277645546710014">"پین قدیمی که نوشتهاید صحیح نیست."</string> - <string name="badPuk" msgid="5487257647081132201">"PUK که نوشته اید صحیح نیست."</string> + <string name="badPuk" msgid="5487257647081132201">"PUK که نوشتهاید صحیح نیست."</string> <string name="mismatchPin" msgid="609379054496863419">"پینهایی که وارد کردهاید با یکدیگر مطابقت ندارند."</string> <string name="invalidPin" msgid="3850018445187475377">"یک پین بنویسید که 4 تا 8 رقم باشد."</string> <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با 8 رقم یا بیشتر تایپ کنید."</string> @@ -129,10 +129,10 @@ <string name="contentServiceSync" msgid="8353523060269335667">"همگام سازی"</string> <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگام سازی"</string> <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"تعداد موارد حذف شده <xliff:g id="CONTENT_TYPE">%s</xliff:g> بسیار زیاد است."</string> - <string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانه لوحی پر است! برخی از فایلها را حذف کنید تا فضا آزاد شود."</string> + <string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانهٔ لوحی پر است! برخی از فایلها را حذف کنید تا فضا آزاد شود."</string> <string name="low_memory" product="default" msgid="3475999286680000541">"حافظه تلفن پر است. بعضی از فایلها را حذف کنید تا فضا آزاد شود."</string> <string name="me" msgid="6545696007631404292">"من"</string> - <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینههای رایانه لوحی"</string> + <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینههای رایانهٔ لوحی"</string> <string name="power_dialog" product="default" msgid="1319919075463988638">"گزینههای تلفن"</string> <string name="silent_mode" msgid="7167703389802618663">"حالت ساکت"</string> <string name="turn_on_radio" msgid="3912793092339962371">"روشن کردن بی سیم"</string> @@ -143,14 +143,14 @@ <string name="silent_mode_vibrate" msgid="7072043388581551395">"زنگ لرزشی"</string> <string name="silent_mode_ring" msgid="8592241816194074353">"زنگ روشن"</string> <string name="shutdown_progress" msgid="2281079257329981203">"خاموش کردن..."</string> - <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانه لوحی شما خاموش میشود."</string> + <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش میشود."</string> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"گوشی شما خاموش میشود."</string> <string name="shutdown_confirm_question" msgid="2906544768881136183">"آیا میخواهید تلفن خاموش شود؟"</string> <string name="reboot_safemode_title" msgid="7054509914500140361">"راهاندازی مجدد در حالت امن"</string> - <string name="reboot_safemode_confirm" msgid="55293944502784668">"آیا میخواهید با حالت امن راهاندازی مجدد کنید؟ با این کار کلیه برنامههای شخص ثالثی که نصب کردهاید غیرفعال میشوند. با راهاندازی دوباره سیستم این برنامهها دوباره بازیابی میشوند."</string> + <string name="reboot_safemode_confirm" msgid="55293944502784668">"آیا میخواهید با حالت امن راهاندازی مجدد کنید؟ با این کار همهٔ برنامههای شخص ثالثی که نصب کردهاید غیرفعال میشوند. با راهاندازی دوباره سیستم این برنامهها دوباره بازیابی میشوند."</string> <string name="recent_tasks_title" msgid="3691764623638127888">"اخیر"</string> <string name="no_recent_tasks" msgid="8794906658732193473">"برنامههای جدید موجود نیست."</string> - <string name="global_actions" product="tablet" msgid="408477140088053665">"گزینههای رایانه لوحی"</string> + <string name="global_actions" product="tablet" msgid="408477140088053665">"گزینههای رایانهٔ لوحی"</string> <string name="global_actions" product="default" msgid="2406416831541615258">"گزینههای تلفن"</string> <string name="global_action_lock" msgid="2844945191792119712">"قفل صفحه"</string> <string name="global_action_power_off" msgid="4471879440839879722">"خاموش کردن"</string> @@ -168,7 +168,7 @@ <string name="permgrouplab_messages" msgid="7521249148445456662">"پیامهای شما"</string> <string name="permgroupdesc_messages" msgid="7821999071003699236">"پیام کوتاه، ایمیل و دیگر پیامها را بخوانید."</string> <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"اطلاعات شخصی شما"</string> - <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در رایانه لوحی."</string> + <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در رایانهٔ لوحی."</string> <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"دسترسی مستقیم به مخاطبین و تقویم ذخیره شده در گوشی."</string> <string name="permgrouplab_location" msgid="635149742436692049">"موقعیت مکانی شما"</string> <string name="permgroupdesc_location" msgid="5704679763124170100">"بر موقعیت مکانی فیزیکی خود نظارت داشته باشید."</string> @@ -176,8 +176,8 @@ <string name="permgroupdesc_network" msgid="4478299413241861987">"به ویژگیهای مختلف شبکه دسترسی داشته باشید."</string> <string name="permgrouplab_accounts" msgid="3359646291125325519">"حسابهای شما"</string> <string name="permgroupdesc_accounts" msgid="4948732641827091312">"به حسابهای موجود دسترسی داشته باشید."</string> - <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"کنترلهای سخت افزار"</string> - <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"دسترسی مستقیم به سخت افزار در گوشی."</string> + <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"کنترلهای سختافزار"</string> + <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"دسترسی مستقیم به سختافزار در گوشی."</string> <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"تماسهای تلفنی"</string> <string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"نظارت، ضبط و پردازش تماسهای تلفنی."</string> <string name="permgrouplab_systemTools" msgid="4652191644082714048">"ابزارهای سیستم"</string> @@ -208,10 +208,10 @@ <string name="permlab_sendSmsNoConfirmation" msgid="4781483105951730228">"ارسال پیامک بدون تأیید"</string> <string name="permdesc_sendSmsNoConfirmation" msgid="402569800862935907">"به برنامه اجازه میدهد پیامکها را ارسال کند. این باعث ایجاد هزینههای پیشبینی نشده میشود. برنامههای مخرب ممکن است با ارسال پیام بدون تأیید شما هزینههایی را برای شما ایجاد کنند."</string> <string name="permlab_readSms" msgid="8745086572213270480">"خواندن پیامهای نوشتاری شما (پیامک یا MMS)"</string> - <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه میدهد پیامکهای ذخیره شده در رایانه لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان میدهد همه پیامکها را صرفنظر از محتوا یا محرمانه بودن آنها بخواند."</string> + <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"به برنامه اجازه میدهد پیامکهای ذخیره شده در رایانهٔ لوحی یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان میدهد همه پیامکها را صرفنظر از محتوا یا محرمانه بودن آنها بخواند."</string> <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"به برنامه اجازه میدهد پیامکهای ذخیره شده در تلفن یا سیم کارت شما را بخواند. این ویژگی به برنامه امکان میدهد همه پیامکها را صرفنظر از محتوا یا محرمانه بودن آنها بخواند."</string> <string name="permlab_writeSms" msgid="3216950472636214774">"ویرایش پیامهای نوشتاری شما (پیامک یا MMS)"</string> - <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"به برنامه اجازه میدهد تا در پیامهای کوتاه ذخیره شده در رایانه لوحی یا سیم کارت بنویسد. برنامههای مخرب پیامهای شما را حذف میکنند."</string> + <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"به برنامه اجازه میدهد تا در پیامهای کوتاه ذخیره شده در رایانهٔ لوحی یا سیم کارت بنویسد. برنامههای مخرب پیامهای شما را حذف میکنند."</string> <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"به برنامه اجازه میدهد تا در پیامهای کوتاه ذخیره شده در تلفن یا سیم کارت بنویسد. برنامههای مخرب میتوانند پیامهای شما را حذف کنند."</string> <string name="permlab_receiveWapPush" msgid="5991398711936590410">"دریافت پیامهای نوشتاری (WAP)"</string> <string name="permdesc_receiveWapPush" msgid="748232190220583385">"به برنامه اجازه میدهد پیامهای WAP را دریافت و پردازش کند. این مجوز میتواند پیامهای ارسالی به شما را بدون نمایش آنها به شما حذف یا کنترل کند."</string> @@ -226,7 +226,7 @@ <string name="permlab_startAnyActivity" msgid="2918768238045206456">"شروع هر نوع فعالیت"</string> <string name="permdesc_startAnyActivity" msgid="997823695343584001">"به برنامه اجازه میدهد هر فعالیتی را شروع کند بدون اینکه وضعیت صادرشده یا حفاظت با مجوز در نظر گرفته شود."</string> <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"تنظیم سازگاری با صفحهٔ نمایش"</string> - <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"به برنامه کاربردی اجازه کنترل حالت سازگاری صفحهٔ نمایش برای برنامههای دیگر را میدهد. برنامههای خرابکار ممکن است باعث کارکرد نادرست دیگر برنامهها شوند."</string> + <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"به برنامهٔ کاربردی اجازه کنترل حالت سازگاری صفحهٔ نمایش برای برنامههای دیگر را میدهد. برنامههای خرابکار ممکن است باعث کارکرد نادرست دیگر برنامهها شوند."</string> <string name="permlab_setDebugApp" msgid="3022107198686584052">"فعال کردن عیبیابی برنامه"</string> <string name="permdesc_setDebugApp" msgid="4474512416299013256">"به برنامه اجازه میدهد تا عیبیابی را برای برنامهای دیگر فعال کند. برنامههای مخرب میتوانند از آن استفاده کنند تا اجرای برنامههای دیگر را متوقف کنند."</string> <string name="permlab_changeConfiguration" msgid="4162092185124234480">"تغییر تنظیمات نمایشگر سیستم"</string> @@ -244,27 +244,27 @@ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"بازیابی محتوای صفحه"</string> <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"به برنامه اجازه میدهد تا محتوای پنجره فعال را بازیابی کند. برنامههای مخرب میتوانند کل محتوای پنجره را بازیابی کنند و همه متن آنرا به غیر از گذرواژهها امتحان کنند."</string> <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"بازیابی اطلاعات پنجره"</string> - <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"به یک برنامه کاربردی اجازه میدهد که اطلاعات مربوط به پنجرهها را از مدیریت پنجره بازیابی کند. برنامههای کاربردی مخرب ممکن است اطلاعاتی که برای استفاده سیستم داخلی درنظر گرفته شدهاند را بازیابی کنند."</string> + <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"به یک برنامهٔ کاربردی اجازه میدهد که اطلاعات مربوط به پنجرهها را از مدیریت پنجره بازیابی کند. برنامههای کاربردی مخرب ممکن است اطلاعاتی که برای استفاده سیستم داخلی درنظر گرفته شدهاند را بازیابی کنند."</string> <string name="permlab_filter_events" msgid="8675535648807427389">"فیلتر کردن رویدادها"</string> - <string name="permdesc_filter_events" msgid="8006236315888347680">"به یک برنامه کاربردی اجازه میدهد یک فیلتر ورودی را که جریان تمام رویدادهای کاربران را قبل از ارسال شدن فیلتر میکند، ثبت نماید. برنامه کاربردی مخرب ممکن است رابط کاربری سیستم را بدون مداخله کاربر، کنترل کند."</string> + <string name="permdesc_filter_events" msgid="8006236315888347680">"به یک برنامهٔ کاربردی اجازه میدهد یک فیلتر ورودی را که جریان تمام رویدادهای کاربران را قبل از ارسال شدن فیلتر میکند، ثبت نماید. برنامه کاربردی مخرب ممکن است رابط کاربری سیستم را بدون مداخله کاربر، کنترل کند."</string> <string name="permlab_shutdown" msgid="7185747824038909016">"خاموش شدن جزئی"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"مدیر فعالیت را در حالت خاموشی قرار میدهد. خاموشی را به صورت کامل انجام نمیدهد."</string> <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string> <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"اجازه نمیدهد کاربر به برنامه دیگری برود."</string> - <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"نظارت و کنترل راه اندازی همه برنامه"</string> - <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"به برنامه اجازه میدهد تا نحوه راه اندازی فعالیتهای سیستم را کنترل کند. برنامههای مخرب میتوانند کاملا با سیستم سازگار شوند. این مجوز فقط برای توسعه نیاز است و برای استفاده عادی نیست."</string> + <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"نظارت و کنترل راهاندازی همه برنامه"</string> + <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"به برنامه اجازه میدهد تا نحوه راهاندازی فعالیتهای سیستم را کنترل کند. برنامههای مخرب میتوانند کاملا با سیستم سازگار شوند. این مجوز فقط برای توسعه نیاز است و برای استفاده عادی نیست."</string> <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ارسال پخش بسته حذف شده"</string> <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"به برنامه اجازه میدهد تا اعلان حذف بسته برنامه را پخش کند. برنامههای مخرب میتوانند از آن استفاده کنند تا هر برنامه در حال اجرای دیگر را از بین ببرد."</string> <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ارسال پخش دریافت شده توسط پیامک"</string> <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"به برنامه اجازه میدهد تا اعلان دریافت پیام کوتاه را پخش کند. برنامههای مخرب میتوانند از این برای جعل پیامهای کوتاه ورودی استفاده کنند."</string> <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ارسال پخش دریافت شده توسط WAP-PUSH"</string> - <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"به برنامه اجازه میدهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامههای مخرب میتوانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحه وب را با انواع مخرب جایگزین کنند."</string> + <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"به برنامه اجازه میدهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامههای مخرب میتوانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحهٔ وب را با انواع مخرب جایگزین کنند."</string> <string name="permlab_setProcessLimit" msgid="2451873664363662666">"محدود کردن تعداد فرآیندهای در حال اجرا"</string> <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"به برنامه اجازه میدهد تا حداکثر تعداد پردازشهایی را که اجرا خواهد شد کنترل کند. هرگز برای برنامههای عادی لازم نیست."</string> <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"بستن اجباری برنامههای پسزمینه"</string> <string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"به برنامه اجازه میدهد تا به محض اینکه فعالیتها به پسزمینه رفتند تمام شوند. برای برنامههای عادی نیازی نیست."</string> <string name="permlab_batteryStats" msgid="7863923071360031652">"اصلاح کردن آمار مربوط به باتری"</string> - <string name="permdesc_batteryStats" msgid="6835186932305744068">"به برنامه اجازه میدهد تا آمار جمع آوری شده باتری را تغییر دهد. برای استفاده برنامههای عادی نیست."</string> + <string name="permdesc_batteryStats" msgid="6835186932305744068">"به برنامه اجازه میدهد تا آمار جمعآوری شده باتری را تغییر دهد. برای استفاده برنامههای عادی نیست."</string> <string name="permlab_backup" msgid="470013022865453920">"کنترل نسخهٔ پشتیبان سیستم و بازیابی"</string> <string name="permdesc_backup" msgid="6912230525140589891">"به برنامه اجازه میدهد پشتیبان سیستم را کنترل کند و مکانیستم را بازیابی کند. برای استفاده برنامههای عادی نیست."</string> <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"تهیه نسخهٔ پشتیبان کامل را تأیید کرده یا عملیات را بازیابی کنید"</string> @@ -278,7 +278,7 @@ <string name="permlab_manageAppTokens" msgid="1286505717050121370">"مدیریت نشانههای برنامه"</string> <string name="permdesc_manageAppTokens" msgid="8043431713014395671">"به برنامه اجازه میدهد با ایجاد کنارگذر از سفارش عادی Z، نشانههای خود را ایجاد و مدیریت کند. برای برنامههای عادی مورد نیاز است."</string> <string name="permlab_injectEvents" msgid="1378746584023586600">"کلیدها و دکمههای کنترل را فشار دهید"</string> - <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"به برنامه اجازه میدهد تا رویدادهای ورودی خود (فشردن کلیدها و غیره) را تحویل دهد. برنامههای مخرب میتوانند از آن استفاده کنند تا کارکرد رایانه لوحی را کنترل کنند."</string> + <string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"به برنامه اجازه میدهد تا رویدادهای ورودی خود (فشردن کلیدها و غیره) را تحویل دهد. برنامههای مخرب میتوانند از آن استفاده کنند تا کارکرد رایانهٔ لوحی را کنترل کنند."</string> <string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"به برنامه اجازه میدهد تا رویدادهای ورودی خود را به برنامههای دیگر تحویل دهد (فشردن کلیدها و غیره). برنامههای مخرب میتوانند از آن برای کنترل کارکرد تلفن استفاده کنند."</string> <string name="permlab_readInputState" msgid="469428900041249234">"مواردی که مینویسید و کارهایی که انجام میدهید را ضبط کنید"</string> <string name="permdesc_readInputState" msgid="8387754901688728043">"به برنامه اجازه میدهد تا کلیدهایی را که هنگام تعامل با برنامهٔ دیگر فشار میدهید ببیند (مانند تایپ کردن گذرواژه). برای برنامههای عادی مورد نیاز نیست."</string> @@ -300,42 +300,42 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"به برنامه اجازه میدهد تا چرخش صفحه را هر وقت بخواهد تغییر دهد. برای برنامههای عادی نیاز نیست."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغییر سرعت اشارهگر"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"به برنامه اجازه میدهد تا سرعت ماوس و پد کنترل را هر وقت خواست تغییر دهد. برای برنامههای عادی نیاز نیست."</string> - <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحه کلید"</string> - <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه میدهد تا چیدمان صفحه کلید را تغییر دهد. این کار هیچگاه برای برنامههای عادی نیاز نیست."</string> + <string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"تغییر چیدمان صفحهکلید"</string> + <string name="permdesc_setKeyboardLayout" msgid="8480016771134175879">"به برنامه اجازه میدهد تا چیدمان صفحهکلید را تغییر دهد. این کار هیچگاه برای برنامههای عادی نیاز نیست."</string> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ارسال سیگنالهای Linux به برنامهها"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"به برنامه اجازه میدهد تا درخواست کند سیگنال ارائه شده به همه مراحل دائم ارسال شود."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"همیشه برنامه اجرا شود"</string> - <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان میدهد قسمتهایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامهها محدود کرده و باعث کندی رایانه لوحی میشود."</string> + <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان میدهد قسمتهایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامهها محدود کرده و باعث کندی رایانهٔ لوحی میشود."</string> <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"به برنامه امکان میدهد قسمتهایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامهها محدود کرده و باعث کندی تلفن میشود."</string> <string name="permlab_deletePackages" msgid="184385129537705938">"حذف برنامهها"</string> <string name="permdesc_deletePackages" msgid="7411480275167205081">"به برنامه اجازه میدهد تا بستههای Android را پاک کند. برنامههای مخرب میتوانند از آن استفاده کنند تا برنامههای مهم را حذف کنند."</string> <string name="permlab_clearAppUserData" msgid="274109191845842756">"حذف دادههای برنامههای دیگر"</string> <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"به برنامه اجازه میدهد تا دادههای کاربر را پاک کند."</string> - <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"حذف حافظه پنهان برنامههای دیگر"</string> - <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"به برنامه اجازه میدهد تا فایلهای حافظه پنهان را پاک کند."</string> + <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"حذف حافظهٔ پنهان برنامههای دیگر"</string> + <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"به برنامه اجازه میدهد تا فایلهای حافظهٔ پنهان را پاک کند."</string> <string name="permlab_getPackageSize" msgid="7472921768357981986">"اندازه گیری فضای حافظه برنامه"</string> - <string name="permdesc_getPackageSize" msgid="3921068154420738296">"به برنامه اجازه میدهد تا کدها، دادهها و اندازههای حافظه پنهان خود را بازیابی کند"</string> + <string name="permdesc_getPackageSize" msgid="3921068154420738296">"به برنامه اجازه میدهد تا کدها، دادهها و اندازههای حافظهٔ پنهان خود را بازیابی کند"</string> <string name="permlab_installPackages" msgid="2199128482820306924">"نصب مستقیم برنامه"</string> <string name="permdesc_installPackages" msgid="5628530972548071284">"به برنامه اجازه میدهد تا بستههای Android به روز شده یا جدید را نصب کند. برنامههای مخرب میتوانند از این استفاده کنند تا برنامههای جدید را با مجوزهای قوی اختیاری اضافه کنند."</string> - <string name="permlab_clearAppCache" msgid="7487279391723526815">"حذف تمام دادههای حافظه پنهان برنامه"</string> - <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"به برنامه اجازه میدهد تا حافظه رایانه لوحی را با حذف فایلها در فهرست حافظه پنهان برنامه آزاد کند. معمولا دسترسی برای پردازش سیستم بسیار محدود است."</string> - <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"به برنامه اجازه میدهد تا با حذف فایلها در فهرست حافظه پنهان برنامه حافظه تلفن را آزاد کند. معمولا دسترسی به پردازش سیستم بسیار محدود است."</string> + <string name="permlab_clearAppCache" msgid="7487279391723526815">"حذف تمام دادههای حافظهٔ پنهان برنامه"</string> + <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"به برنامه اجازه میدهد تا حافظه رایانهٔ لوحی را با حذف فایلها در فهرست حافظهٔ پنهان برنامه آزاد کند. معمولا دسترسی برای پردازش سیستم بسیار محدود است."</string> + <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"به برنامه اجازه میدهد تا با حذف فایلها در فهرست حافظهٔ پنهان برنامه حافظه تلفن را آزاد کند. معمولا دسترسی به پردازش سیستم بسیار محدود است."</string> <string name="permlab_movePackage" msgid="3289890271645921411">"انتقال منابع برنامه"</string> <string name="permdesc_movePackage" msgid="319562217778244524">"به برنامه اجازه میدهد تا منابع برنامه را از رسانه داخلی به رسانه خارجی و بالعکس منتقل کند."</string> <string name="permlab_readLogs" msgid="6615778543198967614">"مطالعه دادههای گزارش حساس"</string> - <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"به برنامه اجازه میدهد فایلهای مختلف گزارش سیستم را بخواند. با این کار، برنامه اطلاعات کلی مربوط به کاری که با رایانه لوحی انجام میدهید را کشف میکند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string> + <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"به برنامه اجازه میدهد فایلهای مختلف گزارش سیستم را بخواند. با این کار، برنامه اطلاعات کلی مربوط به کاری که با رایانهٔ لوحی انجام میدهید را کشف میکند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string> <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"به برنامه اجازه میدهد تا فایلهای گزارش مختلف سیستم را بخواند. این کار به برنامه اجازه میدهد اطلاعات عمومی کاری که با تلفن انجام میدهید مثلا اطلاعات خصوصی و شخصی را کشف کند."</string> <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"استفاده از هر رمزگشای رسانهای برای بازپخش"</string> <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"اجازه میدهد برنامه از هر رمزگشای رسانه نصب شدهای استفاده کند تا برای پخش رمزگشایی شود."</string> <string name="permlab_diagnostic" msgid="8076743953908000342">"خواندن/نوشتن منابع متعلق به تشخیص"</string> <string name="permdesc_diagnostic" msgid="6608295692002452283">"به برنامه اجازه میدهد هر منبعی را که متعلق به گروه تشخیص است بخواند و در آن بنویسد؛ بهعنوان مثال، فایلهای /dev. این امر بهصورت بالقوه میتواند بر پایدار بودن و امنیت سیستم تأثیر بگذارد. این تنها باید برای تشخیصهای مختص سختافزار توسط تولیدکننده یا اپراتور استفاده شود."</string> <string name="permlab_changeComponentState" msgid="6335576775711095931">"فعال یا غیر فعال کردن اجزای برنامه"</string> - <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"به برنامه اجازه میدهد تا فعال بودن یا نبودن اجزای برنامهٔ دیگر را تغییر دهد. برنامههای مخرب میتوانند از آن استفاده کنند تا قابلیتهای مهم رایانه لوحی را غیرفعال کنند. باید دقت کرد که با این مجوز ممکن است وضعیت اجزای برنامه ناپایدار، ناهماهنگ یا غیرقابل استفاده شود."</string> + <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"به برنامه اجازه میدهد تا فعال بودن یا نبودن اجزای برنامهٔ دیگر را تغییر دهد. برنامههای مخرب میتوانند از آن استفاده کنند تا قابلیتهای مهم رایانهٔ لوحی را غیرفعال کنند. باید دقت کرد که با این مجوز ممکن است وضعیت اجزای برنامه ناپایدار، ناهماهنگ یا غیرقابل استفاده شود."</string> <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"به برنامه اجازه میدهد تا فعال بودن یا غیرفعال بودن جزئیات برنامهٔ دیگر را تغییر دهد. برنامههای مخرب میتوانند از آن استفاده کنند تا ویژگیهای مهم را غیرفعال کنند. برای این مجوز باید دقت کنید چون ممکن است وضعیت جزئیات برنامه ناپایدار، بیثبات یا غیرقابل استفاده شود."</string> <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"ارائه یا لغو مجوزها"</string> - <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"به یک برنامه کاربردی اجازه میدهد تا مجوزهای خاصی را برای خود یا دیگر برنامهها ارائه کرده یا آنها را لغو کند. برنامههای مضر از این حالت برای دسترسی به ویژگیهایی استفاده میکنند که شما اجازه آن را در اختیارشان قرار ندادهاید."</string> + <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"به یک برنامهٔ کاربردی اجازه میدهد تا مجوزهای خاصی را برای خود یا دیگر برنامهها ارائه کرده یا آنها را لغو کند. برنامههای مضر از این حالت برای دسترسی به ویژگیهایی استفاده میکنند که شما اجازه آن را در اختیارشان قرار ندادهاید."</string> <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"تنظیم برنامههای ترجیحی"</string> - <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه میدهد تا برنامههای ترجیحی شما را تغییر دهد. برنامههای مخرب میتوانند بدون اعلان برنامههایی را که اجرا میشوند، تغییر دهند خود را به جای برنامههای کنونی قلمداد کنند تا دادههای شخصی را از شما جمع آوری کنند."</string> + <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه میدهد تا برنامههای ترجیحی شما را تغییر دهد. برنامههای مخرب میتوانند بدون اعلان برنامههایی را که اجرا میشوند، تغییر دهند خود را به جای برنامههای کنونی قلمداد کنند تا دادههای شخصی را از شما جمعآوری کنند."</string> <string name="permlab_writeSettings" msgid="2226195290955224730">"اصلاح تنظیمات سیستم"</string> <string name="permdesc_writeSettings" msgid="7775723441558907181">"به برنامه اجازه میدهد تا دادههای تنظیم سیستم را تغییر دهد. برنامههای مخرب میتوانند پیکربندی سیستم شما را خراب کنند."</string> <string name="permlab_writeSecureSettings" msgid="204676251876718288">"اصلاح کردن تنظیمات سیستم ایمن"</string> @@ -343,36 +343,36 @@ <string name="permlab_writeGservices" msgid="2149426664226152185">"اصلاح کردن نقشه سرویسهای Google"</string> <string name="permdesc_writeGservices" msgid="1287309437638380229">"به برنامه اجازه میدهد تا نقشه سرویسهای Google را تغییر دهد. برای استفاده برنامههای عادی نیست."</string> <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"اجرا شدن در هنگام راهاندازی"</string> - <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"به برنامه اجازه میدهد تا به محض اتمام راهاندازی سیستم خودبخود شروع به کار کند. این کار ممکن است باعث شود مدت زمان بیشتری صرف شدوع به کار رایانه لوحی شود و به برنامه اجازه میدهد تا با اجرای همیشگی رایانه لوحی را کند کند."</string> + <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"به برنامه اجازه میدهد تا به محض اتمام راهاندازی سیستم خودبخود شروع به کار کند. این کار ممکن است باعث شود مدت زمان بیشتری صرف شدوع به کار رایانهٔ لوحی شود و به برنامه اجازه میدهد تا با اجرای همیشگی رایانهٔ لوحی را کند کند."</string> <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"به برنامه اجازه میدهد تا به محض اینکه سیستم راهاندازی شد خودبخود شروع به کار کند. این کار باعث میشود مدت زمان بیشتری صرف شود تا تلفن شروع به کار کند و به برنامه اجازه میدهد تا کل تلفن کند شود چون همیشه در حال اجرا شدن است."</string> <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ارسال پخش چسبنده"</string> - <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"به برنامه اجازه میدهد تا پخشهای ماندگار را که پس از اتمام پخش باقی میمانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانه لوحی شود."</string> + <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"به برنامه اجازه میدهد تا پخشهای ماندگار را که پس از اتمام پخش باقی میمانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری رایانهٔ لوحی شود."</string> <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"به برنامه اجازه میدهد تا پخشهای ماندگار را که پس از اتمام پخش باقی میمانند ارسال کند. استفاده بیش از حد این ویژگی ممکن است باعث مصرف بیش از حد حافظه و در نتیجه کندی یا ناپایداری تلفن شود."</string> <string name="permlab_readContacts" msgid="8348481131899886131">"خواندن مخاطبین شما"</string> - <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه میدهد دادههای مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را بخواند از جمله، تعداد دفعات تماسهایی که برقرار کردهاید، ایمیلهایی که ارسال کردهاید یا به روشهای دیگری به افراد خاصی ارتباط برقرار کردهاید. این با برنامهها امکان میدهد دادههای مخاطب شما را ذخیره کنند و برنامههای مخرب ممکن است دادههای مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string> + <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"به برنامه اجازه میدهد دادههای مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را بخواند از جمله، تعداد دفعات تماسهایی که برقرار کردهاید، ایمیلهایی که ارسال کردهاید یا به روشهای دیگری به افراد خاصی ارتباط برقرار کردهاید. این با برنامهها امکان میدهد دادههای مخاطب شما را ذخیره کنند و برنامههای مخرب ممکن است دادههای مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string> <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"به برنامه اجازه میدهد دادههای مربوط به مخاطبین ذخیره شده در تلفن شما را بخواند از جمله، تعداد دفعات تماسهایی که برقرار کردهاید، ایمیلهایی که ارسال کردهاید یا به روشهای دیگری با افراد خاصی ارتباط برقرار کردهاید. این به برنامهها امکان میدهد دادههای مخاطب شما را ذخیره کنند و برنامههای مخرب ممکن است دادههای مخاطب را بدون اطلاع شما به اشتراک بگذارند."</string> <string name="permlab_writeContacts" msgid="5107492086416793544">"اصلاح مخاطبین شما"</string> - <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه میدهد دادههای مربوط به مخاطبین ذخیره شده در رایانه لوحی شما را از جمله تعداد تماسهایی که برقرار کردهاید، ایمیلهایی که ارسال کردهاید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه میدهد دادههای مخاطب را حذف نماید."</string> + <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"به برنامه اجازه میدهد دادههای مربوط به مخاطبین ذخیره شده در رایانهٔ لوحی شما را از جمله تعداد تماسهایی که برقرار کردهاید، ایمیلهایی که ارسال کردهاید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه میدهد دادههای مخاطب را حذف نماید."</string> <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"به برنامه اجازه میدهد دادههای مربوط به مخاطبین ذخیره شده در تلفن شما را از جمله تعداد تماسهایی که برقرار کردهاید، ایمیلهایی که ارسال کردهاید یا ارتباطاتی را که به هر شکل با مخاطبین خاصی برقرار کردید تغییر دهد. این مجوز به برنامه اجازه میدهد دادههای مخاطب را حذف نماید."</string> <string name="permlab_readCallLog" msgid="3478133184624102739">"خواندن گزارش تماس"</string> - <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"به برنامه اجازه میدهد گزارش تماس رایانه لوحی شما را بخواند از جمله دادههای مربوط به تماسهای ورودی و خروجی. این مجوز به برنامهها اجازه میدهد دادههای گزارش تماس شما را ذخیره کنند و برنامههای مخرب ممکن است دادههای گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string> + <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"به برنامه اجازه میدهد گزارش تماس رایانهٔ لوحی شما را بخواند از جمله دادههای مربوط به تماسهای ورودی و خروجی. این مجوز به برنامهها اجازه میدهد دادههای گزارش تماس شما را ذخیره کنند و برنامههای مخرب ممکن است دادههای گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string> <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"به برنامه اجازه میدهد گزارش تماس تلفنی شما را بخواند از جمله دادههای مربوط به تماسهای ورودی و خروجی. این مجوز به برنامهها اجازه میدهد دادههای گزارش تماس شما را ذخیره کنند و برنامههای مخرب ممکن است دادههای گزارش تماس شما را بدون اطلاع شما به اشتراک بگذارند."</string> <string name="permlab_writeCallLog" msgid="8552045664743499354">"نوشتن گزارش تماس"</string> - <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه میدهد گزارشات تماس رایانه لوحی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string> + <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه میدهد گزارشات تماس رایانهٔ لوحی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string> <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"به برنامه اجازه میدهد گزارشات تماس تلفنی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string> <string name="permlab_readProfile" msgid="4701889852612716678">"خواندن کارت تماس شما"</string> - <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه میدهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه میتواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را به دیگران ارسال کند."</string> + <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"به برنامه اجازه میدهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه میتواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را به دیگران ارسال کند."</string> <string name="permlab_writeProfile" msgid="907793628777397643">"اصلاح کارت تماس شما"</string> - <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه میدهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه میتواند شما را شناسایی کند و ممکن است اطلاعات نمایه شما را برای دیگران ارسال کند."</string> + <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"به برنامه اجازه میدهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه میتواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را برای دیگران ارسال کند."</string> <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"خواندن جریان اجتماعی شما"</string> <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه میدهد به بهروزرسانیهای اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آنها را همگامسازی کند. دقت کنید که هنگام اشتراکگذاری -- این ویژگی به برنامه اجازه میدهد ارتباطات بین شما و دوستان شما را در شبکههای اجتماعی، صرفنظر از محرمانه بودن آنها بخواند. توجه: این مجوز ممکن است در همه شبکههای اجتماعی اجرا نشود."</string> <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"نوشتن در جریان اجتماعی شما"</string> <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"به برنامه اجازه میدهد بهروزرسانیهای اجتماعی از طرف دوستان شما را نمایش دهد. دقت کنید هنگام اشتراکگذاری اطلاعات -- این ویژگی به برنامه اجازه میدهد پیامهایی را که به نظر میرسد از طرف یکی از دوستان شما باشد ایجاد کند. توجه: این مجوز در همه شبکههای اجتماعی قابل اجرا نیست."</string> <string name="permlab_readCalendar" msgid="5972727560257612398">"خواندن رویدادهای تقویم به همراه اطلاعات محرمانه"</string> - <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان میدهد همه رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد دادههای تقویم شما را صرفنظر از محرمانه یا حساس بودن آنها به اشتراک گذاشته یا ذخیره کند."</string> + <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"به برنامه امکان میدهد همه رویدادهای تقویم ذخیره شده در رایانهٔ لوحی شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد دادههای تقویم شما را صرفنظر از محرمانه یا حساس بودن آنها به اشتراک گذاشته یا ذخیره کند."</string> <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"به برنامه امکان میدهد همه رویدادهای تقویم ذخیره شده در تلفن شما را بخواند، از جمله رویدادهای دوستان یا همکاران. این ممکن است به برنامه امکان دهد دادههای تقویم شما را صرفنظر از محرمانه یا حساس بودن آنها به اشتراک گذاشته یا ذخیره کند."</string> <string name="permlab_writeCalendar" msgid="8438874755193825647">"افزودن یا تغییر رویدادهای تقویم و ارسال ایمیل به مهمانان بدون دخالت مالک"</string> - <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه میدهد رویدادهایی را که میتوانید در رایانه لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیامهایی را که به نظر میرسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string> + <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"به برنامه اجازه میدهد رویدادهایی را که میتوانید در رایانهٔ لوحی خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیامهایی را که به نظر میرسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string> <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"به برنامه اجازه میدهد رویدادهایی را که میتوانید در تلفن خود اصلاح نمایید، از جمله رویدادهای دوستان یا همکاران خود را، اضافه یا حذف کرده یا تغییر دهد. این ویژگی ممکن است به برنامه اجازه دهد پیامهایی را که به نظر میرسد از مالکین تقویم رسیده است ارسال نموده یا رویدادها را بدون اطلاع مالک اصلاح کنند."</string> <string name="permlab_accessMockLocation" msgid="8688334974036823330">"منابع مکان کاذب برای تست"</string> <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائهدهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان میدهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائهدهندگان موقعیت مکانی را نادیده بگیرد."</string> @@ -381,7 +381,7 @@ <string name="permlab_installLocationProvider" msgid="6578101199825193873">"مجوز برای نصب یک ارائه دهنده مکان"</string> <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائهدهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان میدهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائهدهندگان موقعیت مکانی را نادیده بگیرد."</string> <string name="permlab_accessFineLocation" msgid="5885550969882561436">"موقعیت مکانی دقیق (GPS)"</string> - <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیتیابی جهانی در رایانه لوحی خود دسترسی پیدا کنید. وقتی سرویسهای موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه میدهد موقعیت مکانی دقیق شما را تعیین کند."</string> + <string name="permdesc_accessFineLocation" product="tablet" msgid="8960597421469894181">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیتیابی جهانی در رایانهٔ لوحی خود دسترسی پیدا کنید. وقتی سرویسهای موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه میدهد موقعیت مکانی دقیق شما را تعیین کند."</string> <string name="permdesc_accessFineLocation" product="default" msgid="239268765496141815">"به منابع موقعیت مکانی دقیق مانند سیستم موقعیتیابی جهانی در تلفن خود دسترسی پیدا کنید. وقتی سرویسهای موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه اجازه میدهد موقعیت مکانی دقیق شما را تعیین کند."</string> <string name="permlab_accessCoarseLocation" msgid="7422827215441638984">"موقعیت مکانی تقریبی (مبتنی بر شبکه)"</string> <string name="permdesc_accessCoarseLocation" msgid="5383798877137640762">"به موقعیت مکانی تقریبی ارائهدهندگان موقعیت مکانی با استفاده از منابع شبکه مانند برج مخابراتی و Wi-Fi دسترسی پیدا کنید. وقتی این سرویسهای موقعیت مکانی موجود و فعال باشند، این مجوز به برنامه امکان میدهد موقعیت مکانی تقریبی شما را تعیین کند."</string> @@ -395,14 +395,14 @@ <string name="permdesc_recordAudio" msgid="4906839301087980680">"به برنامه اجازه میدهد صدا را با میکروفن ضبط کند. این مجوز به برنامه اجازه میدهد صدا را در هر زمان که بخواهید بدون تأیید شما ضبط کند."</string> <string name="permlab_camera" msgid="3616391919559751192">"عکسبرداری و فیلمبرداری"</string> <string name="permdesc_camera" msgid="8497216524735535009">"به برنامه اجازه میدهد با دوربین به عکسبرداری و فیلمبرداری بپردازد. این مجوز به برنامه اجازه میدهد از دوربین در هر زمانی بدون تأیید شما استفاده کند."</string> - <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانه لوحی"</string> + <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانهٔ لوحی"</string> <string name="permlab_brick" product="default" msgid="8337817093326370537">"تلفن بطور دائمی غیرفعال شود"</string> - <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"به برنامه اجازه میدهد تا رایانه لوحی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string> + <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"به برنامه اجازه میدهد تا رایانهٔ لوحی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string> <string name="permdesc_brick" product="default" msgid="5788903297627283099">"به برنامه اجازه میدهد تا گوشی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string> - <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"راه اندازی مجدد اجباری رایانه لوحی"</string> - <string name="permlab_reboot" product="default" msgid="2898560872462638242">"اجبار برنامه برای راه اندازی مجدد"</string> - <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"به برنامه اجازه میدهد تا سبب راه اندازی مجدد رایانه لوحی شود."</string> - <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"به برنامه اجازه میدهد تا سبب راه اندازی مجدد گوشی شود."</string> + <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"راهاندازی مجدد اجباری رایانهٔ لوحی"</string> + <string name="permlab_reboot" product="default" msgid="2898560872462638242">"اجبار برنامه برای راهاندازی مجدد"</string> + <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"به برنامه اجازه میدهد تا سبب راهاندازی مجدد رایانهٔ لوحی شود."</string> + <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"به برنامه اجازه میدهد تا سبب راهاندازی مجدد گوشی شود."</string> <string name="permlab_mount_unmount_filesystems" product="nosdcard" msgid="2927361537942591841">"دسترسی به سیستم فایل حافظهٔ USB"</string> <string name="permlab_mount_unmount_filesystems" product="default" msgid="4402305049890953810">"دسترسی به سیستم فایل کارت SD"</string> <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"به برنامه اجازه میدهد تا فایلهای سیستمی در حافظه جداشدنی نصب شود یا نصب آن لغو شود."</string> @@ -427,14 +427,14 @@ <string name="permdesc_manageUsb" msgid="7776155430218239833">"به برنامه اجازه میدهد تا تنظیمات برگزیده و مجوزهای دستگاههای USB را مدیریت کند."</string> <string name="permlab_accessMtp" msgid="4953468676795917042">"اعمال پروتکل MTP"</string> <string name="permdesc_accessMtp" msgid="6532961200486791570">"دسترسی به درایور کرنل MTP جهت اعمال پروتکل MTP USB را اجازه میدهد."</string> - <string name="permlab_hardware_test" msgid="4148290860400659146">"تست سخت افزار"</string> + <string name="permlab_hardware_test" msgid="4148290860400659146">"تست سختافزار"</string> <string name="permdesc_hardware_test" msgid="6597964191208016605">"به برنامه اجازه میدهد به منظور تست سختافزار، قسمتهای جانبی مختلف را کنترل کنند."</string> <string name="permlab_callPhone" msgid="3925836347681847954">"تماس مستقیم با شماره تلفنها"</string> <string name="permdesc_callPhone" msgid="3740797576113760827">"به برنامه اجازه میدهد بدون دخالت شما با شمارههای تلفن تماس بگیرد. این ممکن است باعث ایجاد هزینه یا تماسهای پیشبینی نشده شود. توجه داشته باشید که این به برنامه اجازه نمیدهد به برقراری تماسهای اضطراری بپردازد. برنامههای مخرب ممکن است با برقراری تماس بدون تأیید شما هزینههایی را برای شما ایجاد کنند."</string> <string name="permlab_callPrivileged" msgid="4198349211108497879">"تماس مستقیم با هر شماره تلفنی"</string> <string name="permdesc_callPrivileged" msgid="1689024901509996810">"به برنامه اجازه میدهد تا بدون دخالت با هر شماره تلفنی تماس بگیرد، از جمله شمارههای اضطراری. برنامههای مخرب میتوانند تماسهای غیرضروری و غیر قانونی با خدمات اضطراری بگیرند."</string> - <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"راه اندازی مستقیم تنظیم رایانه لوحی CDMA"</string> - <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"شروع مستقیم راه اندازی تلفن CDMA"</string> + <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"راهاندازی مستقیم تنظیم رایانهٔ لوحی CDMA"</string> + <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"شروع مستقیم راهاندازی تلفن CDMA"</string> <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"به برنامه اجازه میدهد تا شرایط مقررات CDMA را شروع کند. برنامههای مخرب میتوانند شرایط مقررات CDMA را در مواقع غیرضروری شروع کند."</string> <string name="permlab_locationUpdates" msgid="7785408253364335740">"کنترل اعلانهای بهروزرسانی مکان"</string> <string name="permdesc_locationUpdates" msgid="1120741557891438876">"به برنامه اجازه میدهد اعلانهای بهروزرسانی موقعیت مکانی را از رادیو فعال/غیرفعال کند. برای استفاده برنامههای عادی نیست."</string> @@ -446,17 +446,17 @@ <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"به برنامه اجازه میدهد ویژگیهای دستگاه را کنترل کند. برنامهای که این مجوز را دارد میتواند بدون اطلاع شما تعویض شبکه داشته باشد، رادیوی تلفن را روشن یا خاموش کند و کارهایی از این قبیل را انجام دهد."</string> <string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string> <string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه میدهد به ویژگیهای تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه میدهد شماره تلفن و شناسههای دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string> - <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانه لوحی"</string> + <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانهٔ لوحی"</string> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ممانعت از به خواب رفتن تلفن"</string> - <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"به برنامه اجازه میدهد تا از غیرفعال شدن رایانه لوحی جلوگیری کند."</string> + <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"به برنامه اجازه میدهد تا از غیرفعال شدن رایانهٔ لوحی جلوگیری کند."</string> <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"به برنامه اجازه میدهد تا از غیرفعال شدن تلفن جلوگیری کند."</string> - <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"روشن/خاموش کردن رایانه لوحی"</string> + <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"روشن/خاموش کردن رایانهٔ لوحی"</string> <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"روشن/خاموش کردن تلفن"</string> - <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"به برنامه اجازه میدهد رایانه لوحی را روشن یا خاموش کند."</string> + <string name="permdesc_devicePower" product="tablet" msgid="6689862878984631831">"به برنامه اجازه میدهد رایانهٔ لوحی را روشن یا خاموش کند."</string> <string name="permdesc_devicePower" product="default" msgid="6037057348463131032">"به برنامه اجازه میدهد گوشی را روشن یا خاموش کند."</string> <string name="permlab_factoryTest" msgid="3715225492696416187">"اجرا در حالت تست کارخانه"</string> - <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سخت افزار رایانه لوحی شما را فراهم میآورد. فقط زمانی که رایانه لوحی در حالت تست سازنده در حال اجراست قابل دسترسی است."</string> - <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سخت افزار تلفن شما را فراهم میآورد. فقط زمانی که تلفن در حالت تست سازنده در حال اجراست قابل دسترسی است."</string> + <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سختافزار رایانهٔ لوحی شما را فراهم میآورد. فقط زمانی که رایانهٔ لوحی در حالت تست سازنده در حال اجراست قابل دسترسی است."</string> + <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"اجرا به عنوان تست سازنده سطح پایین، امکان دسترسی کامل به سختافزار تلفن شما را فراهم میآورد. فقط زمانی که تلفن در حالت تست سازنده در حال اجراست قابل دسترسی است."</string> <string name="permlab_setWallpaper" msgid="6627192333373465143">"تنظیم تصویر زمینه"</string> <string name="permdesc_setWallpaper" msgid="7373447920977624745">"به برنامه اجازه میدهد تا تصویر زمینه سیستم را تنظیم کند."</string> <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"تنظیم اندازه تصویر زمینه"</string> @@ -464,15 +464,15 @@ <string name="permlab_masterClear" msgid="2315750423139697397">"بازنشانی سیستم به موارد پیشفرض کارخانه"</string> <string name="permdesc_masterClear" msgid="3665380492633910226">"به برنامه اجازه میدهد تا بطور کامل سیستم را روی تنظیمات کارخانه بازنشانی کند، همه دادهها، پیکربندی و برنامههای نصب شده را پاک کند."</string> <string name="permlab_setTime" msgid="2021614829591775646">"تنظیم ساعت"</string> - <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"به برنامه اجازه میدهد تا زمان ساعت رایانه لوحی را تغییر دهد."</string> + <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"به برنامه اجازه میدهد تا زمان ساعت رایانهٔ لوحی را تغییر دهد."</string> <string name="permdesc_setTime" product="default" msgid="1855702730738020">"به برنامه اجازه میدهد تا زمان ساعت تلفن را تغییر دهد."</string> <string name="permlab_setTimeZone" msgid="2945079801013077340">"تنظیم منطقهٔ زمانی"</string> - <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"به برنامه اجازه میدهد تا منطقهٔ زمانی رایانه لوحی را تغییر دهد."</string> + <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"به برنامه اجازه میدهد تا منطقهٔ زمانی رایانهٔ لوحی را تغییر دهد."</string> <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"به برنامه اجازه میدهد تا منطقهٔ زمانی تلفن را تغییر دهد."</string> <string name="permlab_accountManagerService" msgid="4829262349691386986">"عملکرد به عنوان AccountManagerService"</string> <string name="permdesc_accountManagerService" msgid="1948455552333615954">"به برنامه اجازه میدهد با AccountAuthenticators تماس برقرار کند."</string> <string name="permlab_getAccounts" msgid="1086795467760122114">"یافتن حسابها در دستگاه"</string> - <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"به برنامه اجازه میدهد به لیست حسابهای شناخته شده توسط رایانه لوحی دسترسی پیدا کند. این ممکن است حسابهای ایجاد شده توسط برنامههایی را که نصب کردهاید، شامل شود."</string> + <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"به برنامه اجازه میدهد به لیست حسابهای شناخته شده توسط رایانهٔ لوحی دسترسی پیدا کند. این ممکن است حسابهای ایجاد شده توسط برنامههایی را که نصب کردهاید، شامل شود."</string> <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"به برنامه اجازه میدهد به لیست حسابهای شناخته شده توسط تلفن دسترسی پیدا کند. این ممکن است حسابهای ایجاد شده توسط برنامههایی را که نصب کردهاید، شامل شود."</string> <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"ایجاد حسابها و تنظیم گذرواژهها"</string> <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"به برنامه اجازه میدهد از امکانات تأیید کننده اعتبار حساب AccountManager از جمله ایجاد حساب و دریافت و تنظیم گذرواژهها استفاده کند."</string> @@ -497,18 +497,18 @@ <string name="permlab_changeWifiState" msgid="6550641188749128035">"اتصال به Wi-Fi و قطع اتصال از آن"</string> <string name="permdesc_changeWifiState" msgid="7137950297386127533">"به برنامه اجازه میدهد تا به نقاط دسترسی Wi-Fi وصل شود و ارتباط خود را با آنها قطع کند و تغییراتی را در پیکربندی دستگاه برای شبکههای Wi-Fi ایجاد کند."</string> <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"دریافت چندگانه Wi-Fi را مجاز میکند"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه میدهد به دریافت بستههای ارسالی به همه دستگاههای موجود در شبکه Wi-Fi با استفاده از آدرسهای پخش چندگانه و نه فقط به رایانه لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده میکند."</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"به برنامه اجازه میدهد به دریافت بستههای ارسالی به همه دستگاههای موجود در شبکه Wi-Fi با استفاده از آدرسهای پخش چندگانه و نه فقط به رایانهٔ لوحی شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده میکند."</string> <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه میدهد به دریافت بستههای ارسالی به همه دستگاههای موجود در شبکه Wi-Fi با استفاده از آدرسهای پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده میکند."</string> <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه میدهد تا رایانه لوحی بلوتوث محلی را پیکربندی کرده، دستگاههای راه دور را شناسایی کرده و با آنها جفت شود."</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه میدهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاههای راه دور را شناسایی کرده و با آنها جفت شود."</string> <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه میدهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاههای راه دور را پیدا کند و با آنها جفت شود."</string> <string name="permlab_accessWimaxState" msgid="7436749103151096452">"مشاهدهٔ اتصالات وایمکس"</string> <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"به برنامه امکان میدهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکههای وایمکس متصل را مشخص کند."</string> <string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغییر وضعیت WiMAX"</string> - <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان میدهد رایانه لوحی را به شبکههای وایمکس متصل کرده یا اتصال آن را از این شبکهها قطع کند."</string> + <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان میدهد رایانهٔ لوحی را به شبکههای وایمکس متصل کرده یا اتصال آن را از این شبکهها قطع کند."</string> <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"به برنامه امکان میدهد تا تلفن را به شبکههای وایمکس متصل کرده یا اتصال آنرا از این شبکهها قطع کند."</string> <string name="permlab_bluetooth" msgid="6127769336339276828">"مرتبط سازی با دستگاههای بلوتوث"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در رایانه لوحی را مشاهده کند و اتصال با دستگاههای مرتبط را برقرار کرده و بپذیرد."</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاههای مرتبط را برقرار کرده و بپذیرد."</string> <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاههای مرتبط را برقرار کرده و بپذیرد."</string> <string name="permlab_nfc" msgid="4423351274757876953">"کنترل ارتباط راه نزدیک"</string> <string name="permdesc_nfc" msgid="7120611819401789907">"به برنامه اجازه میدهد تا با تگهای ارتباط میدان نزدیک (NFC)، کارتها و فایل خوان ارتباط برقرار کند."</string> @@ -538,8 +538,8 @@ <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"به برنامه اجازه میدهد تا در کارت SD بنویسد."</string> <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"تغییر/حذف محتواهای حافظه رسانه داخلی"</string> <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"به برنامه اجازه میدهد تا محتویات حافظه رسانه داخلی را تغییر دهد."</string> - <string name="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظه پنهان"</string> - <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه میدهد تا سیستم فایل حافظه پنهان را بخواند و بنویسد."</string> + <string name="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظهٔ پنهان"</string> + <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"به برنامه اجازه میدهد تا سیستم فایل حافظهٔ پنهان را بخواند و بنویسد."</string> <string name="permlab_use_sip" msgid="5986952362795870502">"علامتگذاری/دریافت تماسهای اینترنتی"</string> <string name="permdesc_use_sip" msgid="4717632000062674294">"به برنامه اجازه میدهد تا از خدمات SIP استفاده کند و تماسهای اینترنتی بگیرد/دریافت کند."</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"خواندن سابقه استفاده از شبکه"</string> @@ -551,19 +551,19 @@ <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string> <string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسههای مجاز در گذرواژههای بازکردن قفل صفحه را کنترل کنید."</string> <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاشهای قفل گشایی صفحه"</string> - <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژههای اشتباه تایپ شده را هنگام بازکردن قفل صفحه کنترل میکند، و یا اگر دفعات زیادی گذرواژه اشتباه تایپ شود رایانه لوحی را قفل میکند و همه دادههای رایانه لوحی را پاک میکند."</string> + <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژههای اشتباه تایپ شده را هنگام بازکردن قفل صفحه کنترل میکند، و یا اگر دفعات زیادی گذرواژه اشتباه تایپ شود رایانهٔ لوحی را قفل میکند و همه دادههای رایانهٔ لوحی را پاک میکند."</string> <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"تعداد گذرواژههای نادرست تایپ شده را کنترل میکند. هنگام بازکردن قفل صفحه اگر دفعات زیادی گذرواژه نادرست تایپ کردهاید، تلفن را قفل کنید یا همه دادههای تلفن را پاک کنید."</string> <string name="policylab_resetPassword" msgid="2620077191242688955">"تغییر رمز ورود قفل گشایی صفحه"</string> <string name="policydesc_resetPassword" msgid="605963962301904458">"گذرواژه بازگشایی قفل صفحه را تغییر دهید."</string> <string name="policylab_forceLock" msgid="2274085384704248431">"قفل کردن صفحه"</string> <string name="policydesc_forceLock" msgid="1141797588403827138">"نحوه و زمان قفل شدن صفحه را کنترل کنید."</string> <string name="policylab_wipeData" msgid="3910545446758639713">"پاک کردن تمام دادهها"</string> - <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به دادههای کارخانه، دادههای رایانه لوحی بدون هشدار پاک میشود."</string> + <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"با انجام بازنشانی به دادههای کارخانه، دادههای رایانهٔ لوحی بدون هشدار پاک میشود."</string> <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"با انجام بازنشانی به دادههای کارخانه، دادههای تلفن بدون هشدار پاک میشود."</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تنظیم پروکسی جهانی دستگاه"</string> <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"پروکسی جهانی دستگاه مورد نظر را جهت استفاده هنگام فعال بودن خط مشی تنظیم کنید. فقط اولین سرپرست دستگاه پروکسی جهانی مفید را تنظیم میکند."</string> <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود قفل صفحه"</string> - <string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یکبار باید گذرواژه صفحه قفل عوض شود."</string> + <string name="policydesc_expirePassword" msgid="1729725226314691591">"کنترل کنید چند وقت یک بار باید گذرواژه صفحه قفل عوض شود."</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string> <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"باید اطلاعات ذخیره شده برنامه رمزگذاری شود."</string> <string name="policylab_disableCamera" msgid="6395301023152297826">"غیر فعال کردن دوربین ها"</string> @@ -707,7 +707,7 @@ <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> <string name="lockscreen_low_battery" msgid="1482873981919249740">"شارژر خود را متصل کنید."</string> <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"سیم کارت موجود نیست."</string> - <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانه لوحی نیست."</string> + <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانهٔ لوحی نیست."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"سیم کارت درون تلفن نیست."</string> <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"سیم کارت را وارد کنید."</string> <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"سیم کارت موجود نیست یا قابل خواندن نیست. یک سیم کارت وارد کنید."</string> @@ -725,13 +725,13 @@ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"سیم کارت قفل شد."</string> <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"بازگشایی قفل سیم کارت..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> - <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژه خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کردهاید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> + <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژهٔ خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کردهاید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"پین را<xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه تایپ کردهاید. "\n\n"پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> - <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته میشود که برای بازگشایی قفل رایانه لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> - <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر از شما خواسته میشود که برای بازگشایی قفل گوشی خود به برنامه Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانه لوحی کردهاید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانه لوحی به پیشفرض کارخانه بازنشانی میشود و تمام دادههای کاربر از دست خواهد رفت."</string> + <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته میشود که برای بازگشایی قفل رایانهٔ لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> + <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر از شما خواسته میشود که برای بازگشایی قفل گوشی خود به برنامهٔ Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل رایانهٔ لوحی کردهاید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، رایانهٔ لوحی به پیشفرض کارخانه بازنشانی میشود و تمام دادههای کاربر از دست خواهد رفت."</string> <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"شما به اشتباه <xliff:g id="NUMBER_0">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کردهاید. پس از<xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر، تلفن به پیشفرض کارخانه بازنشانی میشود و تمام دادههای کاربر از دست خواهد رفت."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانه لوحی کردهاید. رایانه لوحی در حال حاضر به پیشفرض کارخانه بازنشانی میشود."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانهٔ لوحی کردهاید. رایانهٔ لوحی در حال حاضر به پیشفرض کارخانه بازنشانی میشود."</string> <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کردهاید. این تلفن در حال حاضر به پیشفرض کارخانه بازنشانی میشود."</string> <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"در <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string> <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"الگو را فراموش کردهاید؟"</string> @@ -742,7 +742,7 @@ <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"رمز ورود"</string> <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ورود به سیستم"</string> <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"نام کاربر یا رمز ورود نامعتبر است."</string> - <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژه خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string> + <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژهٔ خود را فراموش کردید؟"\n"از "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"در حال بررسی..."</string> <string name="lockscreen_unlock_label" msgid="737440483220667054">"بازگشایی قفل"</string> <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"صدا روشن"</string> @@ -762,8 +762,8 @@ <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string> <string name="factorytest_failed" msgid="5410270329114212041">"تست کارخانه انجام نشد"</string> <string name="factorytest_not_system" msgid="4435201656767276723">"عملکرد FACTORY_TEST تنها برای بستههای نصب شده در /system/app پشتیبانی میشود."</string> - <string name="factorytest_no_action" msgid="872991874799998561">"بسته ای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string> - <string name="factorytest_reboot" msgid="6320168203050791643">"راه اندازی مجدد"</string> + <string name="factorytest_no_action" msgid="872991874799998561">"بستهای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string> + <string name="factorytest_reboot" msgid="6320168203050791643">"راهاندازی مجدد"</string> <string name="js_dialog_title" msgid="1987483977834603872">"صفحه در \"<xliff:g id="TITLE">%s</xliff:g>\" میگوید:"</string> <string name="js_dialog_title_default" msgid="6961903213729667573">"جاوا اسکریپت"</string> <string name="js_dialog_before_unload" msgid="730366588032430474">"از این صفحه خارج میشوید؟"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"برای ادامه روی تأیید و برای ماندن در همین صفحه روی لغو کلیک کنید."</string> @@ -790,7 +790,7 @@ <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"خواندن سابقه و نشانکهای وب شما"</string> <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"به برنامه اجازه میدهد سابقه نشانیهای اینترنتی را که مرورگر بازدید کرده است و همه نشانکهای مرورگر را بخواند. توجه: این مجوز توسط مرورگرهای شخص ثالث یا سایر برنامههای دارای قابلیت مرور وب قابل اجرا نیست."</string> <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"نوشتن نشانکهای وب و سابقه"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"به برنامه اجازه میدهد سابقه مرورگر یا نشانکهای ذخیره شده در رایانه لوحی شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد دادههای مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامههای دارای قابلیت مرور وب قابل اجرا نباشد."</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"به برنامه اجازه میدهد سابقه مرورگر یا نشانکهای ذخیره شده در رایانهٔ لوحی شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد دادههای مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامههای دارای قابلیت مرور وب قابل اجرا نباشد."</string> <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"به برنامه اجازه میدهد سابقه مرورگر یا نشانکهای ذخیره شده در تلفن شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد دادههای مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامههای دارای قابلیت مرور وب قابل اجرا نباشد."</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"تنظیم یک هشدار"</string> <string name="permdesc_setAlarm" msgid="316392039157473848">"به برنامه اجازه میدهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامههای ساعت زنگدار نمیتوانند این ویژگی را اعمال کنند."</string> @@ -826,7 +826,7 @@ <string name="searchview_description_submit" msgid="2688450133297983542">"ارسال عبارت جستجو"</string> <string name="searchview_description_voice" msgid="2453203695674994440">"جستجوی صوتی"</string> <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"فعال کردن «کاوش با لمس»؟"</string> - <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانه لوحی از حرکات اشاره استفاده کنید."</string> + <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانهٔ لوحی از حرکات اشاره استفاده کنید."</string> <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از تلفن خود از حرکات اشاره استفاده کنید."</string> <string name="oneMonthDurationPast" msgid="7396384508953779925">"۱ ماه قبل"</string> <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"قبل از ۱ ماه گذشته"</string> @@ -968,7 +968,7 @@ <string name="webpage_unresponsive" msgid="3272758351138122503">"این صفحه پاسخ نمیدهد."\n\n"آیا میخواهید آن را ببندید؟"</string> <string name="launch_warning_title" msgid="1547997780506713581">"برنامه مجدداً هدایت شد"</string> <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> اکنون در حال اجرا است."</string> - <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ابتدا راه اندازی شد."</string> + <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ابتدا راهاندازی شد."</string> <string name="screen_compat_mode_scale" msgid="3202955667675944499">"مقیاس"</string> <string name="screen_compat_mode_show" msgid="4013878876486655892">"همیشه نشان داده شود"</string> <string name="screen_compat_mode_hint" msgid="1064524084543304459">"در تنظیمات سیستم >برنامهها > مورد دانلود شده آن را دوباره فعال کنید."</string> @@ -1062,17 +1062,17 @@ <string name="perms_description_app" msgid="5139836143293299417">"ارائه شده توسط <xliff:g id="APP_NAME">%1$s</xliff:g> ."</string> <string name="usb_storage_activity_title" msgid="4465055157209648641">"حافظه انبوه USB"</string> <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل شد"</string> - <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"شما از طریق USB به رایانه خود متصل شدهاید. اگر میخواهید فایلها را بین رایانه خود و حافظهٔ USB در Android کپی کنید، دکمه زیر را لمس کنید."</string> - <string name="usb_storage_message" product="default" msgid="805351000446037811">"شما از طریق USB به رایانه خود متصل شدهاید. اگر میخواهید فایلها را بین رایانه خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string> + <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"شما از طریق USB به رایانهٔ خود متصل شدهاید. اگر میخواهید فایلها را بین رایانهٔ خود و حافظهٔ USB در Android کپی کنید، دکمه زیر را لمس کنید."</string> + <string name="usb_storage_message" product="default" msgid="805351000446037811">"شما از طریق USB به رایانهٔ خود متصل شدهاید. اگر میخواهید فایلها را بین رایانهٔ خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string> <string name="usb_storage_button_mount" msgid="1052259930369508235">"روشن کردن دستگاه ذخیرهسازی USB"</string> <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"هنگام استفاده از حافظهٔ USB برای حافظه انبوه USB مشکلی بوجود آمد."</string> <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"هنگام استفاده از کارت SD برای حافظه ذخیره انبوه USB مشکلی بوجود آمد."</string> <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB متصل شد"</string> - <string name="usb_storage_notification_message" msgid="939822783828183763">"برای کپی کردن فایلها از/به رایانه خود لمس کنید."</string> + <string name="usb_storage_notification_message" msgid="939822783828183763">"برای کپی کردن فایلها از/به رایانهٔ خود لمس کنید."</string> <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"خاموش کردن دستگاه ذخیرهسازی USB"</string> <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"برای غیرفعال کردن حافظهٔ USB، لمس کنید."</string> <string name="usb_storage_stop_title" msgid="660129851708775853">"دستگاه ذخیرهسازی USB در حال استفاده است"</string> - <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"قبل از غیرفعال کردن حافظهٔ USB، حافظهٔ USB مربوط به Android را در رایانه خود لغو نصب کنید (\"خارج کنید\")."</string> + <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"قبل از غیرفعال کردن حافظهٔ USB، حافظهٔ USB مربوط به Android را در رایانهٔ خود لغو نصب کنید (\"خارج کنید\")."</string> <string name="usb_storage_stop_message" product="default" msgid="8043969782460613114">"قبل از غیرفعال کردن حافظهٔ USB، کارت SD مربوط به Android را در رایانه لغو نصب کنید (\"خارج کنید\")."</string> <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"خاموش کردن دستگاه ذخیرهسازی USB"</string> <string name="usb_storage_stop_error_message" msgid="1970374898263063836">"هنگام غیرفعال کردن حافظهٔ USB مشکلی بوجود آمد. بررسی کنید میزبان USB را لغو نصب کرده باشید، سپس دوباره امتحان کنید."</string> @@ -1080,7 +1080,7 @@ <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"در صورت فعال کردن حافظهٔ USB، برخی از برنامههایی که از آنها استفاده میکنید متوقف میشوند و تا زمانی که حافظهٔ USB را غیرفعال نکنید امکان استفاده از آنها وجود نخواهد داشت."</string> <string name="dlg_error_title" msgid="7323658469626514207">"راهاندازی USB ناموفق بود."</string> <string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string> - <string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به عنوان دستگاه رسانه ای"</string> + <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_accessory_notification_title" msgid="7848236974087653666">"به یک وسیله جانبی USB وصل شده است"</string> @@ -1094,10 +1094,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"برای غیرفعال کردن اشکال زدایی USB لمس کنید."</string> <string name="select_input_method" msgid="4653387336791222978">"انتخاب روش ورودی"</string> <string name="configure_input_methods" msgid="9091652157722495116">"تنظیم روشهای ورودی"</string> - <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحه کلید فیزیکی"</string> + <string name="use_physical_keyboard" msgid="6203112478095117625">"صفحهکلید فیزیکی"</string> <string name="hardware" msgid="7517821086888990278">"سختافزار"</string> - <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرحبندی صفحه کلید"</string> - <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرحبندی صفحه کلید لمس کنید…"</string> + <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرحبندی صفحهکلید"</string> + <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"برای انتخاب یک طرحبندی صفحهکلید لمس کنید…"</string> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string> @@ -1112,8 +1112,8 @@ <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"کارت SD آسیب دیده"</string> <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="1795917578395333280">"حافظهٔ USB خراب است. سعی کنید آنرا دوباره فرمت کنید."</string> <string name="ext_media_unmountable_notification_message" product="default" msgid="1753898567525568253">"کارت SD خراب است. سعی کنید آنرا دوباره فرمت کنید."</string> - <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظهٔ USB به صورت غیر منتظره جدا شد"</string> - <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیر منتظره ای جدا شد"</string> + <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظهٔ USB به صورت غیرمنتظره جدا شد"</string> + <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیرمنتظرهای جدا شد"</string> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"اتصال حافظهٔ USB را قبل از بیرون آوردن قطع کنید تا سبب از بین رفتن دادهها نشود."</string> <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"کارت SD را قبل از بیرون آوردن جدا کنید تا سبب از بین رفتن دادهها نشود."</string> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"حافظهٔ USB را میتوانید با ایمنی جدا کنید"</string> @@ -1283,7 +1283,7 @@ <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="4292569383976636200">"مشاهده همه"</string> + <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"مشاهدهٔ همه"</string> <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"انتخاب فعالیت"</string> <string name="share_action_provider_share_with" msgid="5247684435979149216">"اشتراکگذاری با"</string> <string name="status_bar_device_locked" msgid="3092703448690669768">"دستگاه قفل است."</string> @@ -1293,7 +1293,7 @@ <string name="SetupCallDefault" msgid="5834948469253758575">"تماس را میپذیرید؟"</string> <string name="activity_resolver_use_always" msgid="8017770747801494933">"همیشه"</string> <string name="activity_resolver_use_once" msgid="2404644797149173758">"فقط این بار"</string> - <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانه لوحی"</string> + <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانهٔ لوحی"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"تلفن"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"هدفونها"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"بلندگوهای جایگاه اتصال"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 84d83ccec987..3488b618427d 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -245,7 +245,7 @@ <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikácii načítať obsah aktívneho okna. Škodlivé aplikácie môžu získať celý obsah okna a preskúmať celý jeho text okrem hesiel."</string> <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítanie informácií o oknách"</string> <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikácii načítať informácie o oknách zo správcu okien. Škodlivé aplikácie môžu načítať informácie, ktoré sú určené pre interné využitie systému."</string> - <string name="permlab_filter_events" msgid="8675535648807427389">"filtrovanie prenosov"</string> + <string name="permlab_filter_events" msgid="8675535648807427389">"filtrovanie udalostí"</string> <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožňuje aplikácii zaregistrovať vstupný filter, ktorý filtruje stream všetkých prenosov používateľa pred ich odvysielaním. Škodlivá aplikácia môže bez zásahu používateľa ovládať používateľské rozhranie systému."</string> <string name="permlab_shutdown" msgid="7185747824038909016">"Čiastočné vypnutie"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvedie správcu činností do vypnutého stavu. Úplné vypnutie však nenastane."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 43e22da36745..6fb20ddac27b 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -244,9 +244,9 @@ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"epua maudhui ya skrini"</string> <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Inaruhusu programu kutoa maudhui ya dirisha amilifu. Programu hasidi zinaweza kutoa maudhui yote ya dirisha na kuchunguza maandishi yake yote isipokuwa nenosiri."</string> <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"okoa maelezo ya dirisha"</string> - <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Huruhusu programu kuokoa maelezo kuhusu madirisha kutoka kwenye kidhibiti dirisha. Huenda programu hasidi ikaokoa maelezo ambayo yamekusudiwa kwa matumizi ya mfumo wa ndani."</string> + <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Huruhusu programu kuokoa maelezo kuhusu madirisha kutoka kwenye kidhibiti dirisha. Huenda programu hasidi ikakusanya maelezo ambayo yamekusudiwa kwa matumizi ya mfumo wa ndani."</string> <string name="permlab_filter_events" msgid="8675535648807427389">"chuja matukio"</string> - <string name="permdesc_filter_events" msgid="8006236315888347680">"Huruhusu programu kusajili kichujio ingizo kinachochuja mkondo wa matukio ya mtumiaji kabla ya kutumwa. Huenda programu hasidi zikadhibiti mfumo wa UI bila mtumiaji kuingilia kati."</string> + <string name="permdesc_filter_events" msgid="8006236315888347680">"Huruhusu programu kusajili kichujio ingizo kinachochuja mkondo wa matukio ya mtumiaji kabla ya kutumwa. Huenda programu hasidi ikadhibiti mfumo wa UI bila mtumiaji kuingilia kati."</string> <string name="permlab_shutdown" msgid="7185747824038909016">"Zima nusu"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"Huweka kisimamia shughuli katika hali ya kuzima. Haiadhiri uzimaji kamili"</string> <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string> @@ -474,8 +474,8 @@ <string name="permlab_getAccounts" msgid="1086795467760122114">"pata akaunti kwenye kifaa"</string> <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa kompyuta kibao. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string> <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa simu. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string> - <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"unda akaunti na weka manenosiri"</string> - <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Inaruhusu programu kutumia uwezo wa uthibitishaji akaunti wa KidhibitiAkaunti, pamoja na kuunda akaunti na kupata na kuweka nywila zao."</string> + <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"fungua akaunti na weka manenosiri"</string> + <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Inaruhusu programu kutumia uwezo wa uthibitishaji akaunti wa KidhibitiAkaunti, ikiwa ni pamoja na kufungua akaunti na kupata na kuweka manenosiri ya akaunti hizo."</string> <string name="permlab_manageAccounts" msgid="4983126304757177305">"ongeza au uondoe akaunti"</string> <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Inaruhusu programu kutekeleza shughuli kama vile kuongeza na kutoa akaunti, na kufuta manenosiri yazo."</string> <string name="permlab_useCredentials" msgid="235481396163877642">"tumia akaunti kwenye kifaa"</string> @@ -741,7 +741,7 @@ <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Jina la mtumiaji (barua pepe)"</string> <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Nenosiri"</string> <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Ingia"</string> - <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Jina batili la mtumiaji au nywila"</string> + <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Jina la mtumiaji au nenosiri batili."</string> <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Umesahau jina lako la mtumiaji au nenosiri?"\n"Tembela "<b>"google.com/accounts/recovery"</b>"."</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Inakagua..."</string> <string name="lockscreen_unlock_label" msgid="737440483220667054">"Fungua"</string> @@ -905,7 +905,7 @@ <string name="day" msgid="8144195776058119424">"siku"</string> <string name="days" msgid="4774547661021344602">"siku"</string> <string name="hour" msgid="2126771916426189481">"saa"</string> - <string name="hours" msgid="894424005266852993">"masaa"</string> + <string name="hours" msgid="894424005266852993">"saa"</string> <string name="minute" msgid="9148878657703769868">"dakika"</string> <string name="minutes" msgid="5646001005827034509">"Dakika"</string> <string name="second" msgid="3184235808021478">"sekunde"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index c7fc99399f71..12f80daefd00 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -243,14 +243,10 @@ <string name="permdesc_dump" msgid="1778299088692290329">"允许应用检索系统的内部状态。恶意应用可能会检索一般情况下绝不需要检索的多种私人信息和安全信息。"</string> <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"检索屏幕内容"</string> <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允许应用检索活动窗口的内容。恶意应用可能会检索整个窗口的内容,并检查其中除密码以外的所有文字。"</string> - <!-- no translation found for permlab_retrieve_window_info (8532295199112519378) --> - <skip /> - <!-- no translation found for permdesc_retrieve_window_info (4998836370424186849) --> - <skip /> - <!-- no translation found for permlab_filter_events (8675535648807427389) --> - <skip /> - <!-- no translation found for permdesc_filter_events (8006236315888347680) --> - <skip /> + <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"检索窗口信息"</string> + <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允许应用通过窗口管理器检索窗口信息。恶意应用可能会检索供内部系统使用的信息。"</string> + <string name="permlab_filter_events" msgid="8675535648807427389">"过滤活动"</string> + <string name="permdesc_filter_events" msgid="8006236315888347680">"允许应用注册输入过滤器,这类过滤器会在所有用户活动分派之前对这些用户活动的信息流进行过滤。恶意应用可能会在没有用户干预的情况下控制系统用户界面。"</string> <string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string> <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index a1c20ceb870e..8a8cb8e683ac 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -244,9 +244,9 @@ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"擷取螢幕內容"</string> <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允許應用程式擷取使用中的視窗內容。請注意,惡意應用程式可能利用此功能擷取完整視窗內容,並檢視密碼之外的所有文字。"</string> <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"擷取視窗資訊"</string> - <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允許應用程式透過視窗管理程式擷取視窗的相關資訊。惡意應用程式可能藉此擷取僅限內部系統使用的資訊。"</string> + <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允許應用程式透過視窗管理程式擷取視窗的相關資訊。請注意,惡意應用程式可能藉此擷取僅限內部系統使用的資訊。"</string> <string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string> - <string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有使用者活動的串流前先行篩選。惡意應用程式可能藉此擅自控制系統使用者介面。"</string> + <string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有使用者活動的串流前先行篩選。請注意,惡意應用程式可能藉此擅自控制系統使用者介面。"</string> <string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string> <string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string> <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string> diff --git a/core/tests/coretests/src/android/util/TimeUtilsTest.java b/core/tests/coretests/src/android/util/TimeUtilsTest.java index 8d9f8e55df80..74c8e04b8dc1 100644 --- a/core/tests/coretests/src/android/util/TimeUtilsTest.java +++ b/core/tests/coretests/src/android/util/TimeUtilsTest.java @@ -18,8 +18,6 @@ package android.util; import junit.framework.TestCase; -import android.util.TimeUtils; - import java.util.Calendar; import java.util.TimeZone; @@ -442,6 +440,13 @@ public class TimeUtilsTest extends TestCase { assertFormatDuration("+10s24ms", 10024); } + public void testFormatHugeDuration() { + //assertFormatDuration("+15542d1h11m11s555ms", 1342833071555L); + // TODO: improve formatDuration() API + assertFormatDuration("+999d23h59m59s999ms", 1342833071555L); + assertFormatDuration("-999d23h59m59s999ms", -1342833071555L); + } + private void assertFormatDuration(String expected, long duration) { StringBuilder sb = new StringBuilder(); TimeUtils.formatDuration(duration, sb); diff --git a/docs/html/guide/google/gcm/adv.jd b/docs/html/guide/google/gcm/adv.jd index 39e946ee34e0..5cb433f4f58d 100644 --- a/docs/html/guide/google/gcm/adv.jd +++ b/docs/html/guide/google/gcm/adv.jd @@ -203,7 +203,7 @@ registerReceiver(mRetryReceiver, filter); <p>GCM allows a maximum of 4 different collapse keys to be used by the GCM server at any given time. In other words, the GCM server can simultaneously store 4 different send-to-sync messages, each with a different collapse key. If you exceed this number GCM will only keep 4 collapse keys, with no guarantees about which ones they will be.</p> <h3 id="payload">Messages with payload</h3> -<p>Unlike a send-to-sync message, every "message with payload" (non-collapsible message) is delivered. The payload the message contains can be up to 4K. For example, here is a JSON-formatted message in an IM application in which spectators are discussing a sporting event:</p> +<p>Unlike a send-to-sync message, every "message with payload" (non-collapsible message) is delivered. The payload the message contains can be up to 4kb. For example, here is a JSON-formatted message in an IM application in which spectators are discussing a sporting event:</p> <pre class="prettyprint pretty-json">{ "registration_id" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...", diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd index 79edb9f234d5..1b95520bf78f 100644 --- a/docs/html/guide/google/gcm/gcm.jd +++ b/docs/html/guide/google/gcm/gcm.jd @@ -651,8 +651,8 @@ message sent by the application server. See <a href="adv.html#collapsible">Advan <tr> <td><code>data</code></td> <td>A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be -included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code> -There is no limit on the number of key/value pairs, though there is a limit on the total size of the message. Optional.</td> +included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. +There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). Note that the values <em>must be enclosed by strings</em>. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Optional.</td> </tr> <tr> <td><code>delay_while_idle</code></td> diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 3b3691c637d1..7f0ed7309b62 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -288,13 +288,13 @@ void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len } void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, - int numGlyphs, Rect *bounds) { + int numGlyphs, Rect *bounds, const float* positions) { if (bounds == NULL) { ALOGE("No return rectangle provided to measure text"); return; } bounds->set(1e6, -1e6, -1e6, 1e6); - render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, NULL); + render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions); } void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len, @@ -697,8 +697,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp } CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool allocate) { - uint8_t* textureMemory = NULL; - CacheTexture* cacheTexture = new CacheTexture(textureMemory, width, height); + CacheTexture* cacheTexture = new CacheTexture(width, height); if (allocate) { allocateTextureMemory(cacheTexture); @@ -1008,7 +1007,7 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) { } FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text, - uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius) { + uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) { checkInit(); if (!mCurrentFont) { @@ -1026,7 +1025,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch mBounds = NULL; Rect bounds; - mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds); + mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions); uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; @@ -1040,7 +1039,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch int penY = radius - bounds.bottom; mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, - dataBuffer, paddedWidth, paddedHeight); + Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); blurImage(dataBuffer, paddedWidth, paddedHeight, radius); DropShadow image; diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index 2ab680e0e379..9ed69325c914 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -61,9 +61,8 @@ class FontRenderer; class CacheTexture { public: - CacheTexture() { } - CacheTexture(uint8_t* texture, uint16_t width, uint16_t height) : - mTexture(texture), mTextureId(0), mWidth(width), mHeight(height), + CacheTexture(uint16_t width, uint16_t height) : + mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), mLinearFiltering(false) { } ~CacheTexture() { if (mTexture) { @@ -185,7 +184,7 @@ protected: uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, - int numGlyphs, Rect *bounds); + int numGlyphs, Rect *bounds, const float* positions); Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); @@ -274,7 +273,7 @@ public: // After renderDropShadow returns, the called owns the memory in DropShadow.image // and is responsible for releasing it when it's done with it DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, - uint32_t len, int numGlyphs, uint32_t radius); + uint32_t len, int numGlyphs, uint32_t radius, const float* positions); GLuint getTexture(bool linearFiltering = false) { checkInit(); diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h index 9180778e9aa9..c4a50bed3ad2 100644 --- a/libs/hwui/GammaFontRenderer.h +++ b/libs/hwui/GammaFontRenderer.h @@ -59,6 +59,7 @@ public: void clear() { delete mRenderer; + mRenderer = NULL; } void flush() { diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 0016b8145fda..7026eeadc5ce 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -16,8 +16,6 @@ #define LOG_TAG "OpenGLRenderer" -#include <GLES2/gl2.h> - #include <SkCanvas.h> #include <SkGradientShader.h> @@ -45,6 +43,8 @@ GradientCache::GradientCache(): INIT_LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE); } + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); + mCache.setOnEntryRemovedListener(this); } @@ -116,8 +116,11 @@ void GradientCache::clear() { Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) { + int width = 256 * (count - 1); + width = width < mMaxTextureSize ? width : mMaxTextureSize; + SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, 256 * (count - 1), 1); + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, 4); bitmap.allocPixels(); bitmap.eraseColor(0); @@ -134,7 +137,7 @@ Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, p.setStyle(SkPaint::kStrokeAndFill_Style); p.setShader(localShader)->unref(); - canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p); + canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 4.0f, p); // Asume the cache is always big enough const uint32_t size = bitmap.rowBytes() * bitmap.height(); diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index ac346846ba99..59515a1ceefb 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -17,6 +17,8 @@ #ifndef ANDROID_HWUI_GRADIENT_CACHE_H #define ANDROID_HWUI_GRADIENT_CACHE_H +#include <GLES2/gl2.h> + #include <SkShader.h> #include <utils/Mutex.h> @@ -152,6 +154,8 @@ private: uint32_t mSize; uint32_t mMaxSize; + GLint mMaxTextureSize; + Vector<SkShader*> mGarbage; mutable Mutex mLock; }; // class GradientCache diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 5fa3d3ebc9dc..6d781c77fa7a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2303,6 +2303,44 @@ status_t OpenGLRenderer::drawRect(float left, float top, float right, float bott return DrawGlInfo::kStatusDrew; } +void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count, + const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode, + float x, float y) { + mCaches.activeTexture(0); + + // NOTE: The drop shadow will not perform gamma correction + // if shader-based correction is enabled + mCaches.dropShadowCache.setFontRenderer(fontRenderer); + const ShadowTexture* shadow = mCaches.dropShadowCache.get( + paint, text, bytesCount, count, mShadowRadius, positions); + const AutoTexture autoCleanup(shadow); + + const float sx = x - shadow->left + mShadowDx; + const float sy = y - shadow->top + mShadowDy; + + const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha; + int shadowColor = mShadowColor; + if (mShader) { + shadowColor = 0xffffffff; + } + + setupDraw(); + setupDrawWithTexture(true); + setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha); + setupDrawColorFilter(); + setupDrawShader(); + setupDrawBlending(true, mode); + setupDrawProgram(); + setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height); + setupDrawTexture(shadow->id); + setupDrawPureColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawShaderUniforms(); + setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); +} + status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, const float* positions, SkPaint* paint) { if (text == NULL || count == 0 || mSnapshot->isIgnored() || @@ -2331,6 +2369,11 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); + if (CC_UNLIKELY(mHasShadow)) { + drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode, + 0.0f, 0.0f); + } + // Pick the appropriate texture filtering bool linearFilter = mSnapshot->transform->changesBounds(); if (pureTranslate && !linearFilter) { @@ -2424,39 +2467,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, getAlphaAndMode(paint, &alpha, &mode); if (CC_UNLIKELY(mHasShadow)) { - mCaches.activeTexture(0); - - // NOTE: The drop shadow will not perform gamma correction - // if shader-based correction is enabled - mCaches.dropShadowCache.setFontRenderer(fontRenderer); - const ShadowTexture* shadow = mCaches.dropShadowCache.get( - paint, text, bytesCount, count, mShadowRadius); - const AutoTexture autoCleanup(shadow); - - const float sx = oldX - shadow->left + mShadowDx; - const float sy = oldY - shadow->top + mShadowDy; - - const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha; - int shadowColor = mShadowColor; - if (mShader) { - shadowColor = 0xffffffff; - } - - setupDraw(); - setupDrawWithTexture(true); - setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha); - setupDrawColorFilter(); - setupDrawShader(); - setupDrawBlending(true, mode); - setupDrawProgram(); - setupDrawModelView(sx, sy, sx + shadow->width, sy + shadow->height); - setupDrawTexture(shadow->id); - setupDrawPureColorUniforms(); - setupDrawColorFilterUniforms(); - setupDrawShaderUniforms(); - setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); + drawTextShadow(paint, text, bytesCount, count, NULL, fontRenderer, alpha, mode, oldX, oldY); } // Pick the appropriate texture filtering diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 1926575bccc2..441e9fd6c8d8 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -498,6 +498,24 @@ private: void drawTextDecorations(const char* text, int bytesCount, float length, float x, float y, SkPaint* paint); + /** + * Draws shadow layer on text (with optional positions). + * + * @param paint The paint to draw the shadow with + * @param text The text to draw + * @param bytesCount The number of bytes in the text + * @param count The number of glyphs in the text + * @param positions The x, y positions of individual glyphs (or NULL) + * @param fontRenderer The font renderer object + * @param alpha The alpha value for drawing the shadow + * @param mode The xfermode for drawing the shadow + * @param x The x coordinate where the shadow will be drawn + * @param y The y coordinate where the shadow will be drawn + */ + void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count, + const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode, + float x, float y); + /** * Draws a path texture. Path textures are alpha8 bitmaps that need special * compositing to apply colors/filters/etc. @@ -507,7 +525,7 @@ private: * @param y The y coordinate where the texture will be drawn * @param paint The paint to draw the texture with */ - void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint); + void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint); /** * Resets the texture coordinates stored in mMeshVertices. Setting the values diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index cf5f82205e03..2153a8bb89ad 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -48,7 +48,8 @@ ResourceCache::~ResourceCache() { void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { Mutex::Autolock _l(mLock); - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ssize_t index = mCache->indexOfKey(resource); + ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; if (ref == NULL || mCache->size() == 0) { ref = new ResourceReference(resourceType); mCache->add(resource, ref); @@ -78,7 +79,8 @@ void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) { void ResourceCache::decrementRefcount(void* resource) { Mutex::Autolock _l(mLock); - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ssize_t index = mCache->indexOfKey(resource); + ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; if (ref == NULL) { // Should not get here - shouldn't get a call to decrement if we're not yet tracking it return; @@ -111,12 +113,13 @@ void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) { void ResourceCache::recycle(SkBitmap* resource) { Mutex::Autolock _l(mLock); - if (mCache->indexOfKey(resource) < 0) { + ssize_t index = mCache->indexOfKey(resource); + if (index < 0) { // not tracking this resource; just recycle the pixel data resource->setPixels(NULL, NULL); return; } - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ResourceReference* ref = mCache->valueAt(index); if (ref == NULL) { // Should not get here - shouldn't get a call to recycle if we're not yet tracking it return; @@ -129,7 +132,8 @@ void ResourceCache::recycle(SkBitmap* resource) { void ResourceCache::destructor(SkPath* resource) { Mutex::Autolock _l(mLock); - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ssize_t index = mCache->indexOfKey(resource); + ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; if (ref == NULL) { // If we're not tracking this resource, just delete it if (Caches::hasInstance()) { @@ -146,7 +150,8 @@ void ResourceCache::destructor(SkPath* resource) { void ResourceCache::destructor(SkBitmap* resource) { Mutex::Autolock _l(mLock); - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ssize_t index = mCache->indexOfKey(resource); + ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; if (ref == NULL) { // If we're not tracking this resource, just delete it if (Caches::hasInstance()) { @@ -163,7 +168,8 @@ void ResourceCache::destructor(SkBitmap* resource) { void ResourceCache::destructor(SkiaShader* resource) { Mutex::Autolock _l(mLock); - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ssize_t index = mCache->indexOfKey(resource); + ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; if (ref == NULL) { // If we're not tracking this resource, just delete it delete resource; @@ -177,7 +183,8 @@ void ResourceCache::destructor(SkiaShader* resource) { void ResourceCache::destructor(SkiaColorFilter* resource) { Mutex::Autolock _l(mLock); - ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; + ssize_t index = mCache->indexOfKey(resource); + ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; if (ref == NULL) { // If we're not tracking this resource, just delete it delete resource; diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index bef137371d44..93aa8a5c0af3 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -102,13 +102,13 @@ void TextDropShadowCache::clear() { } ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len, - int numGlyphs, uint32_t radius) { - ShadowText entry(paint, radius, len, text); + int numGlyphs, uint32_t radius, const float* positions) { + ShadowText entry(paint, radius, len, text, positions); ShadowTexture* texture = mCache.get(entry); if (!texture) { FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0, - len, numGlyphs, radius); + len, numGlyphs, radius, positions); texture = new ShadowTexture; texture->left = shadow.penX; diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h index e2bdde1eca89..bae0c49349f6 100644 --- a/libs/hwui/TextDropShadowCache.h +++ b/libs/hwui/TextDropShadowCache.h @@ -35,8 +35,9 @@ struct ShadowText { ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) { } - ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText): - radius(radius), len(len) { + ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText, + const float* positions): + radius(radius), len(len), positions(positions) { // TODO: Propagate this through the API, we should not cast here text = (const char16_t*) srcText; @@ -66,11 +67,18 @@ struct ShadowText { uint32_t italicStyle; uint32_t scaleX; const char16_t* text; + const float* positions; String16 str; + Vector<float> positionsCopy; void copyTextLocally() { str.setTo((const char16_t*) text, len >> 1); text = str.string(); + if (positions != NULL) { + positionsCopy.clear(); + positionsCopy.appendArray(positions, len); + positions = positionsCopy.array(); + } } bool operator<(const ShadowText& rhs) const { @@ -81,7 +89,12 @@ struct ShadowText { LTE_INT(flags) { LTE_INT(italicStyle) { LTE_INT(scaleX) { - return memcmp(text, rhs.text, len) < 0; + int cmp = memcmp(text, rhs.text, len); + if (cmp < 0) return true; + if (cmp == 0 && rhs.positions != NULL) { + if (positions == NULL) return true; + return memcmp(positions, rhs.positions, len << 2) < 0; + } } } } @@ -117,7 +130,7 @@ public: void operator()(ShadowText& text, ShadowTexture*& texture); ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len, - int numGlyphs, uint32_t radius); + int numGlyphs, uint32_t radius, const float* positions); /** * Clears the cache. This causes all textures to be deleted. diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java index aacf8572fcad..5ad60ab95932 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -19,6 +19,7 @@ package android.location; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemClock; import android.util.Printer; import java.text.DecimalFormat; @@ -59,6 +60,7 @@ public class Location implements Parcelable { private String mProvider; private long mTime = 0; + private long mElapsedRealtimeNano = 0; private double mLatitude = 0.0; private double mLongitude = 0.0; private boolean mHasAltitude = false; @@ -84,6 +86,7 @@ public class Location implements Parcelable { public void dump(Printer pw, String prefix) { pw.println(prefix + "mProvider=" + mProvider + " mTime=" + mTime); + pw.println(prefix + "mElapsedRealtimeNano=" + mElapsedRealtimeNano); pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude); pw.println(prefix + "mHasAltitude=" + mHasAltitude + " mAltitude=" + mAltitude); pw.println(prefix + "mHasSpeed=" + mHasSpeed + " mSpeed=" + mSpeed); @@ -118,6 +121,7 @@ public class Location implements Parcelable { public void set(Location l) { mProvider = l.mProvider; mTime = l.mTime; + mElapsedRealtimeNano = l.mElapsedRealtimeNano; mLatitude = l.mLatitude; mLongitude = l.mLongitude; mHasAltitude = l.mHasAltitude; @@ -137,6 +141,7 @@ public class Location implements Parcelable { public void reset() { mProvider = null; mTime = 0; + mElapsedRealtimeNano = 0; mLatitude = 0; mLongitude = 0; mHasAltitude = false; @@ -467,23 +472,62 @@ public class Location implements Parcelable { } /** - * Returns the UTC time of this fix, in milliseconds since January 1, + * Return the UTC time of this fix, in milliseconds since January 1, * 1970. + * <p>Note that the UTC time on a device is not monotonic: it + * can jump forwards or backwards unpredictably. So always use + * {@link #getElapsedRealtimeNano()} when calculating time deltas. + * <p>On the other hand, {@link #getTime()} is useful for presenting + * a human readable time to the user, or for carefully comparing + * location fixes across reboot or across devices. + * <p>This method will always return a valid timestamp on + * Locations generated by a {@link LocationProvider}. + * + * @return time of fix, in milliseconds since January 1, 1970. */ public long getTime() { return mTime; } /** - * Sets the UTC time of this fix, in milliseconds since January 1, + * Set the UTC time of this fix, in milliseconds since January 1, * 1970. + * + * @param time UTC time of this fix, in milliseconds since January 1, 1970 */ public void setTime(long time) { mTime = time; } /** - * Returns the latitude of this fix. + * Return the time of this fix, in elapsed real-time since system boot. + * <p>This value can be reliably compared to + * {@link android.os.SystemClock#elapsedRealtimeNano()}, + * to calculate the age of a fix, and to compare Location fixes, since + * elapsed real-time is guaranteed monotonic for each system boot, and + * continues to increment even when the system is in deep sleep. + * <p>This method will always return a valid timestamp on + * Locations generated by a {@link LocationProvider}. + * + * @return elapsed real-time of fix, in nanoseconds since system boot. + */ + public long getElapsedRealtimeNano() { + return mElapsedRealtimeNano; + } + + /** + * Set the time of this fix, in elapsed real-time since system boot. + * + * @param time elapsed real-time of fix, in nanoseconds since system boot. + */ + public void setElapsedRealtimeNano(long time) { + mElapsedRealtimeNano = time; + } + + /** + * Return the latitude of this fix. + * <p>This method will always return a valid latitude on + * Locations generated by a {@link LocationProvider}. */ public double getLatitude() { return mLatitude; @@ -497,7 +541,9 @@ public class Location implements Parcelable { } /** - * Returns the longitude of this fix. + * Return the longitude of this fix. + * <p>This method will always return a valid longitude on + * Locations generated by a {@link LocationProvider}. */ public double getLongitude() { return mLongitude; @@ -619,16 +665,27 @@ public class Location implements Parcelable { } /** - * Returns true if the provider is able to report accuracy information, - * false otherwise. The default implementation returns false. + * Return true if this Location has an associated accuracy. + * <p>All Location objects generated by a {@link LocationProvider} + * will have an accuracy. */ public boolean hasAccuracy() { return mHasAccuracy; } /** - * Returns the accuracy of the fix in meters. If hasAccuracy() is false, - * 0.0 is returned. + * Return the accuracy of this Location fix. + * <p>Accuracy is measured in meters, and indicates the + * radius of 95% confidence. + * In other words, there is a 95% probability that the + * true location is within a circle centered at the reported + * location, with radius of the reported accuracy. + * <p>This is only a measure of horizontal accuracy, and does + * not indicate the accuracy of bearing, velocity or altitude + * if those are included in this Location. + * <p>If {@link #hasAccuracy} is false, 0.0 is returned. + * <p>All Location object generated by a {@link LocationProvider} + * will have a valid accuracy. */ public float getAccuracy() { return mAccuracy; @@ -653,6 +710,37 @@ public class Location implements Parcelable { } /** + * Return true if this Location object has enough data set to + * be considered a valid fix from a {@link LocationProvider}. + * @see #makeComplete + * @hide + */ + public boolean isComplete() { + if (mProvider == null) return false; + if (!mHasAccuracy) return false; + if (mTime == 0) return false; + if (mElapsedRealtimeNano == 0) return false; + return true; + } + + /** + * Helper to fill in incomplete fields. + * Only use this to assist in backwards compatibility + * with Location objects received from applications. + * @see #isComplete + * @hide + */ + public void makeComplete() { + if (mProvider == null) mProvider = "?"; + if (!mHasAccuracy) { + mHasAccuracy = true; + mAccuracy = 100.0f; + } + if (mTime == 0) mTime = System.currentTimeMillis(); + if (mElapsedRealtimeNano == 0) mElapsedRealtimeNano = SystemClock.elapsedRealtimeNano(); + } + + /** * Returns additional provider-specific information about the * location fix as a Bundle. The keys and values are determined * by the provider. If no additional information is available, @@ -681,6 +769,7 @@ public class Location implements Parcelable { @Override public String toString() { return "Location[mProvider=" + mProvider + ",mTime=" + mTime + + ",mElapsedRealtimeNano=" + mElapsedRealtimeNano + ",mLatitude=" + mLatitude + ",mLongitude=" + mLongitude + ",mHasAltitude=" + mHasAltitude + @@ -700,6 +789,7 @@ public class Location implements Parcelable { String provider = in.readString(); Location l = new Location(provider); l.mTime = in.readLong(); + l.mElapsedRealtimeNano = in.readLong(); l.mLatitude = in.readDouble(); l.mLongitude = in.readDouble(); l.mHasAltitude = in.readInt() != 0; @@ -726,6 +816,7 @@ public class Location implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(mProvider); parcel.writeLong(mTime); + parcel.writeLong(mElapsedRealtimeNano); parcel.writeDouble(mLatitude); parcel.writeDouble(mLongitude); parcel.writeInt(mHasAltitude ? 1 : 0); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index ff74f41adf30..15a29286098d 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -19,11 +19,13 @@ package android.location; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.os.RemoteException; import android.os.Handler; import android.os.Message; +import android.os.SystemClock; import android.util.Log; import com.android.internal.location.DummyLocationProvider; @@ -1220,8 +1222,11 @@ public class LocationManager { } /** - * Sets a mock location for the given provider. This location will be used in place - * of any actual location from the provider. + * Sets a mock location for the given provider. + * <p>This location will be used in place of any actual location from the provider. + * The location object must have a minimum number of fields set to be + * considered a valid LocationProvider Location, as per documentation + * on {@link Location} class. * * @param provider the provider name * @param loc the mock location @@ -1230,8 +1235,20 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @throws IllegalArgumentException if the location is incomplete */ public void setTestProviderLocation(String provider, Location loc) { + if (!loc.isComplete()) { + if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) { + // for backwards compatibility, allow mock locations that are incomplete + Log.w(TAG, "Incomplete Location object", new Throwable()); + loc.makeComplete(); + } else { + throw new IllegalArgumentException( + "Location object not complete. Missing timestamps or accuracy?"); + } + } + try { mService.setTestProviderLocation(provider, loc); } catch (RemoteException ex) { diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 888564b91329..2c66897983d4 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -48,12 +48,12 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلانها"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"تنظیم روشهای ورودی"</string> - <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه کلید فیزیکی"</string> + <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحهکلید فیزیکی"</string> <string name="usb_device_permission_prompt" msgid="834698001271562057">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهید به دستگاه USB دسترسی داشته باشد؟"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهد تا به وسیله جانبی USB دسترسی داشته باشد؟"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"وقتی این دستگاه USB وصل است، <xliff:g id="ACTIVITY">%1$s</xliff:g> باز شود؟"</string> <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"وقتی این وسیله جانبی USB وصل است، <xliff:g id="ACTIVITY">%1$s</xliff:g> باز شود؟"</string> - <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"هیچ برنامه کاربردی نصب شدهای با این وسیله جانبی USB کار نمیکند. در <xliff:g id="URL">%1$s</xliff:g> درباره این وسیله جانبی اطلاعات بیشتری کسب کنید"</string> + <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"هیچ برنامهٔ کاربردی نصب شدهای با این وسیله جانبی USB کار نمیکند. در <xliff:g id="URL">%1$s</xliff:g> دربارهٔ این وسیله جانبی اطلاعات بیشتری کسب کنید"</string> <string name="title_usb_accessory" msgid="4966265263465181372">"لوازم جانبی USB"</string> <string name="label_view" msgid="6304565553218192990">"مشاهده"</string> <string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیشفرض برای این دستگاه USB"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 00d3bac78eb1..b333bbec931e 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -51,7 +51,7 @@ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha ziada cha USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Je, ungetaka kufungua <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string> <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Je, ungetaka kufungua <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string> - <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Jifunze zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string> + <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Pata maelezo zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string> <string name="title_usb_accessory" msgid="4966265263465181372">"Kifaa cha Usb"</string> <string name="label_view" msgid="6304565553218192990">"Ona"</string> <string name="always_use_device" msgid="1450287437017315906">"Kwa kifaa hiki cha USB tumia chaguo-msingi"</string> diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 0bdf84a05692..cb69660cb729 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -21,6 +21,7 @@ import android.animation.LayoutTransition; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.ActivityOptions; +import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; @@ -845,8 +846,9 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener 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); + intent.setComponent(intent.resolveActivity(mContext.getPackageManager())); + TaskStackBuilder.create(getContext()) + .addNextIntentWithParentStack(intent).startActivities(); } public boolean onInterceptTouchEvent(MotionEvent ev) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index bd8be1f349f3..b392648b6864 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -16,9 +16,24 @@ package com.android.systemui.statusbar; +import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.statusbar.StatusBarIcon; +import com.android.internal.statusbar.StatusBarIconList; +import com.android.internal.statusbar.StatusBarNotification; +import com.android.internal.widget.SizeAdaptiveLayout; +import com.android.systemui.R; +import com.android.systemui.SearchPanelView; +import com.android.systemui.SystemUI; +import com.android.systemui.recent.RecentTasksLoader; +import com.android.systemui.recent.RecentsPanelView; +import com.android.systemui.recent.TaskDescription; +import com.android.systemui.statusbar.policy.NotificationRowLayout; +import com.android.systemui.statusbar.tablet.StatusBarPanel; + import android.app.ActivityManagerNative; import android.app.KeyguardManager; import android.app.PendingIntent; +import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -51,22 +66,6 @@ import android.widget.LinearLayout; import android.widget.PopupMenu; import android.widget.RemoteViews; -import com.android.internal.statusbar.IStatusBarService; -import com.android.internal.statusbar.StatusBarIcon; -import com.android.internal.statusbar.StatusBarIconList; -import com.android.internal.statusbar.StatusBarNotification; -import com.android.internal.widget.SizeAdaptiveLayout; -import com.android.systemui.R; -import com.android.systemui.SearchPanelView; -import com.android.systemui.SystemUI; -import com.android.systemui.recent.RecentTasksLoader; -import com.android.systemui.recent.RecentsPanelView; -import com.android.systemui.recent.TaskDescription; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.NotificationData.Entry; -import com.android.systemui.statusbar.policy.NotificationRowLayout; -import com.android.systemui.statusbar.tablet.StatusBarPanel; - import java.util.ArrayList; public abstract class BaseStatusBar extends SystemUI implements @@ -299,8 +298,8 @@ public abstract class BaseStatusBar extends SystemUI implements 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); - mContext.startActivity(intent); + intent.setComponent(intent.resolveActivity(mContext.getPackageManager())); + TaskStackBuilder.create(mContext).addNextIntentWithParentStack(intent).startActivities(); } protected View.OnLongClickListener getNotificationLongClicker() { diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml index 7bd5590b2846..ec163af0c444 100644 --- a/packages/VpnDialogs/res/values-fa/strings.xml +++ b/packages/VpnDialogs/res/values-fa/strings.xml @@ -17,7 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="8359175999006833462">"<xliff:g id="APP">%s</xliff:g> تلاش میکند یک اتصال VPN ایجاد کند."</string> - <string name="warning" msgid="5470743576660160079">"با ادامه دادن، به برنامه کاربردی اجازه میدهید تمام ترافیک شبکه را رهگیری کند. "<b>"تا به برنامه اعتماد نکردید آن را قبول نکنید."</b>" در غیر این صورت، این ریسک را قبول میکنید که دادههای شما توسط یک نرمافزار مخرب به خطر بیفتد."</string> + <string name="warning" msgid="5470743576660160079">"با ادامه دادن، به برنامهٔ کاربردی اجازه میدهید تمام ترافیک شبکه را رهگیری کند. "<b>"تا به برنامه اعتماد نکردید آن را قبول نکنید."</b>" در غیر این صورت، این ریسک را قبول میکنید که دادههای شما توسط یک نرمافزار مخرب به خطر بیفتد."</string> <string name="accept" msgid="2889226408765810173">"من به این برنامه اعتماد دارم."</string> <string name="legacy_title" msgid="192936250066580964">"VPN متصل است"</string> <string name="configure" msgid="4905518375574791375">"پیکربندی"</string> diff --git a/services/common_time/clock_recovery.cpp b/services/common_time/clock_recovery.cpp index 4a5b2ef11694..3a7c70c3e17d 100644 --- a/services/common_time/clock_recovery.cpp +++ b/services/common_time/clock_recovery.cpp @@ -225,6 +225,9 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, if (current_point == min_rtt || rtt < control_thresh_) { delta_f = delta = nominal_common_time - observed_common; + last_error_est_valid_ = true; + last_error_est_usec_ = delta; + // Compute the error then clamp to the panic threshold. If we ever // exceed this amt of error, its time to panic and reset the system. // Given that the error in the measurement of the error could be as @@ -258,7 +261,6 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, // Save error terms for later. last_delta_f_ = delta_f; - last_delta_ = delta; // Clamp CO to +/- 100ppm. if (CO < COmin) @@ -295,8 +297,8 @@ bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, int32_t ClockRecoveryLoop::getLastErrorEstimate() { Mutex::Autolock lock(&lock_); - if (last_delta_valid_) - return last_delta_; + if (last_error_est_valid_) + return last_error_est_usec_; else return ICommonClock::kErrorEstimateUnknown; } @@ -310,8 +312,8 @@ void ClockRecoveryLoop::reset_l(bool position, bool frequency) { } if (frequency) { - last_delta_valid_ = false; - last_delta_ = 0; + last_error_est_valid_ = false; + last_error_est_usec_ = 0; last_delta_f_ = 0.0; CO = 0.0f; lastCObias = CObias = 0.0f; diff --git a/services/common_time/clock_recovery.h b/services/common_time/clock_recovery.h index 20fbf96602c3..b6c87ffaf37e 100644 --- a/services/common_time/clock_recovery.h +++ b/services/common_time/clock_recovery.h @@ -108,8 +108,8 @@ class ClockRecoveryLoop { // parameters maintained while running and reset during a reset // of the frequency correction. - bool last_delta_valid_; - int32_t last_delta_; + bool last_error_est_valid_; + int32_t last_error_est_usec_; float last_delta_f_; int32_t integrated_error_; int32_t tgt_correction_; diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp index 0125709b5556..16be8f1ce00c 100644 --- a/services/common_time/common_time_server.cpp +++ b/services/common_time/common_time_server.cpp @@ -107,6 +107,9 @@ CommonTimeServer::CommonTimeServer() , mTimelineID(ICommonClock::kInvalidTimelineID) , mClockSynced(false) , mCommonClockHasClients(false) + , mStateChangeLog("Recent State Change Events", 30) + , mElectionLog("Recent Master Election Traffic", 30) + , mBadPktLog("Recent Bad Packet RX Info", 8) , mInitial_WhoIsMasterRequestTimeouts(0) , mClient_MasterDeviceID(0) , mClient_MasterDevicePriority(0) @@ -330,10 +333,11 @@ bool CommonTimeServer::runStateMachine_l() { // we are in any other state (CLIENT, RONIN or WAIT_FOR_ELECTION), // then transition to either INITIAL or MASTER depending on whether // or not our timeline is valid. - ALOGI("Entering networkless mode interface is %s, " - "shouldAutoDisable = %s", - mBindIfaceValid ? "valid" : "invalid", - shouldAutoDisable() ? "true" : "false"); + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "Entering networkless mode interface is %s, " + "shouldAutoDisable = %s", + mBindIfaceValid ? "valid" : "invalid", + shouldAutoDisable() ? "true" : "false"); if ((mState != ICommonClock::STATE_INITIAL) && (mState != ICommonClock::STATE_MASTER)) { if (mTimelineID == ICommonClock::kInvalidTimelineID) @@ -415,20 +419,23 @@ bool CommonTimeServer::setupSocket_l() { sockaddrToString(mMasterElectionEP, true, masterElectionEPStr, sizeof(masterElectionEPStr)); - ALOGI("Building socket :: bind = %s master election = %s", - mBindIface.string(), masterElectionEPStr); + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "Building socket :: bind = %s master election = %s", + mBindIface.string(), masterElectionEPStr); // TODO: add proper support for IPv6. Right now, we block IPv6 addresses at // the configuration interface level. if (AF_INET != mMasterElectionEP.ss_family) { - ALOGW("TODO: add proper IPv6 support"); + mStateChangeLog.log(ANDROID_LOG_WARN, LOG_TAG, + "TODO: add proper IPv6 support"); goto bailout; } // open a UDP socket for the timeline serivce mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (mSocket < 0) { - ALOGE("Failed to create socket (errno = %d)", errno); + mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to create socket (errno = %d)", errno); goto bailout; } @@ -440,8 +447,9 @@ bool CommonTimeServer::setupSocket_l() { rc = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)); if (rc) { - ALOGE("Failed to bind socket at to interface %s (errno = %d)", - ifr.ifr_name, errno); + mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to bind socket at to interface %s " + "(errno = %d)", ifr.ifr_name, errno); goto bailout; } @@ -459,8 +467,9 @@ bool CommonTimeServer::setupSocket_l() { reinterpret_cast<const sockaddr *>(&bindAddr), sizeof(bindAddr)); if (rc) { - ALOGE("Failed to bind socket to port %hu (errno = %d)", - ntohs(bindAddr.sin_port), errno); + mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to bind socket to port %hu (errno = %d)", + ntohs(bindAddr.sin_port), errno); goto bailout; } @@ -483,17 +492,20 @@ bool CommonTimeServer::setupSocket_l() { rc = setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)); if (rc == -1) { - ALOGE("Failed to disable multicast loopback (errno = %d)", errno); + mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to disable multicast loopback " + "(errno = %d)", errno); goto bailout; } } else if (ntohl(ipv4_addr->sin_addr.s_addr) == 0xFFFFFFFF) { // If the master election address is the broadcast address, then enable // the broadcast socket option - const int one = 1; rc = setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)); if (rc == -1) { - ALOGE("Failed to enable broadcast (errno = %d)", errno); + mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to enable broadcast (errno = %d)", + errno); goto bailout; } } else { @@ -507,7 +519,8 @@ bool CommonTimeServer::setupSocket_l() { // the local subnet) rc = setsockopt(mSocket, IPPROTO_IP, IP_TTL, &one, sizeof(one)); if (rc == -1) { - ALOGE("Failed to set TTL to %d (errno = %d)", one, errno); + mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to set TTL to %d (errno = %d)", one, errno); goto bailout; } @@ -569,6 +582,31 @@ bool CommonTimeServer::arbitrateMaster( ((devicePrio1 == devicePrio2) && (deviceID1 > deviceID2))); } +static void hexDumpToString(const uint8_t* src, size_t src_len, + char* dst, size_t dst_len) { + size_t offset; + size_t i; + + for (i = 0; (i < src_len) && (offset < dst_len); ++i) { + int res; + if (0 == (i % 16)) { + res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i); + if (res < 0) + break; + offset += res; + if (offset >= dst_len) + break; + } + + res = snprintf(dst + offset, dst_len - offset, " %02x", src[i]); + if (res < 0) + break; + offset += res; + } + + dst[dst_len - 1] = 0; +} + bool CommonTimeServer::handlePacket() { uint8_t buf[256]; struct sockaddr_storage srcAddr; @@ -579,14 +617,24 @@ bool CommonTimeServer::handlePacket() { reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen); if (recvBytes < 0) { - ALOGE("%s:%d recvfrom failed", __PRETTY_FUNCTION__, __LINE__); + mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG, + "recvfrom failed (res %d, errno %d)", + recvBytes, errno); return false; } UniversalTimeServicePacket pkt; - recvBytes = pkt.deserializePacket(buf, recvBytes, mSyncGroupID); - if (recvBytes < 0) + if (pkt.deserializePacket(buf, recvBytes, mSyncGroupID) < 0) { + char hex[256]; + char srcEPStr[64]; + + hexDumpToString(buf, static_cast<size_t>(recvBytes), hex, sizeof(hex)); + sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); + + mBadPktLog.log("Failed to parse %d byte packet from %s.%s", + recvBytes, srcEPStr, hex); return false; + } bool result; switch (pkt.packetType) { @@ -614,8 +662,13 @@ bool CommonTimeServer::handlePacket() { break; default: { - ALOGD("%s:%d unknown packet type(%d)", - __PRETTY_FUNCTION__, __LINE__, pkt.packetType); + char srcEPStr[64]; + sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); + + mBadPktLog.log(ANDROID_LOG_WARN, LOG_TAG, + "unknown packet type (%d) from %s", + pkt.packetType, srcEPStr); + result = false; } break; } @@ -699,6 +752,14 @@ bool CommonTimeServer::handleTimeoutWaitForElection() { bool CommonTimeServer::handleWhoIsMasterRequest( const WhoIsMasterRequestPacket* request, const sockaddr_storage& srcAddr) { + + char srcEPStr[64]; + sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); + mElectionLog.log("RXed WhoIs master request while in state %s. " + "src %s reqTID %016llx ourTID %016llx", + stateToString(mState), srcEPStr, + request->timelineID, mTimelineID); + if (mState == ICommonClock::STATE_MASTER) { // is this request related to this master's timeline? if (request->timelineID != ICommonClock::kInvalidTimelineID && @@ -710,6 +771,13 @@ bool CommonTimeServer::handleWhoIsMasterRequest( pkt.deviceID = mDeviceID; pkt.devicePriority = effectivePriority(); + mElectionLog.log("TXing WhoIs master resp to %s while in state %s. " + "ourTID %016llx ourGID %016llx ourDID %016llx " + "ourPrio %u", + srcEPStr, stateToString(mState), + mTimelineID, mSyncGroupID, + pkt.deviceID, pkt.devicePriority); + uint8_t buf[256]; ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); if (bufSz < 0) @@ -761,6 +829,17 @@ bool CommonTimeServer::handleWhoIsMasterRequest( bool CommonTimeServer::handleWhoIsMasterResponse( const WhoIsMasterResponsePacket* response, const sockaddr_storage& srcAddr) { + char srcEPStr[64]; + sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); + mElectionLog.log("RXed WhoIs master response while in state %s. " + "src %s respTID %016llx respDID %016llx respPrio %u " + "ourTID %016llx", + stateToString(mState), srcEPStr, + response->timelineID, + response->deviceID, + static_cast<uint32_t>(response->devicePriority), + mTimelineID); + if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN) { return becomeClient(srcAddr, response->deviceID, @@ -917,6 +996,14 @@ bool CommonTimeServer::handleMasterAnnouncement( uint8_t newDevicePrio = packet->devicePriority; uint64_t newTimelineID = packet->timelineID; + char srcEPStr[64]; + sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); + mElectionLog.log("RXed master announcement while in state %s. " + "src %s srcDevID %lld srcPrio %u srcTID %016llx", + stateToString(mState), srcEPStr, + newDeviceID, static_cast<uint32_t>(newDevicePrio), + newTimelineID); + if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN || mState == ICommonClock::STATE_WAIT_FOR_ELECTION) { @@ -973,6 +1060,15 @@ bool CommonTimeServer::sendWhoIsMasterRequest() { uint8_t buf[256]; ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); if (bufSz >= 0) { + char dstEPStr[64]; + sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr)); + mElectionLog.log("TXing WhoIs master request to %s while in state %s. " + "ourTID %016llx ourGID %016llx ourDID %016llx " + "ourPrio %u", + dstEPStr, stateToString(mState), + mTimelineID, mSyncGroupID, + pkt.senderDeviceID, pkt.senderDevicePriority); + ssize_t sendBytes = sendto( mSocket, buf, bufSz, 0, reinterpret_cast<const sockaddr *>(&mMasterElectionEP), @@ -1049,6 +1145,15 @@ bool CommonTimeServer::sendMasterAnnouncement() { uint8_t buf[256]; ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); if (bufSz >= 0) { + char dstEPStr[64]; + sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr)); + mElectionLog.log("TXing Master announcement to %s while in state %s. " + "ourTID %016llx ourGID %016llx ourDID %016llx " + "ourPrio %u", + dstEPStr, stateToString(mState), + mTimelineID, mSyncGroupID, + pkt.deviceID, pkt.devicePriority); + ssize_t sendBytes = sendto( mSocket, buf, bufSz, 0, reinterpret_cast<const sockaddr *>(&mMasterElectionEP), @@ -1071,15 +1176,16 @@ bool CommonTimeServer::becomeClient(const sockaddr_storage& masterEP, sockaddrToString(masterEP, true, newEPStr, sizeof(newEPStr)); sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr)); - ALOGI("%s --> CLIENT (%s) :%s" - " OldMaster: %02x-%014llx::%016llx::%s" - " NewMaster: %02x-%014llx::%016llx::%s", - stateToString(mState), cause, - (mTimelineID != timelineID) ? " (new timeline)" : "", - mClient_MasterDevicePriority, mClient_MasterDeviceID, - mTimelineID, oldEPStr, - masterDevicePriority, masterDeviceID, - timelineID, newEPStr); + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "%s --> CLIENT (%s) :%s" + " OldMaster: %02x-%014llx::%016llx::%s" + " NewMaster: %02x-%014llx::%016llx::%s", + stateToString(mState), cause, + (mTimelineID != timelineID) ? " (new timeline)" : "", + mClient_MasterDevicePriority, mClient_MasterDeviceID, + mTimelineID, oldEPStr, + masterDevicePriority, masterDeviceID, + timelineID, newEPStr); if (mTimelineID != timelineID) { // start following a new timeline @@ -1132,11 +1238,12 @@ bool CommonTimeServer::becomeMaster(const char* cause) { notifyClockSync(); } - ALOGI("%s --> MASTER (%s) : %s timeline %016llx", - stateToString(mState), cause, - (oldTimelineID == mTimelineID) ? "taking ownership of" - : "creating new", - mTimelineID); + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "%s --> MASTER (%s) : %s timeline %016llx", + stateToString(mState), cause, + (oldTimelineID == mTimelineID) ? "taking ownership of" + : "creating new", + mTimelineID); memset(&mMasterEP, 0, sizeof(mMasterEP)); mMasterEPValid = false; @@ -1165,7 +1272,8 @@ bool CommonTimeServer::becomeRonin(const char* cause) { mMasterEPValid = false; if (mCommonClock.isValid()) { - ALOGI("%s --> RONIN (%s) : lost track of previously valid timeline " + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "%s --> RONIN (%s) : lost track of previously valid timeline " "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)", stateToString(mState), cause, mClient_MasterDevicePriority, mClient_MasterDeviceID, @@ -1178,7 +1286,8 @@ bool CommonTimeServer::becomeRonin(const char* cause) { setState(ICommonClock::STATE_RONIN); return sendWhoIsMasterRequest(); } else { - ALOGI("%s --> INITIAL (%s) : never synced timeline " + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "%s --> INITIAL (%s) : never synced timeline " "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)", stateToString(mState), cause, mClient_MasterDevicePriority, mClient_MasterDeviceID, @@ -1192,7 +1301,8 @@ bool CommonTimeServer::becomeRonin(const char* cause) { } bool CommonTimeServer::becomeWaitForElection(const char* cause) { - ALOGI("%s --> WAIT_FOR_ELECTION (%s) : dropping out of election," + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "%s --> WAIT_FOR_ELECTION (%s) : dropping out of election," " waiting %d mSec for completion.", stateToString(mState), cause, kWaitForElection_TimeoutMs); @@ -1202,7 +1312,9 @@ bool CommonTimeServer::becomeWaitForElection(const char* cause) { } bool CommonTimeServer::becomeInitial(const char* cause) { - ALOGI("Entering INITIAL (%s), total reset.", cause); + mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, + "Entering INITIAL (%s), total reset.", + cause); setState(ICommonClock::STATE_INITIAL); diff --git a/services/common_time/common_time_server.h b/services/common_time/common_time_server.h index b2ad3f01b46d..f6a24191fb31 100644 --- a/services/common_time/common_time_server.h +++ b/services/common_time/common_time_server.h @@ -238,6 +238,11 @@ class CommonTimeServer : public Thread { // interface AND currently active common clock clients. bool mCommonClockHasClients; + // Internal logs used for dumpsys. + LogRing mStateChangeLog; + LogRing mElectionLog; + LogRing mBadPktLog; + // Configuration info struct sockaddr_storage mMasterElectionEP; // Endpoint over which we conduct master election String8 mBindIface; // Endpoint for the service to bind to. diff --git a/services/common_time/common_time_server_api.cpp b/services/common_time/common_time_server_api.cpp index fb8c2615e1c0..e15707181bca 100644 --- a/services/common_time/common_time_server_api.cpp +++ b/services/common_time/common_time_server_api.cpp @@ -354,6 +354,9 @@ status_t CommonTimeServer::dumpClockInterface(int fd, dump_printf("Active Clients : %u\n", activeClients); mClient_PacketRTTLog.dumpLog(fd, mCommonClock); + mStateChangeLog.dumpLog(fd); + mElectionLog.dumpLog(fd); + mBadPktLog.dumpLog(fd); } return NO_ERROR; diff --git a/services/common_time/utils.cpp b/services/common_time/utils.cpp index 3ed259944cf1..ed2c77ddb3a5 100644 --- a/services/common_time/utils.cpp +++ b/services/common_time/utils.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ +#define LOG_TAG "common_time" +#include <utils/Log.h> + #include "utils.h" namespace android { @@ -46,4 +49,116 @@ int Timeout::msecTillTimeout(nsecs_t nowTime) { return static_cast<int>(delta); } +LogRing::LogRing(const char* header, size_t entries) + : mSize(entries) + , mWr(0) + , mIsFull(false) + , mHeader(header) { + mRingBuffer = new Entry[mSize]; + if (NULL == mRingBuffer) + ALOGE("Failed to allocate log ring with %u entries.", mSize); +} + +LogRing::~LogRing() { + if (NULL != mRingBuffer) + delete[] mRingBuffer; +} + +void LogRing::log(int prio, const char* tag, const char* fmt, ...) { + va_list argp; + va_start(argp, fmt); + internalLog(prio, tag, fmt, argp); + va_end(argp); +} + +void LogRing::log(const char* fmt, ...) { + va_list argp; + va_start(argp, fmt); + internalLog(0, NULL, fmt, argp); + va_end(argp); +} + +void LogRing::internalLog(int prio, + const char* tag, + const char* fmt, + va_list argp) { + if (NULL != mRingBuffer) { + Mutex::Autolock lock(&mLock); + String8 s(String8::formatV(fmt, argp)); + Entry* last = NULL; + + if (mIsFull || mWr) + last = &(mRingBuffer[(mWr + mSize - 1) % mSize]); + + + if ((NULL != last) && !last->s.compare(s)) { + gettimeofday(&(last->last_ts), NULL); + ++last->count; + } else { + gettimeofday(&mRingBuffer[mWr].first_ts, NULL); + mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts; + mRingBuffer[mWr].count = 1; + mRingBuffer[mWr].s.setTo(s); + + mWr = (mWr + 1) % mSize; + if (!mWr) + mIsFull = true; + } + } + + if (NULL != tag) + LOG_PRI_VA(prio, tag, fmt, argp); +} + +void LogRing::dumpLog(int fd) { + if (NULL == mRingBuffer) + return; + + Mutex::Autolock lock(&mLock); + + if (!mWr && !mIsFull) + return; + + char buf[1024]; + int res; + size_t start = mIsFull ? mWr : 0; + size_t count = mIsFull ? mSize : mWr; + static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S"; + + res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader); + if (res > 0) + write(fd, buf, res); + + for (size_t i = 0; i < count; ++i) { + struct tm t; + char timebuf[64]; + char repbuf[96]; + size_t ndx = (start + i) % mSize; + + if (1 != mRingBuffer[ndx].count) { + localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t); + strftime(timebuf, sizeof(timebuf), kTimeFmt, &t); + snprintf(repbuf, sizeof(repbuf), + " (repeated %d times, last was %s.%03ld)", + mRingBuffer[ndx].count, + timebuf, + mRingBuffer[ndx].last_ts.tv_usec / 1000); + repbuf[sizeof(repbuf) - 1] = 0; + } else { + repbuf[0] = 0; + } + + localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t); + strftime(timebuf, sizeof(timebuf), kTimeFmt, &t); + res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n", + i, timebuf, + mRingBuffer[ndx].first_ts.tv_usec / 1000, + mRingBuffer[ndx].s.string(), + repbuf); + + if (res > 0) + write(fd, buf, res); + } +} + } // namespace android diff --git a/services/common_time/utils.h b/services/common_time/utils.h index d3545c972b07..c28cf0ac33d7 100644 --- a/services/common_time/utils.h +++ b/services/common_time/utils.h @@ -20,6 +20,8 @@ #include <stdint.h> #include <unistd.h> +#include <utils/String8.h> +#include <utils/threads.h> #include <utils/Timers.h> namespace android { @@ -43,6 +45,39 @@ class Timeout { nsecs_t mSystemEndTime; }; +class LogRing { + public: + LogRing(const char* header, size_t entries); + ~LogRing(); + + // Send a log message to logcat as well as storing it in the ring buffer. + void log(int prio, const char* tag, const char* fmt, ...); + + // Add a log message the ring buffer, do not send the message to logcat. + void log(const char* fmt, ...); + + // Dump the log to an fd (dumpsys style) + void dumpLog(int fd); + + private: + class Entry { + public: + uint32_t count; + struct timeval first_ts; + struct timeval last_ts; + String8 s; + }; + + Mutex mLock; + Entry* mRingBuffer; + size_t mSize; + size_t mWr; + bool mIsFull; + const char* mHeader; + + void internalLog(int prio, const char* tag, const char* fmt, va_list va); +}; + } // namespace android #endif // __UTILS_H__ diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 06b056d4abe0..1498a115534d 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -1532,6 +1532,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission"); } + if (!location.isComplete()) { + Log.w(TAG, "Dropping incomplete location: " + location); + return; + } + mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location); Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location); m.arg1 = (passive ? 1 : 0); @@ -1588,7 +1593,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Check whether sufficient time has passed long minTime = record.mMinTime; - if (loc.getTime() - lastLoc.getTime() < minTime - MAX_PROVIDER_SCHEDULING_JITTER) { + long delta = (loc.getElapsedRealtimeNano() - lastLoc.getElapsedRealtimeNano()) / 1000000L; + if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER) { return false; } diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java index d1f92a7dc72a..5299b719ac4b 100644 --- a/services/java/com/android/server/UiModeManagerService.java +++ b/services/java/com/android/server/UiModeManagerService.java @@ -308,7 +308,7 @@ class UiModeManagerService extends IUiModeManager.Stub { /* if new location is older than the current one, the devices hasn't * moved. */ - if (location.getTime() < mLocation.getTime()) { + if (location.getElapsedRealtimeNano() < mLocation.getElapsedRealtimeNano()) { return false; } @@ -764,7 +764,8 @@ class UiModeManagerService extends IUiModeManager.Stub { mLocationManager.getLastKnownLocation(providers.next()); // pick the most recent location if (location == null || (lastKnownLocation != null && - location.getTime() < lastKnownLocation.getTime())) { + location.getElapsedRealtimeNano() < + lastKnownLocation.getElapsedRealtimeNano())) { location = lastKnownLocation; } } @@ -781,6 +782,7 @@ class UiModeManagerService extends IUiModeManager.Stub { location.setLatitude(0); location.setAccuracy(417000.0f); location.setTime(System.currentTimeMillis()); + location.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano()); } synchronized (mLock) { mLocation = location; diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index 4ad6140d1471..8e75d9447eeb 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -1078,6 +1078,9 @@ public class GpsLocationProvider implements LocationProviderInterface { mLocation.setLatitude(latitude); mLocation.setLongitude(longitude); mLocation.setTime(timestamp); + // It would be nice to push the elapsed real-time timestamp + // further down the stack, but this is still useful + mLocation.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano()); } if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) { mLocation.setAltitude(altitude); diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/java/com/android/server/location/LocationBasedCountryDetector.java index d4fb8ee5abb0..38871d787b47 100755 --- a/services/java/com/android/server/location/LocationBasedCountryDetector.java +++ b/services/java/com/android/server/location/LocationBasedCountryDetector.java @@ -114,7 +114,9 @@ public class LocationBasedCountryDetector extends CountryDetectorBase { for (String provider : providers) { Location lastKnownLocation = mLocationManager.getLastKnownLocation(provider); if (lastKnownLocation != null) { - if (bestLocation == null || bestLocation.getTime() < lastKnownLocation.getTime()) { + if (bestLocation == null || + bestLocation.getElapsedRealtimeNano() < + lastKnownLocation.getElapsedRealtimeNano()) { bestLocation = lastKnownLocation; } } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java deleted file mode 100644 index 3bb7c060e9e3..000000000000 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (C) 2012 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.telephony; - -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; - -import static com.android.internal.telephony.SmsUsageMonitor.CATEGORY_FREE_SHORT_CODE; -import static com.android.internal.telephony.SmsUsageMonitor.CATEGORY_NOT_SHORT_CODE; -import static com.android.internal.telephony.SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE; -import static com.android.internal.telephony.SmsUsageMonitor.CATEGORY_PREMIUM_SHORT_CODE; -import static com.android.internal.telephony.SmsUsageMonitor.CATEGORY_STANDARD_SHORT_CODE; - -/** - * Test cases for SMS short code pattern matching in SmsUsageMonitor. - */ -public class SmsUsageMonitorShortCodeTest extends AndroidTestCase { - - private static final class ShortCodeTest { - final String countryIso; - final String address; - final int category; - - ShortCodeTest(String countryIso, String destAddress, int category) { - this.countryIso = countryIso; - this.address = destAddress; - this.category = category; - } - } - - /** - * List of short code test cases. - */ - private static final ShortCodeTest[] sShortCodeTests = new ShortCodeTest[] { - new ShortCodeTest("al", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("al", "4321", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("al", "54321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("al", "15191", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("al", "55500", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("al", "55600", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("al", "654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("am", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("am", "101", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("am", "102", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("am", "103", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("am", "222", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("am", "1111", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("am", "9999", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("am", "1121", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("am", "1141", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("am", "1161", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("am", "3024", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("at", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("at", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("at", "0901234", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("at", "0900666266", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("au", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("au", "180000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("au", "190000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("au", "1900000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("au", "19000000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("au", "19998882", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("az", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("az", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "12345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "87744", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "3301", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "3302", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "9012", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "9014", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "9394", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "87744", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "93101", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("az", "123456", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("be", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("be", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("be", "567890", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("be", "8000", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("be", "6566", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("be", "7777", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("bg", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("bg", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("bg", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("bg", "12345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("bg", "1816", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("bg", "1915", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("bg", "1916", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("bg", "1935", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("bg", "18423", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("by", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("by", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("by", "3336", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("by", "5013", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("by", "5014", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("by", "7781", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("ca", "911", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ca", "+18005551234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ca", "8005551234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ca", "20000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ca", "200000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ca", "2000000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ca", "60999", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ca", "88188", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("ch", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ch", "123", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ch", "234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ch", "3456", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ch", "98765", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ch", "543", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ch", "83111", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ch", "234567", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ch", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("cn", "120", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("cn", "1062503000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("cn", "1065123456", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("cn", "1066335588", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("cy", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("cy", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("cy", "4321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("cy", "54321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("cy", "654321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("cy", "7510", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("cy", "987654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("cz", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("cz", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("cz", "9090150", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("cz", "90901599", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("cz", "987654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("de", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("de", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("de", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "12345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "8888", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "11111", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "11886", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "22022", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "23300", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "3434", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "34567", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "41414", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "55655", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "66766", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "66777", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "77677", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "80888", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "1232286", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("de", "987654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("dk", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("dk", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("dk", "1259", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("dk", "16123", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("dk", "987654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("ee", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ee", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("ee", "123", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "1259", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "15330", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "17999", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "17010", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "17013", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "9034567", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ee", "34567890", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("es", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("es", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("es", "25165", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("es", "27333", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("es", "995399", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("es", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("fi", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("fi", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("fi", "12345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("fi", "123456", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("fi", "17159", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("fi", "17163", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("fi", "0600123", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("fi", "070012345", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("fi", "987654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("fr", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("fr", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("fr", "34567", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("fr", "45678", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("fr", "81185", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("fr", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("gb", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("gb", "999", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("gb", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("gb", "4567", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("gb", "45678", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("gb", "56789", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("gb", "79067", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("gb", "80079", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("gb", "654321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("gb", "7654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("ge", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ge", "8765", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ge", "2345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ge", "8012", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ge", "8013", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ge", "8014", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ge", "8889", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("gr", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("gr", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("gr", "54321", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("gr", "19567", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("gr", "19678", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("gr", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("hu", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("hu", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("hu", "012", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("hu", "0123", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("hu", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("hu", "1784", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("hu", "2345", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("hu", "01234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("hu", "012345678", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("hu", "0123456789", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("hu", "1234567890", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("hu", "0691227910", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("hu", "2345678901", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("hu", "01234567890", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("ie", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ie", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("ie", "50123", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("ie", "51234", CATEGORY_STANDARD_SHORT_CODE), - new ShortCodeTest("ie", "52345", CATEGORY_STANDARD_SHORT_CODE), - new ShortCodeTest("ie", "57890", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ie", "67890", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ie", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("il", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("il", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("il", "4422", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("il", "4545", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("il", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("it", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("it", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("it", "4567", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("it", "48000", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("it", "45678", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("it", "56789", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("it", "456789", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("kg", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("kg", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("kg", "4152", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("kg", "4157", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("kg", "4449", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("kg", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("kz", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("kz", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("kz", "9194", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("kz", "7790", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("kz", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("lt", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("lt", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("lt", "123", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("lt", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("lt", "1381", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lt", "1394", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lt", "1645", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lt", "12345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("lt", "123456", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("lu", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("lu", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("lu", "1234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("lu", "12345", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("lu", "64747", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lu", "678901", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("lv", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("lv", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("lv", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("lv", "1819", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lv", "1863", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lv", "1874", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("lv", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("mx", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("mx", "2345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("mx", "7766", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("mx", "23456", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("mx", "53035", CATEGORY_PREMIUM_SHORT_CODE), - - new ShortCodeTest("my", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("my", "1234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("my", "23456", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("my", "32298", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("my", "33776", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("my", "345678", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("nl", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("nl", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("nl", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("nl", "4466", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("nl", "5040", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("nl", "23456", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("no", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("no", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("no", "2201", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("no", "2226", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("no", "2227", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("no", "23456", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("no", "234567", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("nz", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("nz", "123", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("nz", "2345", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("nz", "3903", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("nz", "8995", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("nz", "23456", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("pl", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("pl", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("pl", "7890", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("pl", "34567", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("pl", "7910", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pl", "74240", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pl", "79866", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pl", "92525", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pl", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("pt", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("pt", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("pt", "61000", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pt", "62345", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pt", "68304", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pt", "69876", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("pt", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("ro", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ro", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("ro", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ro", "1263", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ro", "1288", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ro", "1314", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ro", "1380", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ro", "7890", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ro", "12345", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("ru", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ru", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ru", "1161", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ru", "2097", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ru", "3933", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ru", "7781", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ru", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("se", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("se", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("se", "1234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("se", "72345", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("se", "72999", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("se", "123456", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("se", "87654321", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("sg", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("sg", "1234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("sg", "70000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("sg", "79999", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("sg", "73800", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("sg", "74688", CATEGORY_STANDARD_SHORT_CODE), - new ShortCodeTest("sg", "987654", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("si", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("si", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("si", "1234", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("si", "3838", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("si", "72999", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("sk", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("sk", "116117", CATEGORY_FREE_SHORT_CODE), - new ShortCodeTest("sk", "1234", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("sk", "6674", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("sk", "7604", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("sk", "72999", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("tj", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("tj", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("tj", "1161", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("tj", "1171", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("tj", "4161", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("tj", "4449", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("tj", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("ua", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("ua", "5432", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("ua", "4448", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ua", "7094", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ua", "7540", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("ua", "98765", CATEGORY_NOT_SHORT_CODE), - - new ShortCodeTest("us", "911", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("us", "+18005551234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("us", "8005551234", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("us", "20000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("us", "200000", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("us", "2000000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("us", "20433", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("us", "21472", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("us", "23333", CATEGORY_PREMIUM_SHORT_CODE), - new ShortCodeTest("us", "99807", CATEGORY_PREMIUM_SHORT_CODE), - - // generic rules for other countries: 5 digits or less considered potential short code - new ShortCodeTest("zz", "2000000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest("zz", "54321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("zz", "4321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("zz", "321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest("zz", "112", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest(null, "2000000", CATEGORY_NOT_SHORT_CODE), - new ShortCodeTest(null, "54321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest(null, "4321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest(null, "321", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE), - new ShortCodeTest(null, "112", CATEGORY_NOT_SHORT_CODE), - }; - - @SmallTest - public void testSmsUsageMonitor() { - SmsUsageMonitor monitor = new SmsUsageMonitor(getContext()); - for (ShortCodeTest test : sShortCodeTests) { - assertEquals("country: " + test.countryIso + " number: " + test.address, - test.category, monitor.checkDestination(test.address, test.countryIso)); - } - } -} diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index c5fdffbda5ba..e7247a300411 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -42,6 +42,15 @@ </activity> <activity + android:name="BigGradientActivity" + android:label="_BigGradient"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="DatePickerActivity" android:label="_DatePicker"> <intent-filter> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java new file mode 100644 index 000000000000..4d28f5125ff2 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 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.content.Context; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Shader; +import android.os.Bundle; +import android.view.View; + +public class BigGradientActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(new BigGradientView(this)); + } + + private class BigGradientView extends View { + public BigGradientView(Context context) { + super(context); + } + + @Override + protected void onDraw(Canvas canvas) { + Paint p = new Paint(); + p.setShader(new LinearGradient(0.0f, 0.0f, 0.0f, getHeight(), 0xff000000, + 0xff333333, Shader.TileMode.CLAMP)); + + canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), p); + } + } +} diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml index 08a010ddc995..bd56d62d29d2 100644 --- a/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml +++ b/tests/RenderScriptTests/ImageProcessing/res/layout/main.xml @@ -50,8 +50,12 @@ android:textSize="8pt" android:text="@string/saturation"/> </LinearLayout> + <Spinner + android:id="@+id/filterselection" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> <TextView - android:id="@+id/inSaturationText" + android:id="@+id/slider1Text" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="8pt" @@ -59,13 +63,13 @@ android:layout_marginTop="15sp" android:text="@string/saturation"/> <SeekBar - android:id="@+id/inSaturation" + android:id="@+id/slider1" android:layout_marginLeft="10sp" android:layout_marginRight="10sp" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView - android:id="@+id/inGammaText" + android:id="@+id/slider2Text" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="8pt" @@ -73,13 +77,13 @@ android:layout_marginTop="15sp" android:text="@string/gamma"/> <SeekBar - android:id="@+id/inGamma" + android:id="@+id/slider2" android:layout_marginLeft="10sp" android:layout_marginRight="10sp" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView - android:id="@+id/outWhiteText" + android:id="@+id/slider3Text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10sp" @@ -87,13 +91,13 @@ android:textSize="8pt" android:text="@string/out_white"/> <SeekBar - android:id="@+id/outWhite" + android:id="@+id/slider3" android:layout_marginLeft="10sp" android:layout_marginRight="10sp" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView - android:id="@+id/inWhiteText" + android:id="@+id/slider4Text" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="8pt" @@ -101,49 +105,21 @@ android:layout_marginTop="15sp" android:text="@string/in_white"/> <SeekBar - android:id="@+id/inWhite" - android:layout_marginLeft="10sp" - android:layout_marginRight="10sp" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - <TextView - android:id="@+id/outBlackText" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textSize="8pt" - android:layout_marginLeft="10sp" - android:layout_marginTop="15sp" - android:text="@string/out_black"/> - <SeekBar - android:id="@+id/outBlack" + android:id="@+id/slider4" android:layout_marginLeft="10sp" android:layout_marginRight="10sp" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView - android:id="@+id/inBlackText" + android:id="@+id/slider5Text" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="8pt" android:layout_marginLeft="10sp" android:layout_marginTop="15sp" - android:text="@string/in_black"/> - <SeekBar - android:id="@+id/inBlack" - android:layout_marginLeft="10sp" - android:layout_marginRight="10sp" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - <TextView - android:id="@+id/blurText" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textSize="8pt" - android:layout_marginLeft="10sp" - android:layout_marginTop="15sp" - android:text="@string/blur_description"/> + android:text="@string/in_white"/> <SeekBar - android:id="@+id/radius" + android:id="@+id/slider5" android:layout_marginLeft="10sp" android:layout_marginRight="10sp" android:layout_width="match_parent" diff --git a/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml b/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml new file mode 100644 index 000000000000..8196bbf02499 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/res/layout/spinner_layout.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Copyright (C) 2012 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. +--> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="10dp" + android:textSize="16sp" +/> diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java new file mode 100644 index 000000000000..697bbb1f9120 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 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.rs.image; + +import java.lang.Math; + +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.Script; +import android.renderscript.ScriptC; +import android.renderscript.Type; +import android.util.Log; +import android.widget.SeekBar; +import android.widget.TextView; + +public class Blur25 extends TestBase { + private int MAX_RADIUS = 25; + private ScriptC_threshold mScript; + private ScriptC_vertical_blur mScriptVBlur; + private ScriptC_horizontal_blur mScriptHBlur; + private int mRadius = MAX_RADIUS; + private float mSaturation = 1.0f; + private Allocation mScratchPixelsAllocation1; + private Allocation mScratchPixelsAllocation2; + + + public boolean onBar1Setup(SeekBar b, TextView t) { + t.setText("Radius"); + b.setProgress(100); + return true; + } + public boolean onBar2Setup(SeekBar b, TextView t) { + b.setProgress(50); + t.setText("Saturation"); + return true; + } + + + public void onBar1Changed(int progress) { + float fRadius = progress / 100.0f; + fRadius *= (float)(MAX_RADIUS); + mRadius = (int)fRadius; + mScript.set_radius(mRadius); + } + public void onBar2Changed(int progress) { + mSaturation = (float)progress / 50.0f; + mScriptVBlur.invoke_setSaturation(mSaturation); + } + + + public void createTest(android.content.res.Resources res) { + int width = mInPixelsAllocation.getType().getX(); + int height = mInPixelsAllocation.getType().getY(); + + Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS)); + tb.setX(width); + tb.setY(height); + mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create()); + mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create()); + + mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur); + mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur); + + mScript = new ScriptC_threshold(mRS, res, R.raw.threshold); + mScript.set_width(width); + mScript.set_height(height); + mScript.set_radius(mRadius); + + mScriptVBlur.invoke_setSaturation(mSaturation); + + mScript.bind_InPixel(mInPixelsAllocation); + mScript.bind_OutPixel(mOutPixelsAllocation); + mScript.bind_ScratchPixel1(mScratchPixelsAllocation1); + mScript.bind_ScratchPixel2(mScratchPixelsAllocation2); + + mScript.set_vBlurScript(mScriptVBlur); + mScript.set_hBlurScript(mScriptHBlur); + } + + public void runTest() { + mScript.invoke_filter(); + } + + public void setupBenchmark() { + mScript.set_radius(MAX_RADIUS); + } + + public void exitBenchmark() { + mScript.set_radius(mRadius); + } +} diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java new file mode 100644 index 000000000000..cd54c2eb5bc1 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Grain.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 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.rs.image; + +import java.lang.Math; + +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.Script; +import android.renderscript.ScriptC; +import android.renderscript.Type; +import android.util.Log; +import android.widget.SeekBar; +import android.widget.TextView; + +public class Grain extends TestBase { + private ScriptC_grain mScript; + private Allocation mNoise; + private Allocation mNoise2; + + + public boolean onBar1Setup(SeekBar b, TextView t) { + t.setText("Strength"); + b.setProgress(50); + return true; + } + + public void onBar1Changed(int progress) { + float s = progress / 100.0f; + mScript.set_gNoiseStrength(s); + } + + public void createTest(android.content.res.Resources res) { + int width = mInPixelsAllocation.getType().getX(); + int height = mInPixelsAllocation.getType().getY(); + + Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS)); + tb.setX(width); + tb.setY(height); + mNoise = Allocation.createTyped(mRS, tb.create()); + mNoise2 = Allocation.createTyped(mRS, tb.create()); + + mScript = new ScriptC_grain(mRS, res, R.raw.grain); + mScript.set_gWidth(width); + mScript.set_gHeight(height); + mScript.set_gNoiseStrength(0.5f); + mScript.set_gBlendSource(mNoise); + mScript.set_gNoise(mNoise2); + } + + public void runTest() { + mScript.forEach_genRand(mNoise); + mScript.forEach_blend9(mNoise2); + mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation); + } + +} + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java new file mode 100644 index 000000000000..3db210a39a2a --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Greyscale.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 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.rs.image; + +import java.lang.Math; + +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.Script; +import android.renderscript.ScriptC; +import android.renderscript.Type; +import android.util.Log; + +public class Greyscale extends TestBase { + private ScriptC_greyscale mScript; + + public void createTest(android.content.res.Resources res) { + mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale); + } + + public void runTest() { + mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation); + } + +} diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java index 73682600ec10..3a9838bf790a 100644 --- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2012 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. @@ -29,133 +29,155 @@ import android.renderscript.Element; import android.renderscript.Script; import android.view.SurfaceView; import android.view.SurfaceHolder; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.SeekBar; +import android.widget.Spinner; import android.widget.TextView; import android.view.View; import android.util.Log; import java.lang.Math; public class ImageProcessingActivity extends Activity - implements SurfaceHolder.Callback, - SeekBar.OnSeekBarChangeListener { + implements SeekBar.OnSeekBarChangeListener { private final String TAG = "Img"; - private Bitmap mBitmapIn; - private Bitmap mBitmapOut; - private ScriptC_threshold mScript; - private ScriptC_vertical_blur mScriptVBlur; - private ScriptC_horizontal_blur mScriptHBlur; - private int mRadius = 0; - private SeekBar mRadiusSeekBar; - - private float mInBlack = 0.0f; - private SeekBar mInBlackSeekBar; - private float mOutBlack = 0.0f; - private SeekBar mOutBlackSeekBar; - private float mInWhite = 255.0f; - private SeekBar mInWhiteSeekBar; - private float mOutWhite = 255.0f; - private SeekBar mOutWhiteSeekBar; - private float mGamma = 1.0f; - private SeekBar mGammaSeekBar; + Bitmap mBitmapIn; + Bitmap mBitmapOut; + String mTestNames[]; + + private SeekBar mBar1; + private SeekBar mBar2; + private SeekBar mBar3; + private SeekBar mBar4; + private SeekBar mBar5; + private TextView mText1; + private TextView mText2; + private TextView mText3; + private TextView mText4; + private TextView mText5; private float mSaturation = 1.0f; - private SeekBar mSaturationSeekBar; private TextView mBenchmarkResult; - - @SuppressWarnings({"FieldCanBeLocal"}) - private RenderScript mRS; - @SuppressWarnings({"FieldCanBeLocal"}) - private Type mPixelType; - @SuppressWarnings({"FieldCanBeLocal"}) - private Allocation mInPixelsAllocation; - @SuppressWarnings({"FieldCanBeLocal"}) - private Allocation mOutPixelsAllocation; - @SuppressWarnings({"FieldCanBeLocal"}) - private Allocation mScratchPixelsAllocation1; - private Allocation mScratchPixelsAllocation2; + private Spinner mTestSpinner; private SurfaceView mSurfaceView; private ImageView mDisplayView; - private boolean mIsProcessing; + private boolean mDoingBenchmark; - class FilterCallback extends RenderScript.RSMessageHandler { - private Runnable mAction = new Runnable() { - public void run() { + private TestBase mTest; - synchronized (mDisplayView) { - mIsProcessing = false; - } - mOutPixelsAllocation.copyTo(mBitmapOut); - mDisplayView.invalidate(); + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + + if (seekBar == mBar1) { + mTest.onBar1Changed(progress); + } else if (seekBar == mBar2) { + mTest.onBar2Changed(progress); + } else if (seekBar == mBar3) { + mTest.onBar3Changed(progress); + } else if (seekBar == mBar4) { + mTest.onBar4Changed(progress); + } else if (seekBar == mBar5) { + mTest.onBar5Changed(progress); } - }; - @Override - public void run() { - mSurfaceView.removeCallbacks(mAction); - mSurfaceView.post(mAction); + mTest.runTest(); + mTest.updateBitmap(mBitmapOut); + mDisplayView.invalidate(); } } - int in[]; - int interm[]; - int out[]; - int MAX_RADIUS = 25; - // Store our coefficients here - float gaussian[]; + public void onStartTrackingTouch(SeekBar seekBar) { + } - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { + public void onStopTrackingTouch(SeekBar seekBar) { + } - if (seekBar == mRadiusSeekBar) { - float fRadius = progress / 100.0f; - fRadius *= (float)(MAX_RADIUS); - mRadius = (int)fRadius; - - mScript.set_radius(mRadius); - } else if (seekBar == mInBlackSeekBar) { - mInBlack = (float)progress; - mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); - } else if (seekBar == mOutBlackSeekBar) { - mOutBlack = (float)progress; - mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); - } else if (seekBar == mInWhiteSeekBar) { - mInWhite = (float)progress + 127.0f; - mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); - } else if (seekBar == mOutWhiteSeekBar) { - mOutWhite = (float)progress + 127.0f; - mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); - } else if (seekBar == mGammaSeekBar) { - mGamma = (float)progress/100.0f; - mGamma = Math.max(mGamma, 0.1f); - mGamma = 1.0f / mGamma; - mScriptVBlur.invoke_setGamma(mGamma); - } else if (seekBar == mSaturationSeekBar) { - mSaturation = (float)progress / 50.0f; - mScriptVBlur.invoke_setSaturation(mSaturation); - } + void setupBars() { + mBar1.setVisibility(View.VISIBLE); + mText1.setVisibility(View.VISIBLE); + mTest.onBar1Setup(mBar1, mText1); - synchronized (mDisplayView) { - if (mIsProcessing) { - return; - } - mIsProcessing = true; - } + mBar2.setVisibility(View.VISIBLE); + mText2.setVisibility(View.VISIBLE); + mTest.onBar2Setup(mBar2, mText2); - mScript.invoke_filter(); - } + mBar3.setVisibility(View.VISIBLE); + mText3.setVisibility(View.VISIBLE); + mTest.onBar3Setup(mBar3, mText3); + + mBar4.setVisibility(View.VISIBLE); + mText4.setVisibility(View.VISIBLE); + mTest.onBar4Setup(mBar4, mText4); + + mBar5.setVisibility(View.VISIBLE); + mText5.setVisibility(View.VISIBLE); + mTest.onBar5Setup(mBar5, mText5); } - public void onStartTrackingTouch(SeekBar seekBar) { + + void changeTest(int testID) { + switch(testID) { + case 0: + mTest = new LevelsV4(false, false); + break; + case 1: + mTest = new LevelsV4(false, true); + break; + case 2: + mTest = new LevelsV4(true, false); + break; + case 3: + mTest = new LevelsV4(true, true); + break; + case 4: + mTest = new Blur25(); + break; + case 5: + mTest = new Greyscale(); + break; + case 6: + mTest = new Grain(); + break; + } + + mTest.createBaseTest(this, mBitmapIn); + setupBars(); + + mTest.runTest(); + mTest.updateBitmap(mBitmapOut); + mDisplayView.invalidate(); + mBenchmarkResult.setText("Result: not run"); } - public void onStopTrackingTouch(SeekBar seekBar) { + void setupTests() { + mTestNames = new String[7]; + mTestNames[0] = "Levels Vec3 Relaxed"; + mTestNames[1] = "Levels Vec4 Relaxed"; + mTestNames[2] = "Levels Vec3 Full"; + mTestNames[3] = "Levels Vec4 Full"; + mTestNames[4] = "Blur radius 25"; + mTestNames[5] = "Greyscale"; + mTestNames[6] = "Grain"; + mTestSpinner.setAdapter(new ArrayAdapter<String>( + this, R.layout.spinner_layout, mTestNames)); } + private AdapterView.OnItemSelectedListener mTestSpinnerListener = + new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { + changeTest(pos); + } + + public void onNothingSelected(AdapterView parent) { + + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -165,95 +187,39 @@ public class ImageProcessingActivity extends Activity mBitmapOut = loadBitmap(R.drawable.city); mSurfaceView = (SurfaceView) findViewById(R.id.surface); - mSurfaceView.getHolder().addCallback(this); mDisplayView = (ImageView) findViewById(R.id.display); mDisplayView.setImageBitmap(mBitmapOut); - mRadiusSeekBar = (SeekBar) findViewById(R.id.radius); - mRadiusSeekBar.setOnSeekBarChangeListener(this); - - mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack); - mInBlackSeekBar.setOnSeekBarChangeListener(this); - mInBlackSeekBar.setMax(128); - mInBlackSeekBar.setProgress(0); - mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack); - mOutBlackSeekBar.setOnSeekBarChangeListener(this); - mOutBlackSeekBar.setMax(128); - mOutBlackSeekBar.setProgress(0); - - mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite); - mInWhiteSeekBar.setOnSeekBarChangeListener(this); - mInWhiteSeekBar.setMax(128); - mInWhiteSeekBar.setProgress(128); - mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite); - mOutWhiteSeekBar.setOnSeekBarChangeListener(this); - mOutWhiteSeekBar.setMax(128); - mOutWhiteSeekBar.setProgress(128); - - mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma); - mGammaSeekBar.setOnSeekBarChangeListener(this); - mGammaSeekBar.setMax(150); - mGammaSeekBar.setProgress(100); - - mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation); - mSaturationSeekBar.setOnSeekBarChangeListener(this); - mSaturationSeekBar.setProgress(50); + mBar1 = (SeekBar) findViewById(R.id.slider1); + mBar2 = (SeekBar) findViewById(R.id.slider2); + mBar3 = (SeekBar) findViewById(R.id.slider3); + mBar4 = (SeekBar) findViewById(R.id.slider4); + mBar5 = (SeekBar) findViewById(R.id.slider5); - mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText); - mBenchmarkResult.setText("Result: not run"); - } + mBar1.setOnSeekBarChangeListener(this); + mBar2.setOnSeekBarChangeListener(this); + mBar3.setOnSeekBarChangeListener(this); + mBar4.setOnSeekBarChangeListener(this); + mBar5.setOnSeekBarChangeListener(this); - public void surfaceCreated(SurfaceHolder holder) { - createScript(); - mScript.invoke_filter(); - mOutPixelsAllocation.copyTo(mBitmapOut); - } + mText1 = (TextView) findViewById(R.id.slider1Text); + mText2 = (TextView) findViewById(R.id.slider2Text); + mText3 = (TextView) findViewById(R.id.slider3Text); + mText4 = (TextView) findViewById(R.id.slider4Text); + mText5 = (TextView) findViewById(R.id.slider5Text); - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - } + mTestSpinner = (Spinner) findViewById(R.id.filterselection); + mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener); - public void surfaceDestroyed(SurfaceHolder holder) { - } + mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText); + mBenchmarkResult.setText("Result: not run"); - private void createScript() { - mRS = RenderScript.create(this); - mRS.setMessageHandler(new FilterCallback()); - - mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn, - Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_SCRIPT); - mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut, - Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_SCRIPT); - - Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS)); - tb.setX(mBitmapIn.getWidth()); - tb.setY(mBitmapIn.getHeight()); - mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create()); - mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create()); - - mScriptVBlur = new ScriptC_vertical_blur(mRS, getResources(), R.raw.vertical_blur); - mScriptHBlur = new ScriptC_horizontal_blur(mRS, getResources(), R.raw.horizontal_blur); - - mScript = new ScriptC_threshold(mRS, getResources(), R.raw.threshold); - mScript.set_width(mBitmapIn.getWidth()); - mScript.set_height(mBitmapIn.getHeight()); - mScript.set_radius(mRadius); - - mScriptVBlur.invoke_setLevels(mInBlack, mOutBlack, mInWhite, mOutWhite); - mScriptVBlur.invoke_setGamma(mGamma); - mScriptVBlur.invoke_setSaturation(mSaturation); - - mScript.bind_InPixel(mInPixelsAllocation); - mScript.bind_OutPixel(mOutPixelsAllocation); - mScript.bind_ScratchPixel1(mScratchPixelsAllocation1); - mScript.bind_ScratchPixel2(mScratchPixelsAllocation2); - - mScript.set_vBlurScript(mScriptVBlur); - mScript.set_hBlurScript(mScriptHBlur); + setupTests(); + changeTest(0); } + private Bitmap loadBitmap(int resource) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; @@ -278,26 +244,29 @@ public class ImageProcessingActivity extends Activity // For benchmark test public long getBenchmark() { - Log.v(TAG, "Benchmarking"); - int oldRadius = mRadius; - mRadius = MAX_RADIUS; - mScript.set_radius(mRadius); + mDoingBenchmark = true; - mScript.invoke_filter(); - mRS.finish(); + mTest.setupBenchmark(); + long result = 0; - long t = java.lang.System.currentTimeMillis(); + Log.v(TAG, "Warming"); + long t = java.lang.System.currentTimeMillis() + 2000; + do { + mTest.runTest(); + mTest.finish(); + } while (t > java.lang.System.currentTimeMillis()); - mScript.invoke_filter(); - mOutPixelsAllocation.copyTo(mBitmapOut); + Log.v(TAG, "Benchmarking"); + t = java.lang.System.currentTimeMillis(); + mTest.runTest(); + mTest.finish(); t = java.lang.System.currentTimeMillis() - t; + Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t); - mRadius = oldRadius; - mScript.set_radius(mRadius); + mTest.exitBenchmark(); + mDoingBenchmark = false; - mScript.invoke_filter(); - mOutPixelsAllocation.copyTo(mBitmapOut); return t; } } diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java new file mode 100644 index 000000000000..9eb5647e4284 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/LevelsV4.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2012 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.rs.image; + +import java.lang.Math; + +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.Matrix3f; +import android.renderscript.Script; +import android.renderscript.ScriptC; +import android.renderscript.Type; +import android.util.Log; +import android.widget.SeekBar; +import android.widget.TextView; + + +public class LevelsV4 extends TestBase { + private ScriptC_levels_relaxed mScriptR; + private ScriptC_levels_full mScriptF; + private float mInBlack = 0.0f; + private float mOutBlack = 0.0f; + private float mInWhite = 255.0f; + private float mOutWhite = 255.0f; + private float mSaturation = 1.0f; + + Matrix3f satMatrix = new Matrix3f(); + float mInWMinInB; + float mOutWMinOutB; + float mOverInWMinInB; + + boolean mUseFull; + boolean mUseV4; + + LevelsV4(boolean useFull, boolean useV4) { + mUseFull = useFull; + mUseV4 = useV4; + } + + + private void setLevels() { + mInWMinInB = mInWhite - mInBlack; + mOutWMinOutB = mOutWhite - mOutBlack; + mOverInWMinInB = 1.f / mInWMinInB; + + mScriptR.set_inBlack(mInBlack); + mScriptR.set_outBlack(mOutBlack); + mScriptR.set_inWMinInB(mInWMinInB); + mScriptR.set_outWMinOutB(mOutWMinOutB); + mScriptR.set_overInWMinInB(mOverInWMinInB); + mScriptF.set_inBlack(mInBlack); + mScriptF.set_outBlack(mOutBlack); + mScriptF.set_inWMinInB(mInWMinInB); + mScriptF.set_outWMinOutB(mOutWMinOutB); + mScriptF.set_overInWMinInB(mOverInWMinInB); + } + + private void setSaturation() { + float rWeight = 0.299f; + float gWeight = 0.587f; + float bWeight = 0.114f; + float oneMinusS = 1.0f - mSaturation; + + satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation); + satMatrix.set(0, 1, oneMinusS * rWeight); + satMatrix.set(0, 2, oneMinusS * rWeight); + satMatrix.set(1, 0, oneMinusS * gWeight); + satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation); + satMatrix.set(1, 2, oneMinusS * gWeight); + satMatrix.set(2, 0, oneMinusS * bWeight); + satMatrix.set(2, 1, oneMinusS * bWeight); + satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation); + mScriptR.set_colorMat(satMatrix); + mScriptF.set_colorMat(satMatrix); + } + + public boolean onBar1Setup(SeekBar b, TextView t) { + b.setProgress(50); + t.setText("Saturation"); + return true; + } + public boolean onBar2Setup(SeekBar b, TextView t) { + b.setMax(128); + b.setProgress(0); + t.setText("In Black"); + return true; + } + public boolean onBar3Setup(SeekBar b, TextView t) { + b.setMax(128); + b.setProgress(0); + t.setText("Out Black"); + return true; + } + public boolean onBar4Setup(SeekBar b, TextView t) { + b.setMax(128); + b.setProgress(128); + t.setText("Out White"); + return true; + } + public boolean onBar5Setup(SeekBar b, TextView t) { + b.setMax(128); + b.setProgress(128); + t.setText("Out White"); + return true; + } + + public void onBar1Changed(int progress) { + mSaturation = (float)progress / 50.0f; + setSaturation(); + } + public void onBar2Changed(int progress) { + mInBlack = (float)progress; + setLevels(); + } + public void onBar3Changed(int progress) { + mOutBlack = (float)progress; + setLevels(); + } + public void onBar4Changed(int progress) { + mInWhite = (float)progress + 127.0f; + setLevels(); + } + public void onBar5Changed(int progress) { + mOutWhite = (float)progress + 127.0f; + setLevels(); + } + + public void createTest(android.content.res.Resources res) { + mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed); + mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full); + setSaturation(); + setLevels(); + } + + public void runTest() { + if (mUseFull) { + if (mUseV4) { + mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation); + } else { + mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation); + } + } else { + if (mUseV4) { + mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation); + } else { + mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation); + } + } + } + +} + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java new file mode 100644 index 000000000000..3a6241d9d9a5 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2012 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.rs.image; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.graphics.BitmapFactory; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.renderscript.ScriptC; +import android.renderscript.RenderScript; +import android.renderscript.Type; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.Script; +import android.view.SurfaceView; +import android.view.SurfaceHolder; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.TextView; +import android.view.View; +import android.util.Log; +import java.lang.Math; + +public class TestBase { + protected final String TAG = "Img"; + + protected RenderScript mRS; + protected Allocation mInPixelsAllocation; + protected Allocation mOutPixelsAllocation; + + // Override to use UI elements + public void onBar1Changed(int progress) { + } + public void onBar2Changed(int progress) { + } + public void onBar3Changed(int progress) { + } + public void onBar4Changed(int progress) { + } + public void onBar5Changed(int progress) { + } + + // Override to use UI elements + // Unused bars will be hidden. + public boolean onBar1Setup(SeekBar b, TextView t) { + b.setVisibility(View.INVISIBLE); + t.setVisibility(View.INVISIBLE); + return false; + } + public boolean onBar2Setup(SeekBar b, TextView t) { + b.setVisibility(View.INVISIBLE); + t.setVisibility(View.INVISIBLE); + return false; + } + public boolean onBar3Setup(SeekBar b, TextView t) { + b.setVisibility(View.INVISIBLE); + t.setVisibility(View.INVISIBLE); + return false; + } + public boolean onBar4Setup(SeekBar b, TextView t) { + b.setVisibility(View.INVISIBLE); + t.setVisibility(View.INVISIBLE); + return false; + } + public boolean onBar5Setup(SeekBar b, TextView t) { + b.setVisibility(View.INVISIBLE); + t.setVisibility(View.INVISIBLE); + return false; + } + + public final void createBaseTest(ImageProcessingActivity act, Bitmap b) { + mRS = RenderScript.create(act); + mInPixelsAllocation = Allocation.createFromBitmap(mRS, b, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b, + Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + createTest(act.getResources()); + } + + // Must override + public void createTest(android.content.res.Resources res) { + android.util.Log.e("img", "implement createTest"); + } + + // Must override + public void runTest() { + } + + public void finish() { + mRS.finish(); + } + + public void updateBitmap(Bitmap b) { + mOutPixelsAllocation.copyTo(b); + } + + // Override to configure specific benchmark config. + public void setupBenchmark() { + } + + // Override to reset after benchmark. + public void exitBenchmark() { + } +} diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs new file mode 100644 index 000000000000..97ae4fb3a38d --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012 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. + */ + +#pragma version(1) +#pragma rs java_package_name(com.android.rs.image) +#pragma rs_fp_relaxed + +void genRand(uchar *out) { + *out = (uchar)rsRand(0xff); +} + +/* + * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits + * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of + * small values are not calculated to gain efficiency. + * The order ot pixels represented in this matrix is: + * 1 2 3 + * 4 0 5 + * 6 7 8 + * and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}. + * However, since most of the valus are identical, we only use the first three + * entries and the entries corresponding to the pixels is: + * 1 2 1 + * 2 0 2 + * 1 2 1 + */ + +int32_t gWidth; +int32_t gHeight; + +rs_allocation gBlendSource; +void blend9(uchar *out, uint32_t x, uint32_t y) { + uint32_t x1 = min(x+1, (uint32_t)gWidth); + uint32_t x2 = max(x-1, (uint32_t)0); + uint32_t y1 = min(y+1, (uint32_t)gHeight); + uint32_t y2 = max(y-1, (uint32_t)0); + + uint p00 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0]; + uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0]; + uint p02 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0]; + uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0]; + uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0]; + uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0]; + uint p20 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0]; + uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0]; + uint p22 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0]; + + p00 += p01; + p02 += p10; + p11 += p12; + p20 += p21; + + p22 += p00; + p02 += p11; + + p20 += p22; + p20 += p02; + + *out = (uchar)(p20 >> 10); +} + +float gNoiseStrength; + +rs_allocation gNoise; +void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) { + float4 ip = convert_float4(*in); + float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0]; + + float energy_level = ip.r + ip.g + ip.b; + float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f; + pnoise = (pnoise - 128.f) * energy_mask; + + ip += pnoise * gNoiseStrength; + ip = clamp(ip, 0.f, 255.f); + + uchar4 p = convert_uchar4(ip); + p.a = 0xff; + *out = p; +} diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs new file mode 100644 index 000000000000..c420cac5d910 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.rs @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 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. + */ + +#pragma version(1) +#pragma rs java_package_name(com.android.rs.image) +#pragma rs_fp_relaxed + +const static float3 gMonoMult = {0.299f, 0.587f, 0.114f}; + +void root(const uchar4 *v_in, uchar4 *v_out) { + float4 f4 = rsUnpackColor8888(*v_in); + + float3 mono = dot(f4.rgb, gMonoMult); + *v_out = rsPackColorTo8888(mono); +} + + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh new file mode 100644 index 000000000000..7c5d930f111c --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels.rsh @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 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. + */ + +float inBlack; +float outBlack; +float inWMinInB; +float outWMinOutB; +float overInWMinInB; +rs_matrix3x3 colorMat; + +void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) { + float3 pixel = convert_float4(in[0]).rgb; + pixel = rsMatrixMultiply(&colorMat, pixel); + pixel = clamp(pixel, 0.f, 255.f); + pixel = (pixel - inBlack) * overInWMinInB; + pixel = pixel * outWMinOutB + outBlack; + pixel = clamp(pixel, 0.f, 255.f); + out->xyz = convert_uchar3(pixel); + out->w = 0xff; +} + +void root4(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) { + float4 pixel = convert_float4(in[0]); + pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb); + pixel = clamp(pixel, 0.f, 255.f); + pixel = (pixel - inBlack) * overInWMinInB; + pixel = pixel * outWMinOutB + outBlack; + pixel = clamp(pixel, 0.f, 255.f); + out->xyzw = convert_uchar4(pixel); +} + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs new file mode 100644 index 000000000000..da6a29134b05 --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2012 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. + */ + +#pragma version(1) +#pragma rs java_package_name(com.android.rs.image) + +#include "levels.rsh" + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs new file mode 100644 index 000000000000..b1154455a26e --- /dev/null +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.rs @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012 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. + */ + +#pragma version(1) +#pragma rs java_package_name(com.android.rs.image) +#pragma rs_fp_relaxed + +#include "levels.rsh" + diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs index d93238c2580c..77cd5be582a0 100644 --- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs @@ -88,6 +88,6 @@ void filter() { fs.ain = rsGetAllocation(ScratchPixel2); rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs)); - rsSendToClientBlocking(CMD_FINISHED); + //rsSendToClientBlocking(CMD_FINISHED); } diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs index a6da192f4059..60fd71bf6fd4 100644 --- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vertical_blur.rs @@ -3,29 +3,9 @@ #include "ip.rsh" -static float inBlack; -static float outBlack; -static float inWhite; -static float outWhite; -static float3 gamma; static float saturation; - -static float inWMinInB; -static float outWMinOutB; -static float overInWMinInB; static rs_matrix3x3 colorMat; -void setLevels(float iBlk, float oBlk, float iWht, float oWht) { - inBlack = iBlk; - outBlack = oBlk; - inWhite = iWht; - outWhite = oWht; - - inWMinInB = inWhite - inBlack; - outWMinOutB = outWhite - outBlack; - overInWMinInB = 1.f / inWMinInB; -} - void setSaturation(float sat) { saturation = sat; @@ -52,10 +32,6 @@ void setSaturation(float sat) { rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation); } -void setGamma(float g) { - gamma = (float3)g; -} - void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) { const FilterStruct *fs = (const FilterStruct *)usrData; float3 blurredPixel = 0; @@ -76,12 +52,8 @@ void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) { } float3 temp = rsMatrixMultiply(&colorMat, blurredPixel); - temp = (clamp(temp, 0.f, 255.f) - inBlack) * overInWMinInB; - if (gamma.x != 1.0f) - temp = pow(temp, (float3)gamma); - temp = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f); - + temp = clamp(temp, 0.f, 255.f); out->xyz = convert_uchar3(temp); - //output->w = input->w; + out->w = 0xff; } diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java index 32a4bd7f9010..9d94ba58d7ee 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java @@ -19,19 +19,267 @@ package com.android.rs.test; import android.content.Context; import android.content.res.Resources; import android.renderscript.*; +import android.util.Log; +import java.util.Arrays; import java.util.Random; public class UT_math_agree extends UnitTest { private Resources mRes; + private Random rand; protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) { super(rstc, "Math Agreement", ctx); mRes = res; + rand = new Random(); } - private void initializeValues(ScriptC_math_agree s) { - Random rand = new Random(); + // packing functions + private Float2 pack_f2(float[] val) { + assert val.length == 2; + return new Float2(val[0], val[1]); + } + private Float3 pack_f3(float[] val) { + assert val.length == 3; + return new Float3(val[0], val[1], val[2]); + } + private Float4 pack_f4(float[] val) { + assert val.length == 4; + return new Float4(val[0], val[1], val[2], val[3]); + } + private Byte2 pack_b2(byte[] val) { + assert val.length == 2; + return new Byte2(val[0], val[1]); + } + private Byte3 pack_b3(byte[] val) { + assert val.length == 3; + return new Byte3(val[0], val[1], val[2]); + } + private Byte4 pack_b4(byte[] val) { + assert val.length == 4; + return new Byte4(val[0], val[1], val[2], val[3]); + } + private Short2 pack_s2(short[] val) { + assert val.length == 2; + return new Short2(val[0], val[1]); + } + private Short3 pack_s3(short[] val) { + assert val.length == 3; + return new Short3(val[0], val[1], val[2]); + } + private Short4 pack_s4(short[] val) { + assert val.length == 4; + return new Short4(val[0], val[1], val[2], val[3]); + } + private Int2 pack_i2(int[] val) { + assert val.length == 2; + return new Int2(val[0], val[1]); + } + private Int3 pack_i3(int[] val) { + assert val.length == 3; + return new Int3(val[0], val[1], val[2]); + } + private Int4 pack_i4(int[] val) { + assert val.length == 4; + return new Int4(val[0], val[1], val[2], val[3]); + } + private Long2 pack_l2(long[] val) { + assert val.length == 2; + return new Long2(val[0], val[1]); + } + private Long3 pack_l3(long[] val) { + assert val.length == 3; + return new Long3(val[0], val[1], val[2]); + } + private Long4 pack_l4(long[] val) { + assert val.length == 4; + return new Long4(val[0], val[1], val[2], val[3]); + } + + // random vector generation functions + private float[] randvec_float(int dim) { + float[] fv = new float[dim]; + for (int i = 0; i < dim; ++i) + fv[i] = rand.nextFloat(); + return fv; + } + private byte[] randvec_char(int dim) { + byte[] cv = new byte[dim]; + rand.nextBytes(cv); + return cv; + } + private short[] randvec_uchar(int dim) { + short[] ucv = new short[dim]; + for (int i = 0; i < dim; ++i) + ucv[i] = (short)rand.nextInt(0x1 << 8); + return ucv; + } + private short[] randvec_short(int dim) { + short[] sv = new short[dim]; + for (int i = 0; i < dim; ++i) + sv[i] = (short)rand.nextInt(0x1 << 16); + return sv; + } + private int[] randvec_ushort(int dim) { + int[] usv = new int[dim]; + for (int i = 0; i < dim; ++i) + usv[i] = rand.nextInt(0x1 << 16); + return usv; + } + private int[] randvec_int(int dim) { + int[] iv = new int[dim]; + for (int i = 0; i < dim; ++i) + iv[i] = rand.nextInt(); + return iv; + } + private long[] randvec_uint(int dim) { + long[] uiv = new long[dim]; + for (int i = 0; i < dim; ++i) + uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE; + return uiv; + } + private long[] randvec_long(int dim) { + long[] lv = new long[dim]; + for (int i = 0; i < dim; ++i) + lv[i] = rand.nextLong(); + return lv; + } + // TODO: unsigned long generator + + // min reference functions + private float min(float v1, float v2) { + return v1 < v2 ? v1 : v2; + } + private float[] min(float[] v1, float[] v2) { + assert v1.length == v2.length; + float[] rv = new float[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = min(v1[i], v2[i]); + return rv; + } + private byte min(byte v1, byte v2) { + return v1 < v2 ? v1 : v2; + } + private byte[] min(byte[] v1, byte[] v2) { + assert v1.length == v2.length; + byte[] rv = new byte[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = min(v1[i], v2[i]); + return rv; + } + private short min(short v1, short v2) { + return v1 < v2 ? v1 : v2; + } + private short[] min(short[] v1, short[] v2) { + assert v1.length == v2.length; + short[] rv = new short[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = min(v1[i], v2[i]); + return rv; + } + private int min(int v1, int v2) { + return v1 < v2 ? v1 : v2; + } + private int[] min(int[] v1, int[] v2) { + assert v1.length == v2.length; + int[] rv = new int[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = min(v1[i], v2[i]); + return rv; + } + private long min(long v1, long v2) { + return v1 < v2 ? v1 : v2; + } + private long[] min(long[] v1, long[] v2) { + assert v1.length == v2.length; + long[] rv = new long[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = min(v1[i], v2[i]); + return rv; + } + // TODO: unsigned long version of min + + // max reference functions + private float max(float v1, float v2) { + return v1 > v2 ? v1 : v2; + } + private float[] max(float[] v1, float[] v2) { + assert v1.length == v2.length; + float[] rv = new float[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = max(v1[i], v2[i]); + return rv; + } + private byte max(byte v1, byte v2) { + return v1 > v2 ? v1 : v2; + } + private byte[] max(byte[] v1, byte[] v2) { + assert v1.length == v2.length; + byte[] rv = new byte[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = max(v1[i], v2[i]); + return rv; + } + private short max(short v1, short v2) { + return v1 > v2 ? v1 : v2; + } + private short[] max(short[] v1, short[] v2) { + assert v1.length == v2.length; + short[] rv = new short[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = max(v1[i], v2[i]); + return rv; + } + private int max(int v1, int v2) { + return v1 > v2 ? v1 : v2; + } + private int[] max(int[] v1, int[] v2) { + assert v1.length == v2.length; + int[] rv = new int[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = max(v1[i], v2[i]); + return rv; + } + private long max(long v1, long v2) { + return v1 > v2 ? v1 : v2; + } + private long[] max(long[] v1, long[] v2) { + assert v1.length == v2.length; + long[] rv = new long[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = max(v1[i], v2[i]); + return rv; + } + // TODO: unsigned long version of max + // fmin reference functions + private float fmin(float v1, float v2) { + return min(v1, v2); + } + private float[] fmin(float[] v1, float[] v2) { + return min(v1, v2); + } + private float[] fmin(float[] v1, float v2) { + float[] rv = new float[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = min(v1[i], v2); + return rv; + } + + // fmax reference functions + private float fmax(float v1, float v2) { + return max(v1, v2); + } + private float[] fmax(float[] v1, float[] v2) { + return max(v1, v2); + } + private float[] fmax(float[] v1, float v2) { + float[] rv = new float[v1.length]; + for (int i = 0; i < v1.length; ++i) + rv[i] = max(v1[i], v2); + return rv; + } + + private void initializeValues(ScriptC_math_agree s) { float x = rand.nextFloat(); float y = rand.nextFloat(); @@ -41,6 +289,249 @@ public class UT_math_agree extends UnitTest { s.set_result_sub(x - y); s.set_result_mul(x * y); s.set_result_div(x / y); + + // Generate random vectors of all types + float rand_f1_0 = rand.nextFloat(); + float[] rand_f2_0 = randvec_float(2); + float[] rand_f3_0 = randvec_float(3); + float[] rand_f4_0 = randvec_float(4); + float rand_f1_1 = rand.nextFloat(); + float[] rand_f2_1 = randvec_float(2); + float[] rand_f3_1 = randvec_float(3); + float[] rand_f4_1 = randvec_float(4); + byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8); + byte[] rand_sc2_0 = randvec_char(2); + byte[] rand_sc3_0 = randvec_char(3); + byte[] rand_sc4_0 = randvec_char(4); + byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8); + byte[] rand_sc2_1 = randvec_char(2); + byte[] rand_sc3_1 = randvec_char(3); + byte[] rand_sc4_1 = randvec_char(4); + short rand_ss1_0 = (short)rand.nextInt(0x1 << 16); + short[] rand_ss2_0 = randvec_short(2); + short[] rand_ss3_0 = randvec_short(3); + short[] rand_ss4_0 = randvec_short(4); + short rand_ss1_1 = (short)rand.nextInt(0x1 << 16); + short[] rand_ss2_1 = randvec_short(2); + short[] rand_ss3_1 = randvec_short(3); + short[] rand_ss4_1 = randvec_short(4); + int rand_si1_0 = rand.nextInt(); + int[] rand_si2_0 = randvec_int(2); + int[] rand_si3_0 = randvec_int(3); + int[] rand_si4_0 = randvec_int(4); + int rand_si1_1 = rand.nextInt(); + int[] rand_si2_1 = randvec_int(2); + int[] rand_si3_1 = randvec_int(3); + int[] rand_si4_1 = randvec_int(4); + long rand_sl1_0 = rand.nextLong(); + long[] rand_sl2_0 = randvec_long(2); + long[] rand_sl3_0 = randvec_long(3); + long[] rand_sl4_0 = randvec_long(4); + long rand_sl1_1 = rand.nextLong(); + long[] rand_sl2_1 = randvec_long(2); + long[] rand_sl3_1 = randvec_long(3); + long[] rand_sl4_1 = randvec_long(4); + // FIXME: generate unsigned input vectors once bug 6764163 is fixed + /* + short rand_uc1_0 = (short)rand.nextInt(0x1 << 8); + short[] rand_uc2_0 = randvec_uchar(2); + short[] rand_uc3_0 = randvec_uchar(3); + short[] rand_uc4_0 = randvec_uchar(4); + short rand_uc1_1 = (short)rand.nextInt(0x1 << 8); + short[] rand_uc2_1 = randvec_uchar(2); + short[] rand_uc3_1 = randvec_uchar(3); + short[] rand_uc4_1 = randvec_uchar(4); + int rand_us1_0 = rand.nextInt(0x1 << 16); + int[] rand_us2_0 = randvec_ushort(2); + int[] rand_us3_0 = randvec_ushort(3); + int[] rand_us4_0 = randvec_ushort(4); + int rand_us1_1 = rand.nextInt(0x1 << 16); + int[] rand_us2_1 = randvec_ushort(2); + int[] rand_us3_1 = randvec_ushort(3); + int[] rand_us4_1 = randvec_ushort(4); + long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE; + long[] rand_ui2_0 = randvec_uint(2); + long[] rand_ui3_0 = randvec_uint(3); + long[] rand_ui4_0 = randvec_uint(4); + long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE; + long[] rand_ui2_1 = randvec_uint(2); + long[] rand_ui3_1 = randvec_uint(3); + long[] rand_ui4_1 = randvec_uint(4); + */ + // TODO: generate unsigned long vectors + + // Set random vectors in renderscript code + s.set_rand_f1_0(rand_f1_0); + s.set_rand_f2_0(pack_f2(rand_f2_0)); + s.set_rand_f3_0(pack_f3(rand_f3_0)); + s.set_rand_f4_0(pack_f4(rand_f4_0)); + s.set_rand_f1_1(rand_f1_1); + s.set_rand_f2_1(pack_f2(rand_f2_1)); + s.set_rand_f3_1(pack_f3(rand_f3_1)); + s.set_rand_f4_1(pack_f4(rand_f4_1)); + s.set_rand_sc1_1(rand_sc1_1); + s.set_rand_sc2_1(pack_b2(rand_sc2_1)); + s.set_rand_sc3_1(pack_b3(rand_sc3_1)); + s.set_rand_sc4_1(pack_b4(rand_sc4_1)); + s.set_rand_ss1_0(rand_ss1_0); + s.set_rand_ss2_0(pack_s2(rand_ss2_0)); + s.set_rand_ss3_0(pack_s3(rand_ss3_0)); + s.set_rand_ss4_0(pack_s4(rand_ss4_0)); + s.set_rand_ss1_1(rand_ss1_1); + s.set_rand_ss2_1(pack_s2(rand_ss2_1)); + s.set_rand_ss3_1(pack_s3(rand_ss3_1)); + s.set_rand_ss4_1(pack_s4(rand_ss4_1)); + s.set_rand_si1_0(rand_si1_0); + s.set_rand_si2_0(pack_i2(rand_si2_0)); + s.set_rand_si3_0(pack_i3(rand_si3_0)); + s.set_rand_si4_0(pack_i4(rand_si4_0)); + s.set_rand_si1_1(rand_si1_1); + s.set_rand_si2_1(pack_i2(rand_si2_1)); + s.set_rand_si3_1(pack_i3(rand_si3_1)); + s.set_rand_si4_1(pack_i4(rand_si4_1)); + s.set_rand_sl1_0(rand_sl1_0); + s.set_rand_sl2_0(pack_l2(rand_sl2_0)); + s.set_rand_sl3_0(pack_l3(rand_sl3_0)); + s.set_rand_sl4_0(pack_l4(rand_sl4_0)); + s.set_rand_sl1_1(rand_sl1_1); + s.set_rand_sl2_1(pack_l2(rand_sl2_1)); + s.set_rand_sl3_1(pack_l3(rand_sl3_1)); + s.set_rand_sl4_1(pack_l4(rand_sl4_1)); + // FIXME: set signed char input vectors once bug is fixed + /* + s.set_rand_sc1_0(rand_sc1_0); + s.set_rand_sc2_0(pack_b2(rand_sc2_0)); + s.set_rand_sc3_0(pack_b3(rand_sc3_0)); + s.set_rand_sc4_0(pack_b4(rand_sc4_0)); + */ + // FIXME: set unsigned input vectors once bug 6764163 is fixed + /* + s.set_rand_us1_0(rand_us1_0); + s.set_rand_us2_0(pack_i2(rand_us2_0)); + s.set_rand_us3_0(pack_i3(rand_us3_0)); + s.set_rand_us4_0(pack_i4(rand_us4_0)); + s.set_rand_us1_1(rand_us1_1); + s.set_rand_us2_1(pack_i2(rand_us2_1)); + s.set_rand_us3_1(pack_i3(rand_us3_1)); + s.set_rand_us4_1(pack_i4(rand_us4_1)); + s.set_rand_uc1_0(rand_uc1_0); + s.set_rand_uc2_0(pack_s2(rand_uc2_0)); + s.set_rand_uc3_0(pack_s3(rand_uc3_0)); + s.set_rand_uc4_0(pack_s4(rand_uc4_0)); + s.set_rand_uc1_1(rand_uc1_1); + s.set_rand_uc2_1(pack_s2(rand_uc2_1)); + s.set_rand_uc3_1(pack_s3(rand_uc3_1)); + s.set_rand_uc4_1(pack_s4(rand_uc4_1)); + s.set_rand_ui1_0(rand_ui1_0); + s.set_rand_ui2_0(pack_l2(rand_ui2_0)); + s.set_rand_ui3_0(pack_l3(rand_ui3_0)); + s.set_rand_ui4_0(pack_l4(rand_ui4_0)); + s.set_rand_ui1_1(rand_ui1_1); + s.set_rand_ui2_1(pack_l2(rand_ui2_1)); + s.set_rand_ui3_1(pack_l3(rand_ui3_1)); + s.set_rand_ui4_1(pack_l4(rand_ui4_1)); + */ + // TODO: set unsigned long vectors + + // Set results for min + s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1)); + s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1))); + s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1))); + s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1))); + s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1)); + s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1))); + s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1))); + s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1))); + s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1)); + s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1))); + s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1))); + s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1))); + s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1)); + s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1))); + s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1))); + s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1))); + // FIXME: set signed char min reference vectors once bug is fixed + /* + s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1)); + s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1))); + s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1))); + s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1))); + */ + // FIXME: set unsigned min reference vectors once bug 6764163 is fixed + /* + s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1)); + s.set_min_rand_uc2_uc2(pack_s3(min(rand_uc2_0, rand_uc2_1))); + s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1))); + s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1))); + s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1)); + s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1))); + s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1))); + s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1))); + s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1)); + s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1))); + s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1))); + s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1))); + */ + // TODO: set results for unsigned long min + + // Set results for max + s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1)); + s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1))); + s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1))); + s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1))); + s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1)); + s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1))); + s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1))); + s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1))); + s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1)); + s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1))); + s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1))); + s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1))); + s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1)); + s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1))); + s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1))); + s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1))); + // FIXME: set signed char max reference vectors once bug is fixed + /* + s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1)); + s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1))); + s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1))); + s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1))); + */ + // FIXME: set unsigned max reference vectors once bug 6764163 is fixed + /* + s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1)); + s.set_max_rand_uc2_uc2(pack_s3(max(rand_uc2_0, rand_uc2_1))); + s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1))); + s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1))); + s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1)); + s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1))); + s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1))); + s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1))); + s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1)); + s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1))); + s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1))); + s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1))); + */ + // TODO: set results for unsigned long max + + // Set results for fmin + s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1)); + s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1))); + s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1))); + s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1))); + s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1))); + s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1))); + s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1))); + + // Set results for fmax + s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1)); + s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1))); + s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1))); + s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1))); + s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1))); + s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1))); + s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1))); } public void run() { diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs index 953b9de144a2..ac3a3fa9b617 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs @@ -1,34 +1,391 @@ #include "shared.rsh" //#pragma rs_fp_relaxed -float x = 0.0f; -float y = 0.0f; -float result_add = 0.0f; -float result_sub = 0.0f; -float result_mul = 0.0f; -float result_div = 0.0f; - -#define TEST_OP(op, opName) \ -result = x op y; \ -if (! float_almost_equal(result, result_##opName)) { \ - rsDebug(#opName " did not match!", 0); \ - rsDebug("x = ", x); \ - rsDebug("y = ", y); \ - rsDebug("Result = ", result); \ - rsDebug("Expected = ", result_##opName); \ - rsDebug("Difference = ", result - result_##opName); \ - rsDebug("ULP Difference =", float_dist(result, result_##opName)); \ +volatile float x = 0.0f; +volatile float y = 0.0f; +volatile float result_add = 0.0f; +volatile float result_sub = 0.0f; +volatile float result_mul = 0.0f; +volatile float result_div = 0.0f; + +#define DECLARE_INPUT_SET(type, abbrev) \ +volatile type rand_##abbrev##1_0, rand_##abbrev##1_1; \ +volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \ +volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \ +volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1; + +#define DECLARE_ALL_INPUT_SETS() \ +DECLARE_INPUT_SET(float, f); \ +DECLARE_INPUT_SET(char, sc); \ +DECLARE_INPUT_SET(uchar, uc); \ +DECLARE_INPUT_SET(short, ss); \ +DECLARE_INPUT_SET(ushort, us); \ +DECLARE_INPUT_SET(int, si); \ +DECLARE_INPUT_SET(uint, ui); \ +DECLARE_INPUT_SET(long, sl); \ +DECLARE_INPUT_SET(ulong, ul); + +DECLARE_ALL_INPUT_SETS(); + +#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func) \ +volatile type func##_rand_##abbrev##1_##abbrev##1; \ +volatile type##2 func##_rand_##abbrev##2_##abbrev##2; \ +volatile type##3 func##_rand_##abbrev##3_##abbrev##3; \ +volatile type##4 func##_rand_##abbrev##4_##abbrev##4; +#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func) \ +volatile type##2 func##_rand_##abbrev##2_##abbrev##1; \ +volatile type##3 func##_rand_##abbrev##3_##abbrev##1; \ +volatile type##4 func##_rand_##abbrev##4_##abbrev##1; + +#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func) \ +DECLARE_REFERENCE_SET_VEC_VEC(float, f, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(int, si, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func); \ +DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func); + +DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min); +DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max); +DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin); +DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin); +DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax); +DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax); + +static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) { + int dist = float_dist(actual, expected); + rsDebug("float operation did not match!", op_name); + rsDebug("v1", v1); + rsDebug("v2", v2); + rsDebug("Dalvik result", expected); + rsDebug("Renderscript result", actual); + rsDebug("ULP difference", dist); +} + +static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) { + int2 dist; + dist.x = float_dist(actual.x, expected.x); + dist.y = float_dist(actual.y, expected.y); + rsDebug("float2 operation did not match!", op_name); + rsDebug("v1.x", v1.x); + rsDebug("v1.y", v1.y); + rsDebug("v2.x", v2.x); + rsDebug("v2.y", v2.y); + rsDebug("Dalvik result .x", expected.x); + rsDebug("Dalvik result .y", expected.y); + rsDebug("Renderscript result .x", actual.x); + rsDebug("Renderscript result .y", actual.y); + rsDebug("ULP difference .x", dist.x); + rsDebug("ULP difference .y", dist.y); +} + +static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) { + int3 dist; + dist.x = float_dist(actual.x, expected.x); + dist.y = float_dist(actual.y, expected.y); + dist.z = float_dist(actual.z, expected.z); + rsDebug("float3 operation did not match!", op_name); + rsDebug("v1.x", v1.x); + rsDebug("v1.y", v1.y); + rsDebug("v1.z", v1.z); + rsDebug("v2.x", v2.x); + rsDebug("v2.y", v2.y); + rsDebug("v2.z", v2.z); + rsDebug("Dalvik result .x", expected.x); + rsDebug("Dalvik result .y", expected.y); + rsDebug("Dalvik result .z", expected.z); + rsDebug("Renderscript result .x", actual.x); + rsDebug("Renderscript result .y", actual.y); + rsDebug("Renderscript result .z", actual.z); + rsDebug("ULP difference .x", dist.x); + rsDebug("ULP difference .y", dist.y); + rsDebug("ULP difference .z", dist.z); +} + +static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) { + int4 dist; + dist.x = float_dist(actual.x, expected.x); + dist.y = float_dist(actual.y, expected.y); + dist.z = float_dist(actual.z, expected.z); + dist.w = float_dist(actual.w, expected.w); + rsDebug("float4 operation did not match!", op_name); + rsDebug("v1.x", v1.x); + rsDebug("v1.y", v1.y); + rsDebug("v1.z", v1.z); + rsDebug("v1.w", v1.w); + rsDebug("v2.x", v2.x); + rsDebug("v2.y", v2.y); + rsDebug("v2.z", v2.z); + rsDebug("v2.w", v2.w); + rsDebug("Dalvik result .x", expected.x); + rsDebug("Dalvik result .y", expected.y); + rsDebug("Dalvik result .z", expected.z); + rsDebug("Dalvik result .w", expected.w); + rsDebug("Renderscript result .x", actual.x); + rsDebug("Renderscript result .y", actual.y); + rsDebug("Renderscript result .z", actual.z); + rsDebug("Renderscript result .w", actual.w); + rsDebug("ULP difference .x", dist.x); + rsDebug("ULP difference .y", dist.y); + rsDebug("ULP difference .z", dist.z); + rsDebug("ULP difference .w", dist.w); +} + +static bool f1_almost_equal(float a, float b) { + return float_almost_equal(a, b); +} + +static bool f2_almost_equal(float2 a, float2 b) { + return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y); +} + + +static bool f3_almost_equal(float3 a, float3 b) { + return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y) + && float_almost_equal(a.z, b.z); +} + +static bool f4_almost_equal(float4 a, float4 b) { + return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y) + && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w); +} + +#define TEST_BASIC_FLOAT_OP(op, opName) \ +temp_f1 = x op y; \ +if (! float_almost_equal(temp_f1, result_##opName)) { \ + fail_f1(x, y , temp_f1, result_##opName, #opName); \ + failed = true; \ +} + +#define TEST_FN_FN(func, size) \ +temp_f##size = func(rand_f##size##_0, rand_f##size##_1); \ +if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) { \ + fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func); \ + failed = true; \ +} +#define TEST_FN_F(func, size) \ +temp_f##size = func(rand_f##size##_0, rand_f1_1); \ +if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) { \ + fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func); \ + failed = true; \ +} + +#define TEST_FN_FN_ALL(func) \ +TEST_FN_FN(func, 1) \ +TEST_FN_FN(func, 2) \ +TEST_FN_FN(func, 3) \ +TEST_FN_FN(func, 4) +#define TEST_FN_F_ALL(func) \ +TEST_FN_F(func, 2) \ +TEST_FN_F(func, 3) \ +TEST_FN_F(func, 4) + +#define TEST_VEC1_VEC1(func, type) \ +temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 ); \ +if (temp_##type##1 != func##_rand_##type##1_##type##1) { \ + rsDebug(#func " " #type "1 operation did not match!", 0); \ + rsDebug("v1", rand_##type##1_0); \ + rsDebug("v2", rand_##type##1_1); \ + rsDebug("Dalvik result", func##_rand_##type##1_##type##1); \ + rsDebug("Renderscript result", temp_##type##1); \ + failed = true; \ +} +#define TEST_VEC2_VEC2(func, type) \ +temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 ); \ +if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x \ + || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) { \ + rsDebug(#func " " #type "2 operation did not match!", 0); \ + rsDebug("v1.x", rand_##type##2_0 .x); \ + rsDebug("v1.y", rand_##type##2_0 .y); \ + rsDebug("v2.x", rand_##type##2_1 .x); \ + rsDebug("v2.y", rand_##type##2_1 .y); \ + rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x); \ + rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y); \ + rsDebug("Renderscript result .x", temp_##type##2 .x); \ + rsDebug("Renderscript result .y", temp_##type##2 .y); \ failed = true; \ } +#define TEST_VEC3_VEC3(func, type) \ +temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 ); \ +if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x \ + || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y \ + || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) { \ + rsDebug(#func " " #type "3 operation did not match!", 0); \ + rsDebug("v1.x", rand_##type##3_0 .x); \ + rsDebug("v1.y", rand_##type##3_0 .y); \ + rsDebug("v1.z", rand_##type##3_0 .z); \ + rsDebug("v2.x", rand_##type##3_1 .x); \ + rsDebug("v2.y", rand_##type##3_1 .y); \ + rsDebug("v2.z", rand_##type##3_1 .z); \ + rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x); \ + rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y); \ + rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z); \ + rsDebug("Renderscript result .x", temp_##type##3 .x); \ + rsDebug("Renderscript result .y", temp_##type##3 .y); \ + rsDebug("Renderscript result .z", temp_##type##3 .z); \ + failed = true; \ +} +#define TEST_VEC4_VEC4(func, type) \ +temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 ); \ +if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x \ + || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y \ + || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z \ + || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) { \ + rsDebug(#func " " #type "4 operation did not match!", 0); \ + rsDebug("v1.x", rand_##type##4_0 .x); \ + rsDebug("v1.y", rand_##type##4_0 .y); \ + rsDebug("v1.z", rand_##type##4_0 .z); \ + rsDebug("v1.w", rand_##type##4_0 .w); \ + rsDebug("v2.x", rand_##type##4_1 .x); \ + rsDebug("v2.y", rand_##type##4_1 .y); \ + rsDebug("v2.z", rand_##type##4_1 .z); \ + rsDebug("v2.w", rand_##type##4_1 .w); \ + rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x); \ + rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y); \ + rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z); \ + rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w); \ + rsDebug("Renderscript result .x", temp_##type##4 .x); \ + rsDebug("Renderscript result .y", temp_##type##4 .y); \ + rsDebug("Renderscript result .z", temp_##type##4 .z); \ + rsDebug("Renderscript result .w", temp_##type##4 .w); \ + failed = true; \ +} + +#define TEST_SC1_SC1(func) TEST_VEC1_VEC1(func, sc) +#define TEST_SC2_SC2(func) TEST_VEC2_VEC2(func, sc) +#define TEST_SC3_SC3(func) TEST_VEC3_VEC3(func, sc) +#define TEST_SC4_SC4(func) TEST_VEC4_VEC4(func, sc) + +#define TEST_UC1_UC1(func) TEST_VEC1_VEC1(func, uc) +#define TEST_UC2_UC2(func) TEST_VEC2_VEC2(func, uc) +#define TEST_UC3_UC3(func) TEST_VEC3_VEC3(func, uc) +#define TEST_UC4_UC4(func) TEST_VEC4_VEC4(func, uc) + +#define TEST_SS1_SS1(func) TEST_VEC1_VEC1(func, ss) +#define TEST_SS2_SS2(func) TEST_VEC2_VEC2(func, ss) +#define TEST_SS3_SS3(func) TEST_VEC3_VEC3(func, ss) +#define TEST_SS4_SS4(func) TEST_VEC4_VEC4(func, ss) + +#define TEST_US1_US1(func) TEST_VEC1_VEC1(func, us) +#define TEST_US2_US2(func) TEST_VEC2_VEC2(func, us) +#define TEST_US3_US3(func) TEST_VEC3_VEC3(func, us) +#define TEST_US4_US4(func) TEST_VEC4_VEC4(func, us) + +#define TEST_SI1_SI1(func) TEST_VEC1_VEC1(func, si) +#define TEST_SI2_SI2(func) TEST_VEC2_VEC2(func, si) +#define TEST_SI3_SI3(func) TEST_VEC3_VEC3(func, si) +#define TEST_SI4_SI4(func) TEST_VEC4_VEC4(func, si) + +#define TEST_UI1_UI1(func) TEST_VEC1_VEC1(func, ui) +#define TEST_UI2_UI2(func) TEST_VEC2_VEC2(func, ui) +#define TEST_UI3_UI3(func) TEST_VEC3_VEC3(func, ui) +#define TEST_UI4_UI4(func) TEST_VEC4_VEC4(func, ui) + +#define TEST_SL1_SL1(func) TEST_VEC1_VEC1(func, sl) +#define TEST_SL2_SL2(func) TEST_VEC2_VEC2(func, sl) +#define TEST_SL3_SL3(func) TEST_VEC3_VEC3(func, sl) +#define TEST_SL4_SL4(func) TEST_VEC4_VEC4(func, sl) + +#define TEST_UL1_UL1(func) TEST_VEC1_VEC1(func, ul) +#define TEST_UL2_UL2(func) TEST_VEC2_VEC2(func, ul) +#define TEST_UL3_UL3(func) TEST_VEC3_VEC3(func, ul) +#define TEST_UL4_UL4(func) TEST_VEC4_VEC4(func, ul) + +#define TEST_SC_SC_ALL(func) \ +TEST_SC1_SC1(func) \ +TEST_SC2_SC2(func) \ +TEST_SC3_SC3(func) \ +TEST_SC4_SC4(func) +#define TEST_UC_UC_ALL(func) \ +TEST_UC1_UC1(func) \ +TEST_UC2_UC2(func) \ +TEST_UC3_UC3(func) \ +TEST_UC4_UC4(func) + +#define TEST_SS_SS_ALL(func) \ +TEST_SS1_SS1(func) \ +TEST_SS2_SS2(func) \ +TEST_SS3_SS3(func) \ +TEST_SS4_SS4(func) +#define TEST_US_US_ALL(func) \ +TEST_US1_US1(func) \ +TEST_US2_US2(func) \ +TEST_US3_US3(func) \ +TEST_US4_US4(func) +#define TEST_SI_SI_ALL(func) \ +TEST_SI1_SI1(func) \ +TEST_SI2_SI2(func) \ +TEST_SI3_SI3(func) \ +TEST_SI4_SI4(func) +#define TEST_UI_UI_ALL(func) \ +TEST_UI1_UI1(func) \ +TEST_UI2_UI2(func) \ +TEST_UI3_UI3(func) \ +TEST_UI4_UI4(func) +#define TEST_SL_SL_ALL(func) \ +TEST_SL1_SL1(func) \ +TEST_SL2_SL2(func) \ +TEST_SL3_SL3(func) \ +TEST_SL4_SL4(func) +#define TEST_UL_UL_ALL(func) \ +TEST_UL1_UL1(func) \ +TEST_UL2_UL2(func) \ +TEST_UL3_UL3(func) \ +TEST_UL4_UL4(func) + +#define TEST_VEC_VEC_ALL(func) \ +TEST_FN_FN_ALL(func) \ +TEST_SS_SS_ALL(func) \ +TEST_SI_SI_ALL(func) +// FIXME: Add tests back in once bug 6764163 is fixed +#if 0 +TEST_SC_SC_ALL(func) \ +TEST_US_US_ALL(func) \ +TEST_UC_UC_ALL(func) \ +TEST_UI_UI_ALL(func) +#endif +// TODO: add long types to ALL macro +#if 0 +TEST_SL_SL_ALL(func) \ +TEST_UL_UL_ALL(func) +#endif + +#define DECLARE_TEMP_SET(type, abbrev) \ +volatile type temp_##abbrev##1; \ +volatile type##2 temp_##abbrev##2; \ +volatile type##3 temp_##abbrev##3; \ +volatile type##4 temp_##abbrev##4; + +#define DECLARE_ALL_TEMP_SETS() \ +DECLARE_TEMP_SET(float, f); \ +DECLARE_TEMP_SET(char, sc); \ +DECLARE_TEMP_SET(uchar, uc); \ +DECLARE_TEMP_SET(short, ss); \ +DECLARE_TEMP_SET(ushort, us); \ +DECLARE_TEMP_SET(int, si); \ +DECLARE_TEMP_SET(uint, ui); \ +DECLARE_TEMP_SET(long, sl); \ +DECLARE_TEMP_SET(ulong, ul); static bool test_math_agree() { bool failed = false; - float result = 0.0; - TEST_OP(+, add); - TEST_OP(-, sub); - TEST_OP(*, mul); - TEST_OP(/, div); + DECLARE_ALL_TEMP_SETS(); + + TEST_BASIC_FLOAT_OP(+, add); + TEST_BASIC_FLOAT_OP(-, sub); + TEST_BASIC_FLOAT_OP(*, mul); + TEST_BASIC_FLOAT_OP(/, div); + + TEST_VEC_VEC_ALL(min); + TEST_VEC_VEC_ALL(max); + TEST_FN_FN_ALL(fmin); + TEST_FN_F_ALL(fmin); + TEST_FN_FN_ALL(fmax); + TEST_FN_F_ALL(fmax); if (failed) { rsDebug("test_math_agree FAILED", 0); diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index a69adc1c9a55..ee076e602e5e 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -2210,7 +2210,7 @@ struct NamespaceAttributePair { status_t writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, - const char* startTag, const KeyedVector<String8, NamespaceAttributePair>* tagAttrPairs) + const char* startTag, const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs) { status_t err; ResXMLTree tree; @@ -2254,17 +2254,21 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, } else if (tagAttrPairs != NULL) { ssize_t tagIndex = tagAttrPairs->indexOfKey(tag); if (tagIndex >= 0) { - const NamespaceAttributePair& nsAttr = tagAttrPairs->valueAt(tagIndex); - ssize_t attrIndex = tree.indexOfAttribute(nsAttr.ns, nsAttr.attr); - if (attrIndex < 0) { - // fprintf(stderr, "%s:%d: <%s> does not have attribute %s:%s.\n", - // layoutFile->getPrintableSource().string(), tree.getLineNumber(), - // tag.string(), nsAttr.ns, nsAttr.attr); - } else { - size_t len; - addProguardKeepRule(keep, - String8(tree.getAttributeStringValue(attrIndex, &len)), NULL, - layoutFile->getPrintableSource(), tree.getLineNumber()); + const Vector<NamespaceAttributePair>& nsAttrVector = tagAttrPairs->valueAt(tagIndex); + for (size_t i = 0; i < nsAttrVector.size(); i++) { + const NamespaceAttributePair& nsAttr = nsAttrVector[i]; + + ssize_t attrIndex = tree.indexOfAttribute(nsAttr.ns, nsAttr.attr); + if (attrIndex < 0) { + // fprintf(stderr, "%s:%d: <%s> does not have attribute %s:%s.\n", + // layoutFile->getPrintableSource().string(), tree.getLineNumber(), + // tag.string(), nsAttr.ns, nsAttr.attr); + } else { + size_t len; + addProguardKeepRule(keep, + String8(tree.getAttributeStringValue(attrIndex, &len)), NULL, + layoutFile->getPrintableSource(), tree.getLineNumber()); + } } } } @@ -2280,9 +2284,18 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, return NO_ERROR; } -static void addTagAttrPair(KeyedVector<String8, NamespaceAttributePair>* dest, +static void addTagAttrPair(KeyedVector<String8, Vector<NamespaceAttributePair> >* dest, const char* tag, const char* ns, const char* attr) { - dest->add(String8(tag), NamespaceAttributePair(ns, attr)); + String8 tagStr(tag); + ssize_t index = dest->indexOfKey(tagStr); + + if (index < 0) { + Vector<NamespaceAttributePair> vector; + vector.add(NamespaceAttributePair(ns, attr)); + dest->add(tagStr, vector); + } else { + dest->editValueAt(index).add(NamespaceAttributePair(ns, attr)); + } } status_t @@ -2291,13 +2304,13 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets) status_t err; // tag:attribute pairs that should be checked in layout files. - KeyedVector<String8, NamespaceAttributePair> kLayoutTagAttrPairs; + KeyedVector<String8, Vector<NamespaceAttributePair> > kLayoutTagAttrPairs; addTagAttrPair(&kLayoutTagAttrPairs, "view", NULL, "class"); addTagAttrPair(&kLayoutTagAttrPairs, "fragment", NULL, "class"); addTagAttrPair(&kLayoutTagAttrPairs, "fragment", RESOURCES_ANDROID_NAMESPACE, "name"); // tag:attribute pairs that should be checked in xml files. - KeyedVector<String8, NamespaceAttributePair> kXmlTagAttrPairs; + KeyedVector<String8, Vector<NamespaceAttributePair> > kXmlTagAttrPairs; addTagAttrPair(&kXmlTagAttrPairs, "PreferenceScreen", RESOURCES_ANDROID_NAMESPACE, "fragment"); addTagAttrPair(&kXmlTagAttrPairs, "header", RESOURCES_ANDROID_NAMESPACE, "fragment"); @@ -2307,7 +2320,7 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets) const sp<AaptDir>& d = dirs.itemAt(k); const String8& dirName = d->getLeaf(); const char* startTag = NULL; - const KeyedVector<String8, NamespaceAttributePair>* tagAttrPairs = NULL; + const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs = NULL; if ((dirName == String8("layout")) || (strncmp(dirName.string(), "layout-", 7) == 0)) { tagAttrPairs = &kLayoutTagAttrPairs; } else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) { @@ -2339,6 +2352,7 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets) if (overlay.get()) { return writeProguardForLayouts(keep, overlay); } + return NO_ERROR; } |