Merge "Remove unnecessary lock to save 1 allocation per TextView"
diff --git a/api/current.txt b/api/current.txt
index 8b02878..16e4a09 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6808,6 +6808,7 @@
ctor public ComponentInfo(android.content.pm.ComponentInfo);
ctor protected ComponentInfo(android.os.Parcel);
method public final int getIconResource();
+ method public final int getLogoResource();
method public boolean isEnabled();
field public android.content.pm.ApplicationInfo applicationInfo;
field public int descriptionRes;
@@ -12057,7 +12058,6 @@
method public void start();
method public void stop();
method public void writeSampleData(int, java.nio.ByteBuffer, android.media.MediaCodec.BufferInfo);
- field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
}
public static final class MediaMuxer.OutputFormat {
@@ -12285,7 +12285,7 @@
method public void removeCallback(android.media.MediaRouter.Callback);
method public void removeUserRoute(android.media.MediaRouter.UserRouteInfo);
method public void selectRoute(int, android.media.MediaRouter.RouteInfo);
- field public static final int CALLBACK_FLAG_ACTIVE_SCAN = 1; // 0x1
+ field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
field public static final int ROUTE_TYPE_LIVE_AUDIO = 1; // 0x1
field public static final int ROUTE_TYPE_LIVE_VIDEO = 2; // 0x2
@@ -19962,6 +19962,7 @@
field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
+ field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
@@ -27040,7 +27041,9 @@
method public void setFlags(int, int);
method public void setFormat(int);
method public void setGravity(int);
+ method public void setIcon(int);
method public void setLayout(int, int);
+ method public void setLogo(int);
method public void setSoftInputMode(int);
method public abstract void setTitle(java.lang.CharSequence);
method public abstract void setTitleColor(int);
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index b4a12c4..12fcdcf 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -822,7 +822,7 @@
* {@link android.Manifest.permission#USE_CREDENTIALS}.
*
* @param account The account to fetch an auth token for
- * @param authTokenType The auth token type, see {#link getAuthToken}
+ * @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
* @param notifyAuthFailure If true, display a notification and return null
* if authentication fails; if false, prompt and wait for the user to
* re-enter correct credentials before returning
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 58eb66f..82c2159 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -29,6 +29,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
@@ -127,6 +128,7 @@
private int mCallingUid;
private String mCallingPackage;
private boolean mDisallowAddAccounts;
+ private boolean mDontShowPicker;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -189,11 +191,23 @@
mSetOfRelevantAccountTypes = getReleventAccountTypes(intent);
mAlwaysPromptForAccount = intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false);
mDescriptionOverride = intent.getStringExtra(EXTRA_DESCRIPTION_TEXT_OVERRIDE);
+
+ // Need to do this once here to request the window feature. Can't do it in onResume
+ mAccounts = getAcceptableAccountChoices(AccountManager.get(this));
+ if (mAccounts.isEmpty()
+ && mDisallowAddAccounts) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.app_not_authorized);
+ mDontShowPicker = true;
+ }
}
@Override
protected void onResume() {
super.onResume();
+
+ if (mDontShowPicker) return;
+
final AccountManager accountManager = AccountManager.get(this);
mAccounts = getAcceptableAccountChoices(accountManager);
@@ -206,11 +220,6 @@
// If there are no relevant accounts and only one relevant account type go directly to
// add account. Otherwise let the user choose.
if (mAccounts.isEmpty()) {
- if (mDisallowAddAccounts) {
- setContentView(R.layout.app_not_authorized);
- setTitle(R.string.error_message_title);
- return;
- }
if (mSetOfRelevantAccountTypes.size() == 1) {
runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next());
} else {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6b5df7f..7f2f744 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1877,9 +1877,12 @@
if (isChild() || !window.hasFeature(Window.FEATURE_ACTION_BAR) || mActionBar != null) {
return;
}
-
+
mActionBar = new ActionBarImpl(this);
mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
+
+ mWindow.setDefaultIcon(mActivityInfo.getIconResource());
+ mWindow.setDefaultLogo(mActivityInfo.getLogoResource());
}
/**
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index b3d99c5..634fa30 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,6 +16,8 @@
package android.app;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import com.android.internal.app.ActionBarImpl;
import com.android.internal.policy.PolicyManager;
@@ -264,6 +266,9 @@
mDecor = mWindow.getDecorView();
if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
+ final ApplicationInfo info = mContext.getApplicationInfo();
+ mWindow.setDefaultIcon(info.icon);
+ mWindow.setDefaultLogo(info.logo);
mActionBar = new ActionBarImpl(this);
}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 1166e4b..d1c7bec 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -529,9 +529,9 @@
/**
* Notifies the specified collection view in all the specified AppWidget instances
- * to invalidate their currently data.
+ * to invalidate their data.
*
- * @param appWidgetIds The AppWidget instances for which to notify of view data changes.
+ * @param appWidgetIds The AppWidget instances to notify of view data changes.
* @param viewId The collection view id.
*/
public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) {
@@ -544,11 +544,11 @@
}
/**
- * Notifies the specified collection view in all the specified AppWidget instance
- * to invalidate it's currently data.
+ * Notifies the specified collection view in the specified AppWidget instance
+ * to invalidate its data.
*
- * @param appWidgetId The AppWidget instance for which to notify of view data changes.
- * @param viewId The collection view id.
+ * @param appWidgetId The AppWidget instance to notify of view data changes.
+ * @param viewId The collection view id.
*/
public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) {
notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 7ec73ef..79bb476 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -47,17 +47,22 @@
* device discovery, query a list of bonded (paired) devices,
* instantiate a {@link BluetoothDevice} using a known MAC address, and create
* a {@link BluetoothServerSocket} to listen for connection requests from other
- * devices.
+ * devices, and start a scan for Bluetooth LE devices.
*
* <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
- * adapter, call the static {@link #getDefaultAdapter} method.
+ * adapter, when running on JELLY_BEAN_MR1 and below, call the
+ * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
+ * higher, retrieve it through
+ * {@link android.content.Context#getSystemService} with
+ * {@link android.content.Context#BLUETOOTH_SERVICE}.
* Fundamentally, this is your starting point for all
* Bluetooth actions. Once you have the local adapter, you can get a set of
* {@link BluetoothDevice} objects representing all paired devices with
* {@link #getBondedDevices()}; start device discovery with
* {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
* listen for incoming connection requests with
- * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}.
+ * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for
+ * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
*
* <p class="note"><strong>Note:</strong>
* Most methods require the {@link android.Manifest.permission#BLUETOOTH}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 79a5ffe..3ee7142 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -107,7 +107,7 @@
* <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
* #EXTRA_CLASS}.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
- * @see {@link BluetoothClass}
+ * {@see BluetoothClass}
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CLASS_CHANGED =
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 77e5f84..df3ec1a 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -565,6 +565,9 @@
/**
* Close this Bluetooth GATT client.
+ *
+ * Application should call this method as early as possible after it is done with
+ * this GATT client.
*/
public void close() {
if (DBG) Log.d(TAG, "close()");
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 2259c1e..80ea4a6 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -27,6 +27,7 @@
*
* @param gatt GATT client
* @param status Status of the connect or disconnect operation.
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
* @param newState Returns the new connection state. Can be one of
* {@link BluetoothProfile#STATE_DISCONNECTED} or
* {@link BluetoothProfile#STATE_CONNECTED}
@@ -72,6 +73,7 @@
* @param characteristic Characteristic that was written to the associated
* remote device.
* @param status The result of the write operation
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
*/
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
@@ -108,6 +110,7 @@
* @param descriptor Descriptor that was writte to the associated
* remote device.
* @param status The result of the write operation
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
*/
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index d3b85a9..58ee54f 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -289,6 +289,9 @@
/**
* Close this GATT server instance.
+ *
+ * Application should call this method as early as possible after it is done with
+ * this GATT server.
*/
public void close() {
if (DBG) Log.d(TAG, "close()");
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 03a6093..897e6fe 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2269,7 +2269,7 @@
/**
* Broadcast Action: An outgoing call is about to be placed.
*
- * <p>The Intent will have the following extra value:
+ * <p>The Intent will have the following extra value:</p>
* <ul>
* <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> -
* the phone number originally intended to be dialed.</li>
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 2812477..4dbcf23 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -116,6 +116,17 @@
public final int getIconResource() {
return icon != 0 ? icon : applicationInfo.icon;
}
+
+ /**
+ * Return the logo resource identifier to use for this component. If
+ * the component defines a logo, that is used; else, the application
+ * logo is used.
+ *
+ * @return The logo associated with this component.
+ */
+ public final int getLogoResource() {
+ return logo != 0 ? logo : applicationInfo.logo;
+ }
protected void dumpFront(Printer pw, String prefix) {
super.dumpFront(pw, prefix);
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 07117fe..de8e256 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -328,6 +328,7 @@
implements Comparator<ResolveInfo> {
public DisplayNameComparator(PackageManager pm) {
mPM = pm;
+ mCollator.setStrength(Collator.PRIMARY);
}
public final int compare(ResolveInfo a, ResolveInfo b) {
@@ -336,10 +337,10 @@
CharSequence sb = b.loadLabel(mPM);
if (sb == null) sb = b.activityInfo.name;
- return sCollator.compare(sa.toString(), sb.toString());
+ return mCollator.compare(sa.toString(), sb.toString());
}
- private final Collator sCollator = Collator.getInstance();
+ private final Collator mCollator = Collator.getInstance();
private PackageManager mPM;
}
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 4881d14..7f82ce3 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -381,7 +381,6 @@
if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
+ " ic=" + mInputConnection);
onUnbindInput();
- mInputStarted = false;
mInputBinding = null;
mInputConnection = null;
}
@@ -719,7 +718,7 @@
super.onDestroy();
mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
mInsetsComputer);
- finishViews();
+ doFinishInput();
if (mWindowAdded) {
// Disable exit animation for the current IME window
// to avoid the race condition between the exit and enter animations
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d02a320..c1d4ae9 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,6 +16,8 @@
package android.os;
+import android.util.ArrayMap;
+
import java.util.HashMap;
/**
@@ -47,8 +49,8 @@
* implements the {@link #onCallbackDied} method.
*/
public class RemoteCallbackList<E extends IInterface> {
- /*package*/ HashMap<IBinder, Callback> mCallbacks
- = new HashMap<IBinder, Callback>();
+ /*package*/ ArrayMap<IBinder, Callback> mCallbacks
+ = new ArrayMap<IBinder, Callback>();
private Object[] mActiveBroadcast;
private int mBroadcastCount = -1;
private boolean mKilled = false;
@@ -159,7 +161,8 @@
*/
public void kill() {
synchronized (mCallbacks) {
- for (Callback cb : mCallbacks.values()) {
+ for (int cbi=mCallbacks.size()-1; cbi>=0; cbi--) {
+ Callback cb = mCallbacks.valueAt(cbi);
cb.mCallback.asBinder().unlinkToDeath(cb, 0);
}
mCallbacks.clear();
@@ -238,11 +241,10 @@
if (active == null || active.length < N) {
mActiveBroadcast = active = new Object[N];
}
- int i=0;
- for (Callback cb : mCallbacks.values()) {
- active[i++] = cb;
+ for (int i=0; i<N; i++) {
+ active[i] = mCallbacks.valueAt(i);
}
- return i;
+ return N;
}
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3267939..31da091 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Printer;
import android.util.Singleton;
@@ -1069,7 +1070,7 @@
// Map from violation stacktrace hashcode -> uptimeMillis of
// last violation. No locking needed, as this is only
// accessed by the same thread.
- private final HashMap<Integer, Long> mLastViolationTime = new HashMap<Integer, Long>();
+ private ArrayMap<Integer, Long> mLastViolationTime;
public AndroidBlockGuardPolicy(final int policyMask) {
mPolicyMask = policyMask;
@@ -1279,8 +1280,13 @@
// Not perfect, but fast and good enough for dup suppression.
Integer crashFingerprint = info.hashCode();
long lastViolationTime = 0;
- if (mLastViolationTime.containsKey(crashFingerprint)) {
- lastViolationTime = mLastViolationTime.get(crashFingerprint);
+ if (mLastViolationTime != null) {
+ Long vtime = mLastViolationTime.get(crashFingerprint);
+ if (vtime != null) {
+ lastViolationTime = vtime;
+ }
+ } else {
+ mLastViolationTime = new ArrayMap<Integer, Long>(1);
}
long now = SystemClock.uptimeMillis();
mLastViolationTime.put(crashFingerprint, now);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ff06df0..c1a296d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -650,7 +650,6 @@
* <p>
* Output: Nothing.
* @see android.service.dreams.DreamService
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 70f7d2e..6da7546 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -212,10 +212,12 @@
*/
@Override
public void clear() {
- freeArrays(mHashes, mArray, mSize);
- mHashes = SparseArray.EMPTY_INTS;
- mArray = SparseArray.EMPTY_OBJECTS;
- mSize = 0;
+ if (mSize != 0) {
+ freeArrays(mHashes, mArray, mSize);
+ mHashes = SparseArray.EMPTY_INTS;
+ mArray = SparseArray.EMPTY_OBJECTS;
+ mSize = 0;
+ }
}
/**
@@ -227,9 +229,9 @@
int[] ohashes = mHashes;
Object[] oarray = mArray;
allocArrays(minimumCapacity);
- if (mHashes.length > 0) {
- System.arraycopy(ohashes, 0, mHashes, 0, mHashes.length);
- System.arraycopy(oarray, 0, mArray, 0, mArray.length);
+ if (mSize > 0) {
+ System.arraycopy(ohashes, 0, mHashes, 0, mSize);
+ System.arraycopy(oarray, 0, mArray, 0, mSize<<1);
}
freeArrays(ohashes, oarray, mSize);
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8007d9a..ad3082e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -97,7 +97,7 @@
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
+ int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
void setAppWillBeHidden(IBinder token);
void setAppVisibility(IBinder token, boolean visible);
void startAppFreezingScreen(IBinder token, int configChanges);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d1fa455..6f88bb2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12413,8 +12413,8 @@
/**
* <p>Specifies the type of layer backing this view. The layer can be
- * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
- * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
+ * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
+ * {@link #LAYER_TYPE_HARDWARE}.</p>
*
* <p>A layer is associated with an optional {@link android.graphics.Paint}
* instance that controls how the layer is composed on screen. The following
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 06974d3..39d48a7 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1256,4 +1256,38 @@
* @param mask Flags specifying which options should be modified. Others will remain unchanged.
*/
public void setUiOptions(int uiOptions, int mask) { }
+
+ /**
+ * Set the primary icon for this window.
+ *
+ * @param resId resource ID of a drawable to set
+ */
+ public void setIcon(int resId) { }
+
+ /**
+ * Set the default icon for this window.
+ * This will be overridden by any other icon set operation which could come from the
+ * theme or another explicit set.
+ *
+ * @hide
+ */
+ public void setDefaultIcon(int resId) { }
+
+ /**
+ * Set the logo for this window. A logo is often shown in place of an
+ * {@link #setIcon(int) icon} but is generally wider and communicates window title information
+ * as well.
+ *
+ * @param resId resource ID of a drawable to set
+ */
+ public void setLogo(int resId) { }
+
+ /**
+ * Set the default logo for this window.
+ * This will be overridden by any other logo set operation which could come from the
+ * theme or another explicit set.
+ *
+ * @hide
+ */
+ public void setDefaultLogo(int resId) { }
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 6a35f20..6291e62 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -642,7 +642,7 @@
*/
public View addStartingWindow(IBinder appToken, String packageName,
int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel,
- int labelRes, int icon, int windowFlags);
+ int labelRes, int icon, int logo, int windowFlags);
/**
* Called when the first window of an application has been displayed, while
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index b3ff54d..f730cf7 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -42,7 +42,8 @@
* Base class for implementors of the InputConnection interface, taking care
* of most of the common behavior for providing a connection to an Editable.
* Implementors of this class will want to be sure to implement
- * {@link #getEditable} to provide access to their own editable object.
+ * {@link #getEditable} to provide access to their own editable object, and
+ * to refer to the documentation in {@link InputConnection}.
*/
public class BaseInputConnection implements InputConnection {
private static final boolean DEBUG = false;
diff --git a/core/java/android/view/inputmethod/CompletionInfo.java b/core/java/android/view/inputmethod/CompletionInfo.java
index 3591cb1..70b8059 100644
--- a/core/java/android/view/inputmethod/CompletionInfo.java
+++ b/core/java/android/view/inputmethod/CompletionInfo.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2007-2008 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -23,6 +23,30 @@
/**
* Information about a single text completion that an editor has reported to
* an input method.
+ *
+ * <p>This class encapsulates a completion offered by an application
+ * that wants it to be presented to the user by the IME. Usually, apps
+ * present their completions directly in a scrolling list for example
+ * (UI developers will usually use or extend
+ * {@see android.widget.AutoCompleteTextView} to implement this).
+ * However, in some cases, the editor may not be visible, as in the
+ * case in extract mode where the IME has taken over the full
+ * screen. In this case, the editor can choose to send their
+ * completions to the IME for display.
+ *
+ * <p>Most applications who want to send completions to an IME should use
+ * {@link android.widget.AutoCompleteTextView} as this class makes this
+ * process easy. In this case, the application would not have to deal directly
+ * with this class.
+ *
+ * <p>An application who implements its own editor and wants direct control
+ * over this would create an array of CompletionInfo objects, and send it to the IME using
+ * {@link InputMethodManager#displayCompletions(View, CompletionInfo[])}.
+ * The IME would present the completions however they see fit, and
+ * call back to the editor through
+ * {@link InputConnection#commitCompletion(CompletionInfo)}.
+ * The application can then pick up the commit event by overriding
+ * {@link android.widget.TextView#onCommitCompletion(CompletionInfo)}.
*/
public final class CompletionInfo implements Parcelable {
private final long mId;
@@ -32,6 +56,12 @@
/**
* Create a simple completion with just text, no label.
+ *
+ * @param id An id that get passed as is (to the editor's discretion)
+ * @param index An index that get passed as is. Typically this is the
+ * index in the list of completions inside the editor.
+ * @param text The text that should be inserted into the editor when
+ * this completion is chosen.
*/
public CompletionInfo(long id, int index, CharSequence text) {
mId = id;
@@ -41,7 +71,18 @@
}
/**
- * Create a full completion with both text and label.
+ * Create a full completion with both text and label. The text is
+ * what will get inserted into the editor, while the label is what
+ * the IME should display. If they are the same, use the version
+ * of the constructor without a `label' argument.
+ *
+ * @param id An id that get passed as is (to the editor's discretion)
+ * @param index An index that get passed as is. Typically this is the
+ * index in the list of completions inside the editor.
+ * @param text The text that should be inserted into the editor when
+ * this completion is chosen.
+ * @param label The text that the IME should be showing among the
+ * completions list.
*/
public CompletionInfo(long id, int index, CharSequence text, CharSequence label) {
mId = id;
@@ -56,7 +97,7 @@
mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
}
-
+
/**
* Return the abstract identifier for this completion, typically
* corresponding to the id associated with it in the original adapter.
@@ -64,7 +105,7 @@
public long getId() {
return mId;
}
-
+
/**
* Return the original position of this completion, typically
* corresponding to its position in the original adapter.
@@ -72,7 +113,7 @@
public int getPosition() {
return mPosition;
}
-
+
/**
* Return the actual text associated with this completion. This is the
* real text that will be inserted into the editor if the user selects it.
@@ -80,7 +121,7 @@
public CharSequence getText() {
return mText;
}
-
+
/**
* Return the user-visible label for the completion, or null if the plain
* text should be shown. If non-null, this will be what the user sees as
@@ -89,7 +130,7 @@
public CharSequence getLabel() {
return mLabel;
}
-
+
@Override
public String toString() {
return "CompletionInfo{#" + mPosition + " \"" + mText
diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java
index 3b2508c..0c5d9e9 100644
--- a/core/java/android/view/inputmethod/ExtractedText.java
+++ b/core/java/android/view/inputmethod/ExtractedText.java
@@ -22,6 +22,9 @@
/**
* Information about text that has been extracted for use by an input method.
+ *
+ * This contains information about a portion of the currently edited text,
+ * that the IME should display into its own interface while in extracted mode.
*/
public class ExtractedText implements Parcelable {
/**
@@ -33,7 +36,7 @@
* The offset in the overall text at which the extracted text starts.
*/
public int startOffset;
-
+
/**
* If the content is a report of a partial text change, this is the
* offset where the change starts and it runs until
@@ -41,7 +44,7 @@
* field is -1.
*/
public int partialStartOffset;
-
+
/**
* If the content is a report of a partial text change, this is the offset
* where the change ends. Note that the actual text may be larger or
@@ -49,40 +52,43 @@
* meaning a reduction or increase, respectively, in the total text.
*/
public int partialEndOffset;
-
+
/**
* The offset where the selection currently starts within the extracted
* text. The real selection start position is at
* <var>startOffset</var>+<var>selectionStart</var>.
*/
public int selectionStart;
-
+
/**
* The offset where the selection currently ends within the extracted
* text. The real selection end position is at
* <var>startOffset</var>+<var>selectionEnd</var>.
*/
public int selectionEnd;
-
+
/**
* Bit for {@link #flags}: set if the text being edited can only be on
* a single line.
*/
public static final int FLAG_SINGLE_LINE = 0x0001;
-
+
/**
* Bit for {@link #flags}: set if the editor is currently in selection mode.
+ *
+ * This happens when a hardware keyboard with latched keys is attached and
+ * the shift key is currently latched.
*/
public static final int FLAG_SELECTING = 0x0002;
-
+
/**
* Additional bit flags of information about the edited text.
*/
public int flags;
-
+
/**
* Used to package this object into a {@link Parcel}.
- *
+ *
* @param dest The {@link Parcel} to be written.
* @param flags The flags used for parceling.
*/
@@ -99,7 +105,8 @@
/**
* Used to make this class parcelable.
*/
- public static final Parcelable.Creator<ExtractedText> CREATOR = new Parcelable.Creator<ExtractedText>() {
+ public static final Parcelable.Creator<ExtractedText> CREATOR
+ = new Parcelable.Creator<ExtractedText>() {
public ExtractedText createFromParcel(Parcel source) {
ExtractedText res = new ExtractedText();
res.text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 76c6d19..e7d84c2 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2007-2008 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -22,60 +22,167 @@
/**
* The InputConnection interface is the communication channel from an
- * {@link InputMethod} back to the application that is receiving its input. It
- * is used to perform such things as reading text around the cursor,
- * committing text to the text box, and sending raw key events to the application.
- *
- * <p>Applications should never directly implement this interface, but instead
- * subclass from {@link BaseInputConnection}. This will ensure that the
- * application does not break when new methods are added to the interface.
+ * {@link InputMethod} back to the application that is receiving its
+ * input. It is used to perform such things as reading text around the
+ * cursor, committing text to the text box, and sending raw key events
+ * to the application.
+ *
+ * <p>Applications should never directly implement this interface, but
+ * instead subclass from {@link BaseInputConnection}. This will ensure
+ * that the application does not break when new methods are added to
+ * the interface.</p>
+ *
+ * <h3>Implementing an IME or an editor</h3>
+ * <p>Text input is the result of the synergy of two essential components:
+ * an Input Method Engine (IME) and an editor. The IME can be a
+ * software keyboard, a handwriting interface, an emoji palette, a
+ * speech-to-text engine, and so on. There are typically several IMEs
+ * installed on any given Android device. In Android, IMEs extend
+ * {@link android.inputmethodservice.InputMethodService}.
+ * For more information about how to create an IME, see the
+ * <a href="{@docRoot}guide/topics/text/creating-input-method.html">
+ * Creating an input method</a> guide.
+ *
+ * The editor is the component that receives text and displays it.
+ * Typically, this is an {@link android.widget.EditText} instance, but
+ * some applications may choose to implement their own editor for
+ * various reasons. This is a large and complicated task, and an
+ * application that does this needs to make sure the behavior is
+ * consistent with standard EditText behavior in Android. An editor
+ * needs to interact with the IME, receiving commands through
+ * this InputConnection interface, and sending commands through
+ * {@link android.view.inputmethod.InputMethodManager}. An editor
+ * should start by implementing
+ * {@link android.view.View#onCreateInputConnection(EditorInfo)}
+ * to return its own input connection.</p>
+ *
+ * <p>If you are implementing your own IME, you will need to call the
+ * methods in this interface to interact with the application. Be sure
+ * to test your IME with a wide range of applications, including
+ * browsers and rich text editors, as some may have peculiarities you
+ * need to deal with. Remember your IME may not be the only source of
+ * changes on the text, and try to be as conservative as possible in
+ * the data you send and as liberal as possible in the data you
+ * receive.</p>
+ *
+ * <p>If you are implementing your own editor, you will probably need
+ * to provide your own subclass of {@link BaseInputConnection} to
+ * answer to the commands from IMEs. Please be sure to test your
+ * editor with as many IMEs as you can as their behavior can vary a
+ * lot. Also be sure to test with various languages, including CJK
+ * languages and right-to-left languages like Arabic, as these may
+ * have different input requirements. When in doubt about the
+ * behavior you should adopt for a particular call, please mimic the
+ * default TextView implementation in the latest Android version, and
+ * if you decide to drift from it, please consider carefully that
+ * inconsistencies in text edition behavior is almost universally felt
+ * as a bad thing by users.</p>
+ *
+ * <h3>Cursors, selections and compositions</h3>
+ * <p>In Android, the cursor and the selection are one and the same
+ * thing. A "cursor" is just the special case of a zero-sized
+ * selection. As such, this documentation uses them
+ * interchangeably. Any method acting "before the cursor" would act
+ * before the start of the selection if there is one, and any method
+ * acting "after the cursor" would act after the end of the
+ * selection.</p>
+ *
+ * <p>An editor needs to be able to keep track of a currently
+ * "composing" region, like the standard edition widgets do. The
+ * composition is marked in a specific style: see
+ * {@link android.text.Spanned#SPAN_COMPOSING}. IMEs use this to help
+ * the user keep track of what part of the text they are currently
+ * focusing on, and interact with the editor using
+ * {@link InputConnection#setComposingText(CharSequence, int)},
+ * {@link InputConnection#setComposingRegion(int, int)} and
+ * {@link InputConnection#finishComposingText()}.
+ * The composing region and the selection are completely independent
+ * of each other, and the IME may use them however they see fit.</p>
*/
public interface InputConnection {
/**
* Flag for use with {@link #getTextAfterCursor} and
- * {@link #getTextBeforeCursor} to have style information returned along
- * with the text. If not set, you will receive only the raw text. If
- * set, you may receive a complex CharSequence of both text and style
- * spans.
+ * {@link #getTextBeforeCursor} to have style information returned
+ * along with the text. If not set, {@link #getTextAfterCursor}
+ * sends only the raw text, without style or other spans. If set,
+ * it may return a complex CharSequence of both text and style
+ * spans. <strong>Editor authors</strong>: you should strive to
+ * send text with styles if possible, but it is not required.
*/
static final int GET_TEXT_WITH_STYLES = 0x0001;
-
+
/**
- * Flag for use with {@link #getExtractedText} to indicate you would
- * like to receive updates when the extracted text changes.
+ * Flag for use with {@link #getExtractedText} to indicate you
+ * would like to receive updates when the extracted text changes.
*/
public static final int GET_EXTRACTED_TEXT_MONITOR = 0x0001;
-
+
/**
- * Get <var>n</var> characters of text before the current cursor position.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a null is returned.
- *
+ * Get <var>n</var> characters of text before the current cursor
+ * position.
+ *
+ * <p>This method may fail either if the input connection has
+ * become invalid (such as its process crashing) or the editor is
+ * taking too long to respond with the text (it is given a couple
+ * seconds to return). In either case, null is returned. This
+ * method does not affect the text in the editor in any way, nor
+ * does it affect the selection or composing spans.</p>
+ *
+ * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the
+ * editor should return a {@link android.text.SpannableString}
+ * with all the spans set on the text.</p>
+ *
+ * <p><strong>IME authors:</strong> please consider this will
+ * trigger an IPC round-trip that will take some time. Assume this
+ * method consumes a lot of time. Also, please keep in mind the
+ * Editor may choose to return less characters than requested even
+ * if they are available for performance reasons.</p>
+ *
+ * <p><strong>Editor authors:</strong> please be careful of race
+ * conditions in implementing this call. An IME can make a change
+ * to the text and use this method right away; you need to make
+ * sure the returned value is consistent with the result of the
+ * latest edits.
+ *
* @param n The expected length of the text.
* @param flags Supplies additional options controlling how the text is
- * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
- *
- * @return Returns the text before the cursor position; the length of the
+ * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
+ * @return the text before the cursor position; the length of the
* returned text might be less than <var>n</var>.
*/
public CharSequence getTextBeforeCursor(int n, int flags);
/**
- * Get <var>n</var> characters of text after the current cursor position.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a null is returned.
- *
+ * Get <var>n</var> characters of text after the current cursor
+ * position.
+ *
+ * <p>This method may fail either if the input connection has
+ * become invalid (such as its process crashing) or the client is
+ * taking too long to respond with the text (it is given a couple
+ * seconds to return). In either case, null is returned.
+ *
+ * <p>This method does not affect the text in the editor in any
+ * way, nor does it affect the selection or composing spans.</p>
+ *
+ * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the
+ * editor should return a {@link android.text.SpannableString}
+ * with all the spans set on the text.</p>
+ *
+ * <p><strong>IME authors:</strong> please consider this will
+ * trigger an IPC round-trip that will take some time. Assume this
+ * method consumes a lot of time.</p>
+ *
+ * <p><strong>Editor authors:</strong> please be careful of race
+ * conditions in implementing this call. An IME can make a change
+ * to the text and use this method right away; you need to make
+ * sure the returned value is consistent with the result of the
+ * latest edits.</p>
+ *
* @param n The expected length of the text.
* @param flags Supplies additional options controlling how the text is
- * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
- *
- * @return Returns the text after the cursor position; the length of the
+ * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
+ *
+ * @return the text after the cursor position; the length of the
* returned text might be less than <var>n</var>.
*/
public CharSequence getTextAfterCursor(int n, int flags);
@@ -83,139 +190,287 @@
/**
* Gets the selected text, if any.
*
- * <p>This method may fail if either the input connection has become
- * invalid (such as its process crashing) or the client is taking too
- * long to respond with the text (it is given a couple of seconds to return).
- * In either case, a null is returned.
+ * <p>This method may fail if either the input connection has
+ * become invalid (such as its process crashing) or the client is
+ * taking too long to respond with the text (it is given a couple
+ * of seconds to return). In either case, null is returned.</p>
+ *
+ * <p>This method must not cause any changes in the editor's
+ * state.</p>
+ *
+ * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the
+ * editor should return a {@link android.text.SpannableString}
+ * with all the spans set on the text.</p>
+ *
+ * <p><strong>IME authors:</strong> please consider this will
+ * trigger an IPC round-trip that will take some time. Assume this
+ * method consumes a lot of time.</p>
+ *
+ * <p><strong>Editor authors:</strong> please be careful of race
+ * conditions in implementing this call. An IME can make a change
+ * to the text or change the selection position and use this
+ * method right away; you need to make sure the returned value is
+ * consistent with the results of the latest edits.</p>
*
* @param flags Supplies additional options controlling how the text is
- * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
- * @return Returns the text that is currently selected, if any, or null if
+ * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
+ * @return the text that is currently selected, if any, or null if
* no text is selected.
*/
public CharSequence getSelectedText(int flags);
/**
- * Retrieve the current capitalization mode in effect at the current
- * cursor position in the text. See
- * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode} for
- * more information.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a 0 is returned.
- *
+ * Retrieve the current capitalization mode in effect at the
+ * current cursor position in the text. See
+ * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}
+ * for more information.
+ *
+ * <p>This method may fail either if the input connection has
+ * become invalid (such as its process crashing) or the client is
+ * taking too long to respond with the text (it is given a couple
+ * seconds to return). In either case, 0 is returned.</p>
+ *
+ * <p>This method does not affect the text in the editor in any
+ * way, nor does it affect the selection or composing spans.</p>
+ *
+ * <p><strong>Editor authors:</strong> please be careful of race
+ * conditions in implementing this call. An IME can change the
+ * cursor position and use this method right away; you need to make
+ * sure the returned value is consistent with the results of the
+ * latest edits and changes to the cursor position.</p>
+ *
* @param reqModes The desired modes to retrieve, as defined by
- * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}. These
+ * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}. These
* constants are defined so that you can simply pass the current
* {@link EditorInfo#inputType TextBoxAttribute.contentType} value
* directly in to here.
- *
- * @return Returns the caps mode flags that are in effect.
+ * @return the caps mode flags that are in effect at the current
+ * cursor position. See TYPE_TEXT_FLAG_CAPS_* in {@link android.text.InputType}.
*/
public int getCursorCapsMode(int reqModes);
-
+
/**
- * Retrieve the current text in the input connection's editor, and monitor
- * for any changes to it. This function returns with the current text,
- * and optionally the input connection can send updates to the
- * input method when its text changes.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a null is returned.
- *
+ * Retrieve the current text in the input connection's editor, and
+ * monitor for any changes to it. This function returns with the
+ * current text, and optionally the input connection can send
+ * updates to the input method when its text changes.
+ *
+ * <p>This method may fail either if the input connection has
+ * become invalid (such as its process crashing) or the client is
+ * taking too long to respond with the text (it is given a couple
+ * seconds to return). In either case, null is returned.</p>
+ *
+ * <p>Editor authors: as a general rule, try to comply with the
+ * fields in <code>request</code> for how many chars to return,
+ * but if performance or convenience dictates otherwise, please
+ * feel free to do what is most appropriate for your case. Also,
+ * if the
+ * {@link #GET_EXTRACTED_TEXT_MONITOR} flag is set, you should be
+ * calling
+ * {@link InputMethodManager#updateExtractedText(View, int, ExtractedText)}
+ * whenever you call
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)}.</p>
+ *
* @param request Description of how the text should be returned.
+ * {@link android.view.inputmethod.ExtractedTextRequest}
* @param flags Additional options to control the client, either 0 or
* {@link #GET_EXTRACTED_TEXT_MONITOR}.
- *
- * @return Returns an ExtractedText object describing the state of the
- * text view and containing the extracted text itself.
+
+ * @return an {@link android.view.inputmethod.ExtractedText}
+ * object describing the state of the text view and containing the
+ * extracted text itself, or null if the input connection is no
+ * longer valid of the editor can't comply with the request for
+ * some reason.
*/
public ExtractedText getExtractedText(ExtractedTextRequest request,
int flags);
/**
- * Delete <var>beforeLength</var> characters of text before the current cursor
- * position, and delete <var>afterLength</var> characters of text after the
- * current cursor position, excluding composing text. Before and after refer
- * to the order of the characters in the string, not to their visual representation.
- *
+ * Delete <var>beforeLength</var> characters of text before the
+ * current cursor position, and delete <var>afterLength</var>
+ * characters of text after the current cursor position, excluding
+ * the selection. Before and after refer to the order of the
+ * characters in the string, not to their visual representation:
+ * this means you don't have to figure out the direction of the
+ * text and can just use the indices as-is.
+ *
+ * <p>The lengths are supplied in Java chars, not in code points
+ * or in glyphs.</p>
+ *
+ * <p>Since this method only operates on text before and after the
+ * selection, it can't affect the contents of the selection. This
+ * may affect the composing span if the span includes characters
+ * that are to be deleted, but otherwise will not change it. If
+ * some characters in the composing span are deleted, the
+ * composing span will persist but get shortened by however many
+ * chars inside it have been removed.</p>
+ *
+ * <p><strong>IME authors:</strong> please be careful not to
+ * delete only half of a surrogate pair. Also take care not to
+ * delete more characters than are in the editor, as that may have
+ * ill effects on the application. Calling this method will cause
+ * the editor to call
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * on your service after the batch input is over.</p>
+ *
+ * <p><strong>Editor authors:</strong> please be careful of race
+ * conditions in implementing this call. An IME can make a change
+ * to the text or change the selection position and use this
+ * method right away; you need to make sure the effects are
+ * consistent with the results of the latest edits. Also, although
+ * the IME should not send lengths bigger than the contents of the
+ * string, you should check the values for overflows and trim the
+ * indices to the size of the contents to avoid crashes. Since
+ * this changes the contents of the editor, you need to make the
+ * changes known to the input method by calling
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+ * but be careful to wait until the batch edit is over if one is
+ * in progress.</p>
*
* @param beforeLength The number of characters to be deleted before the
* current cursor position.
* @param afterLength The number of characters to be deleted after the
* current cursor position.
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean deleteSurroundingText(int beforeLength, int afterLength);
/**
- * Set composing text around the current cursor position with the given text,
- * and set the new cursor position. Any composing text set previously will
- * be removed automatically.
- *
+ * Set composing text around the current cursor position with the
+ * given text, and set the new cursor position. Any composing text
+ * set previously will be removed automatically.
+ *
+ * <p>If there is any composing span currently active, all
+ * characters that it comprises are removed. The passed text is
+ * added in its place, and a composing span is added to this
+ * text. Finally, the cursor is moved to the location specified by
+ * <code>newCursorPosition</code>.</p>
+ *
+ * <p>This is usually called by IMEs to add or remove or change
+ * characters in the composing span. Calling this method will
+ * cause the editor to call
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * on the current IME after the batch input is over.</p>
+ *
+ * <p><strong>Editor authors:</strong> please keep in mind the
+ * text may be very similar or completely different than what was
+ * in the composing span at call time, or there may not be a
+ * composing span at all. Please note that although it's not
+ * typical use, the string may be empty. Treat this normally,
+ * replacing the currently composing text with an empty string.
+ * Also, be careful with the cursor position. IMEs rely on this
+ * working exactly as described above. Since this changes the
+ * contents of the editor, you need to make the changes known to
+ * the input method by calling
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+ * but be careful to wait until the batch edit is over if one is
+ * in progress. Note that this method can set the cursor position
+ * on either edge of the composing text or entirely outside it,
+ * but the IME may also go on to move the cursor position to
+ * within the composing text in a subsequent call so you should
+ * make no assumption at all: the composing text and the selection
+ * are entirely independent.</p>
+ *
* @param text The composing text with styles if necessary. If no style
* object attached to the text, the default style for composing text
- * is used. See {#link android.text.Spanned} for how to attach style
- * object to the text. {#link android.text.SpannableString} and
- * {#link android.text.SpannableStringBuilder} are two
- * implementations of the interface {#link android.text.Spanned}.
- * @param newCursorPosition The new cursor position around the text. If
+ * is used. See {@link android.text.Spanned} for how to attach style
+ * object to the text. {@link android.text.SpannableString} and
+ * {@link android.text.SpannableStringBuilder} are two
+ * implementations of the interface {@link android.text.Spanned}.
+ * @param newCursorPosition The new cursor position around the text. If
* > 0, this is relative to the end of the text - 1; if <= 0, this
- * is relative to the start of the text. So a value of 1 will
+ * is relative to the start of the text. So a value of 1 will
* always advance you to the position after the full text being
- * inserted. Note that this means you can't position the cursor
+ * inserted. Note that this means you can't position the cursor
* within the text, because the editor can make modifications to
* the text you are providing so it is not possible to correctly
* specify locations there.
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean setComposingText(CharSequence text, int newCursorPosition);
/**
- * Mark a certain region of text as composing text. Any composing text set
- * previously will be removed automatically. The default style for composing
- * text is used.
+ * Mark a certain region of text as composing text. If there was a
+ * composing region, the characters are left as they were and the
+ * composing span removed, as if {@link #finishComposingText()}
+ * has been called. The default style for composing text is used.
+ *
+ * <p>The passed indices are clipped to the contents bounds. If
+ * the resulting region is zero-sized, no region is marked and the
+ * effect is the same as that of calling {@link #finishComposingText()}.
+ * The order of start and end is not important. In effect, the
+ * region from start to end and the region from end to start is
+ * the same. Editor authors, be ready to accept a start that is
+ * greater than end.</p>
+ *
+ * <p>Since this does not change the contents of the text, editors should not call
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)} and
+ * IMEs should not receive
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}.
+ * </p>
+ *
+ * <p>This has no impact on the cursor/selection position. It may
+ * result in the cursor being anywhere inside or outside the
+ * composing region, including cases where the selection and the
+ * composing region overlap partially or entirely.</p>
*
* @param start the position in the text at which the composing region begins
* @param end the position in the text at which the composing region ends
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean setComposingRegion(int start, int end);
/**
- * Have the text editor finish whatever composing text is currently
- * active. This simply leaves the text as-is, removing any special
- * composing styling or other state that was around it. The cursor
- * position remains unchanged.
+ * Have the text editor finish whatever composing text is
+ * currently active. This simply leaves the text as-is, removing
+ * any special composing styling or other state that was around
+ * it. The cursor position remains unchanged.
+ *
+ * <p><strong>IME authors:</strong> be aware that this call may be
+ * expensive with some editors.</p>
+ *
+ * <p><strong>Editor authors:</strong> please note that the cursor
+ * may be anywhere in the contents when this is called, including
+ * in the middle of the composing span or in a completely
+ * unrelated place. It must not move.</p>
+ *
+ * @return true on success, false if the input connection
+ * is no longer valid.
*/
public boolean finishComposingText();
-
+
/**
* Commit text to the text box and set the new cursor position.
- * Any composing text set previously will be removed
- * automatically.
- *
- * @param text The committed text.
- * @param newCursorPosition The new cursor position around the text. If
+ *
+ * <p>This method removes the contents of the currently composing
+ * text and replaces it with the passed CharSequence, and then
+ * moves the cursor according to {@code newCursorPosition}.
+ * This behaves like calling
+ * {@link #setComposingText(CharSequence, int) setComposingText(text, newCursorPosition)}
+ * then {@link #finishComposingText()}.</p>
+ *
+ * <p>Calling this method will cause the editor to call
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * on the current IME after the batch input is over.
+ * <strong>Editor authors</strong>, for this to happen you need to
+ * make the changes known to the input method by calling
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+ * but be careful to wait until the batch edit is over if one is
+ * in progress.</p>
+ *
+ * @param text The committed text. This may include styles.
+ * @param newCursorPosition The new cursor position around the text. If
* > 0, this is relative to the end of the text - 1; if <= 0, this
- * is relative to the start of the text. So a value of 1 will
+ * is relative to the start of the text. So a value of 1 will
* always advance you to the position after the full text being
- * inserted. Note that this means you can't position the cursor
+ * inserted. Note that this means you can't position the cursor
* within the text, because the editor can make modifications to
* the text you are providing so it is not possible to correctly
* specify locations there.
- *
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean commitText(CharSequence text, int newCursorPosition);
@@ -223,49 +478,102 @@
/**
* Commit a completion the user has selected from the possible ones
* previously reported to {@link InputMethodSession#displayCompletions
- * InputMethodSession.displayCompletions()}. This will result in the
- * same behavior as if the user had selected the completion from the
- * actual UI.
- *
+ * InputMethodSession#displayCompletions(CompletionInfo[])} or
+ * {@link InputMethodManager#displayCompletions
+ * InputMethodManager#displayCompletions(View, CompletionInfo[])}.
+ * This will result in the same behavior as if the user had
+ * selected the completion from the actual UI. In all other
+ * respects, this behaves like {@link #commitText(CharSequence, int)}.
+ *
+ * <p><strong>IME authors:</strong> please take care to send the
+ * same object that you received through
+ * {@link android.inputmethodservice.InputMethodService#onDisplayCompletions(CompletionInfo[])}.
+ * </p>
+ *
+ * <p><strong>Editor authors:</strong> if you never call
+ * {@link InputMethodSession#displayCompletions(CompletionInfo[])} or
+ * {@link InputMethodManager#displayCompletions(View, CompletionInfo[])} then
+ * a well-behaved IME should never call this on your input
+ * connection, but be ready to deal with misbehaving IMEs without
+ * crashing.</p>
+ *
+ * <p>Calling this method (with a valid {@link CompletionInfo} object)
+ * will cause the editor to call
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * on the current IME after the batch input is over.
+ * <strong>Editor authors</strong>, for this to happen you need to
+ * make the changes known to the input method by calling
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+ * but be careful to wait until the batch edit is over if one is
+ * in progress.</p>
+ *
* @param text The committed completion.
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean commitCompletion(CompletionInfo text);
/**
- * Commit a correction automatically performed on the raw user's input. A typical example would
- * be to correct typos using a dictionary.
+ * Commit a correction automatically performed on the raw user's input. A
+ * typical example would be to correct typos using a dictionary.
+ *
+ * <p>Calling this method will cause the editor to call
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * on the current IME after the batch input is over.
+ * <strong>Editor authors</strong>, for this to happen you need to
+ * make the changes known to the input method by calling
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+ * but be careful to wait until the batch edit is over if one is
+ * in progress.</p>
*
* @param correctionInfo Detailed information about the correction.
- *
- * @return True on success, false if the input connection is no longer valid.
+ * @return true on success, false if the input connection is no longer valid.
*/
public boolean commitCorrection(CorrectionInfo correctionInfo);
/**
- * Set the selection of the text editor. To set the cursor position,
- * start and end should have the same value.
- * @return Returns true on success, false if the input connection is no longer
+ * Set the selection of the text editor. To set the cursor
+ * position, start and end should have the same value.
+ *
+ * <p>Since this moves the cursor, calling this method will cause
+ * the editor to call
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * on the current IME after the batch input is over.
+ * <strong>Editor authors</strong>, for this to happen you need to
+ * make the changes known to the input method by calling
+ * {@link InputMethodManager#updateSelection(View, int, int, int, int)},
+ * but be careful to wait until the batch edit is over if one is
+ * in progress.</p>
+ *
+ * <p>This has no effect on the composing region which must stay
+ * unchanged. The order of start and end is not important. In
+ * effect, the region from start to end and the region from end to
+ * start is the same. Editor authors, be ready to accept a start
+ * that is greater than end.</p>
+ *
+ * @param start the character index where the selection should start.
+ * @param end the character index where the selection should end.
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean setSelection(int start, int end);
-
+
/**
* Have the editor perform an action it has said it can do.
- *
+ *
+ * <p>This is typically used by IMEs when the user presses the key
+ * associated with the action.</p>
+ *
* @param editorAction This must be one of the action constants for
* {@link EditorInfo#imeOptions EditorInfo.editorType}, such as
* {@link EditorInfo#IME_ACTION_GO EditorInfo.EDITOR_ACTION_GO}.
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean performEditorAction(int editorAction);
-
+
/**
- * Perform a context menu action on the field. The given id may be one of:
+ * Perform a context menu action on the field. The given id may be one of:
* {@link android.R.id#selectAll},
* {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
* {@link android.R.id#cut}, {@link android.R.id#copy},
@@ -273,50 +581,82 @@
* or {@link android.R.id#switchInputMethod}
*/
public boolean performContextMenuAction(int id);
-
+
/**
- * Tell the editor that you are starting a batch of editor operations.
- * The editor will try to avoid sending you updates about its state
- * until {@link #endBatchEdit} is called.
+ * Tell the editor that you are starting a batch of editor
+ * operations. The editor will try to avoid sending you updates
+ * about its state until {@link #endBatchEdit} is called. Batch
+ * edits nest.
+ *
+ * <p><strong>IME authors:</strong> use this to avoid getting
+ * calls to
+ * {@link android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int, int, int)}
+ * corresponding to intermediate state. Also, use this to avoid
+ * flickers that may arise from displaying intermediate state. Be
+ * sure to call {@link #endBatchEdit} for each call to this, or
+ * you may block updates in the editor.</p>
+ *
+ * <p><strong>Editor authors:</strong> while a batch edit is in
+ * progress, take care not to send updates to the input method and
+ * not to update the display. IMEs use this intensively to this
+ * effect. Also please note that batch edits need to nest
+ * correctly.</p>
+ *
+ * @return true if a batch edit is now in progress, false otherwise. Since
+ * this method starts a batch edit, that means it will always return true
+ * unless the input connection is no longer valid.
*/
public boolean beginBatchEdit();
-
+
/**
* Tell the editor that you are done with a batch edit previously
- * initiated with {@link #beginBatchEdit}.
+ * initiated with {@link #beginBatchEdit}. This ends the latest
+ * batch only.
+ *
+ * <p><strong>IME authors:</strong> make sure you call this
+ * exactly once for each call to {@link #beginBatchEdit}.</p>
+ *
+ * <p><strong>Editor authors:</strong> please be careful about
+ * batch edit nesting. Updates still to be held back until the end
+ * of the last batch edit.</p>
+ *
+ * @return true if there is still a batch edit in progress after closing
+ * the latest one (in other words, if the nesting count is > 0), false
+ * otherwise or if the input connection is no longer valid.
*/
public boolean endBatchEdit();
-
+
/**
- * Send a key event to the process that is currently attached through
- * this input connection. The event will be dispatched like a normal
- * key event, to the currently focused; this generally is the view that
- * is providing this InputConnection, but due to the asynchronous nature
- * of this protocol that can not be guaranteed and the focus may have
- * changed by the time the event is received.
- *
- * <p>
- * This method can be used to send key events to the application. For
- * example, an on-screen keyboard may use this method to simulate a hardware
- * keyboard. There are three types of standard keyboards, numeric (12-key),
- * predictive (20-key) and ALPHA (QWERTY). You can specify the keyboard type
- * by specify the device id of the key event.
- *
- * <p>
- * You will usually want to set the flag
- * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD} on all
- * key event objects you give to this API; the flag will not be set
- * for you.
+ * Send a key event to the process that is currently attached
+ * through this input connection. The event will be dispatched
+ * like a normal key event, to the currently focused view; this
+ * generally is the view that is providing this InputConnection,
+ * but due to the asynchronous nature of this protocol that can
+ * not be guaranteed and the focus may have changed by the time
+ * the event is received.
*
- * <p>Note that it's discouraged to send such key events in normal operation;
- * this is mainly for use with {@link android.text.InputType#TYPE_NULL} type
- * text fields. Use the {@link #commitText} family of methods to send text
- * to the application instead.
+ * <p>This method can be used to send key events to the
+ * application. For example, an on-screen keyboard may use this
+ * method to simulate a hardware keyboard. There are three types
+ * of standard keyboards, numeric (12-key), predictive (20-key)
+ * and ALPHA (QWERTY). You can specify the keyboard type by
+ * specify the device id of the key event.</p>
+ *
+ * <p>You will usually want to set the flag
+ * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD}
+ * on all key event objects you give to this API; the flag will
+ * not be set for you.</p>
+ *
+ * <p>Note that it's discouraged to send such key events in normal
+ * operation; this is mainly for use with
+ * {@link android.text.InputType#TYPE_NULL} type text fields. Use
+ * the {@link #commitText} family of methods to send text to the
+ * application instead.</p>
+ *
* @param event The key event.
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
- *
+ *
* @see KeyEvent
* @see KeyCharacterMap#NUMERIC
* @see KeyCharacterMap#PREDICTIVE
@@ -325,37 +665,46 @@
public boolean sendKeyEvent(KeyEvent event);
/**
- * Clear the given meta key pressed states in the given input connection.
- *
+ * Clear the given meta key pressed states in the given input
+ * connection.
+ *
+ * <p>This can be used by the IME to clear the meta key states set
+ * by a hardware keyboard with latched meta keys, if the editor
+ * keeps track of these.</p>
+ *
* @param states The states to be cleared, may be one or more bits as
* per {@link KeyEvent#getMetaState() KeyEvent.getMetaState()}.
- *
- * @return Returns true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer
* valid.
*/
public boolean clearMetaKeyStates(int states);
-
+
/**
- * Called by the IME to tell the client when it switches between fullscreen
- * and normal modes. This will normally be called for you by the standard
- * implementation of {@link android.inputmethodservice.InputMethodService}.
+ * Called by the IME to tell the client when it switches between
+ * fullscreen and normal modes. This will normally be called for
+ * you by the standard implementation of
+ * {@link android.inputmethodservice.InputMethodService}.
+ *
+ * @return true on success, false if the input connection is no longer
+ * valid.
*/
public boolean reportFullscreenMode(boolean enabled);
-
+
/**
- * API to send private commands from an input method to its connected
- * editor. This can be used to provide domain-specific features that are
- * only known between certain input methods and their clients. Note that
- * because the InputConnection protocol is asynchronous, you have no way
- * to get a result back or know if the client understood the command; you
- * can use the information in {@link EditorInfo} to determine if
- * a client supports a particular command.
- *
- * @param action Name of the command to be performed. This <em>must</em>
+ * API to send private commands from an input method to its
+ * connected editor. This can be used to provide domain-specific
+ * features that are only known between certain input methods and
+ * their clients. Note that because the InputConnection protocol
+ * is asynchronous, you have no way to get a result back or know
+ * if the client understood the command; you can use the
+ * information in {@link EditorInfo} to determine if a client
+ * supports a particular command.
+ *
+ * @param action Name of the command to be performed. This <em>must</em>
* be a scoped name, i.e. prefixed with a package name you own, so that
* different developers will not create conflicting commands.
* @param data Any data to include with the command.
- * @return Returns true if the command was sent (whether or not the
+ * @return true if the command was sent (whether or not the
* associated editor understood it), false if the input connection is no longer
* valid.
*/
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 8ae0021..19492c2 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -500,6 +500,12 @@
* Sets the default zoom density of the page. This must be called from the UI
* thread. The default is {@link ZoomDensity#MEDIUM}.
*
+ * This setting is not recommended for use in new applications. If the WebView
+ * is utilized to display mobile-oriented pages, the desired effect can be achieved by
+ * adjusting 'width' and 'initial-scale' attributes of page's 'meta viewport'
+ * tag. For pages lacking the tag, {@link android.webkit.WebView#setInitialScale}
+ * and {@link #setUseWideViewPort} can be used.
+ *
* @param zoom the zoom density
*/
public void setDefaultZoom(ZoomDensity zoom) {
@@ -510,6 +516,8 @@
* Gets the default zoom density of the page. This should be called from
* the UI thread.
*
+ * This setting is not recommended for use in new applications.
+ *
* @return the zoom density
* @see #setDefaultZoom
*/
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4c0ccca..ba85c1a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1615,10 +1615,12 @@
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
+ @Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
+ @Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
@@ -1943,8 +1945,8 @@
}
final int top = getChildAt(0).getTop();
- final float fadeLength = (float) getVerticalFadingEdgeLength();
- return top < mPaddingTop ? (float) -(top - mPaddingTop) / fadeLength : fadeEdge;
+ final float fadeLength = getVerticalFadingEdgeLength();
+ return top < mPaddingTop ? -(top - mPaddingTop) / fadeLength : fadeEdge;
}
}
@@ -1961,9 +1963,9 @@
final int bottom = getChildAt(count - 1).getBottom();
final int height = getHeight();
- final float fadeLength = (float) getVerticalFadingEdgeLength();
+ final float fadeLength = getVerticalFadingEdgeLength();
return bottom > height - mPaddingBottom ?
- (float) (bottom - height + mPaddingBottom) / fadeLength : fadeEdge;
+ (bottom - height + mPaddingBottom) / fadeLength : fadeEdge;
}
}
@@ -2771,6 +2773,7 @@
private class PerformClick extends WindowRunnnable implements Runnable {
int mClickMotionPosition;
+ @Override
public void run() {
// The data has changed since we posted this action in the event queue,
// bail out before bad things happen
@@ -2792,6 +2795,7 @@
}
private class CheckForLongPress extends WindowRunnnable implements Runnable {
+ @Override
public void run() {
final int motionPosition = mMotionPosition;
final View child = getChildAt(motionPosition - mFirstPosition);
@@ -2815,6 +2819,7 @@
}
private class CheckForKeyLongPress extends WindowRunnnable implements Runnable {
+ @Override
public void run() {
if (isPressed() && mSelectedPosition >= 0) {
int index = mSelectedPosition - mFirstPosition;
@@ -2989,6 +2994,7 @@
}
final class CheckForTap implements Runnable {
+ @Override
public void run() {
if (mTouchMode == TOUCH_MODE_DOWN) {
mTouchMode = TOUCH_MODE_TAP;
@@ -3239,6 +3245,7 @@
}
}
+ @Override
public void onTouchModeChanged(boolean isInTouchMode) {
if (isInTouchMode) {
// Get rid of the selection when we enter touch mode
@@ -3299,95 +3306,153 @@
}
}
- final int action = ev.getAction();
-
- View v;
-
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
- switch (mTouchMode) {
- case TOUCH_MODE_OVERFLING: {
- mFlingRunnable.endFling();
- if (mPositionScroller != null) {
- mPositionScroller.stop();
- }
- mTouchMode = TOUCH_MODE_OVERSCROLL;
- mMotionX = (int) ev.getX();
- mMotionY = mLastY = (int) ev.getY();
- mMotionCorrection = 0;
- mActivePointerId = ev.getPointerId(0);
- mDirection = 0;
+ final int actionMasked = ev.getActionMasked();
+ switch (actionMasked) {
+ case MotionEvent.ACTION_DOWN: {
+ onTouchDown(ev);
break;
}
- default: {
- mActivePointerId = ev.getPointerId(0);
- final int x = (int) ev.getX();
- final int y = (int) ev.getY();
- int motionPosition = pointToPosition(x, y);
- if (!mDataChanged) {
- if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
- && (getAdapter().isEnabled(motionPosition))) {
- // User clicked on an actual view (and was not stopping a fling).
- // It might be a click or a scroll. Assume it is a click until
- // proven otherwise
- mTouchMode = TOUCH_MODE_DOWN;
- // FIXME Debounce
- if (mPendingCheckForTap == null) {
- mPendingCheckForTap = new CheckForTap();
- }
- postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
- } else {
- if (mTouchMode == TOUCH_MODE_FLING) {
- // Stopped a fling. It is a scroll.
- createScrollingCache();
- mTouchMode = TOUCH_MODE_SCROLL;
- mMotionCorrection = 0;
- motionPosition = findMotionRow(y);
- mFlingRunnable.flywheelTouch();
- }
- }
- }
+ case MotionEvent.ACTION_MOVE: {
+ onTouchMove(ev);
+ break;
+ }
+ case MotionEvent.ACTION_UP: {
+ onTouchUp(ev);
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL: {
+ onTouchCancel();
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ onSecondaryPointerUp(ev);
+ final int x = mMotionX;
+ final int y = mMotionY;
+ final int motionPosition = pointToPosition(x, y);
if (motionPosition >= 0) {
// Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
+ final View child = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = child.getTop();
+ mMotionPosition = motionPosition;
}
- mMotionX = x;
- mMotionY = y;
- mMotionPosition = motionPosition;
- mLastY = Integer.MIN_VALUE;
+ mLastY = y;
break;
}
- }
- if (performButtonActionOnTouchDown(ev)) {
- if (mTouchMode == TOUCH_MODE_DOWN) {
- removeCallbacks(mPendingCheckForTap);
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ // New pointers take over dragging duties
+ final int index = ev.getActionIndex();
+ final int id = ev.getPointerId(index);
+ final int x = (int) ev.getX(index);
+ final int y = (int) ev.getY(index);
+ mMotionCorrection = 0;
+ mActivePointerId = id;
+ mMotionX = x;
+ mMotionY = y;
+ final int motionPosition = pointToPosition(x, y);
+ if (motionPosition >= 0) {
+ // Remember where the motion event started
+ final View child = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = child.getTop();
+ mMotionPosition = motionPosition;
}
+ mLastY = y;
+ break;
}
+ }
+
+ return true;
+ }
+
+ private void onTouchDown(MotionEvent ev) {
+ View v;
+ switch (mTouchMode) {
+ case TOUCH_MODE_OVERFLING: {
+ mFlingRunnable.endFling();
+ if (mPositionScroller != null) {
+ mPositionScroller.stop();
+ }
+ mTouchMode = TOUCH_MODE_OVERSCROLL;
+ mMotionX = (int) ev.getX();
+ mMotionY = mLastY = (int) ev.getY();
+ mMotionCorrection = 0;
+ mActivePointerId = ev.getPointerId(0);
+ mDirection = 0;
break;
}
- case MotionEvent.ACTION_MOVE: {
- int pointerIndex = ev.findPointerIndex(mActivePointerId);
- if (pointerIndex == -1) {
- pointerIndex = 0;
- mActivePointerId = ev.getPointerId(pointerIndex);
- }
- final int y = (int) ev.getY(pointerIndex);
-
- if (mDataChanged) {
- // Re-sync everything if data has been changed
- // since the scroll operation can query the adapter.
- layoutChildren();
+ default: {
+ mActivePointerId = ev.getPointerId(0);
+ final int x = (int) ev.getX();
+ final int y = (int) ev.getY();
+ int motionPosition = pointToPosition(x, y);
+ if (!mDataChanged) {
+ if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
+ && (getAdapter().isEnabled(motionPosition))) {
+ // User clicked on an actual view (and was not stopping a fling).
+ // It might be a click or a scroll. Assume it is a click until
+ // proven otherwise
+ mTouchMode = TOUCH_MODE_DOWN;
+ // FIXME Debounce
+ if (mPendingCheckForTap == null) {
+ mPendingCheckForTap = new CheckForTap();
+ }
+ postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
+ } else {
+ if (mTouchMode == TOUCH_MODE_FLING) {
+ // Stopped a fling. It is a scroll.
+ createScrollingCache();
+ mTouchMode = TOUCH_MODE_SCROLL;
+ mMotionCorrection = 0;
+ motionPosition = findMotionRow(y);
+ mFlingRunnable.flywheelTouch();
+ }
+ }
}
- switch (mTouchMode) {
+ if (motionPosition >= 0) {
+ // Remember where the motion event started
+ v = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = v.getTop();
+ }
+ mMotionX = x;
+ mMotionY = y;
+ mMotionPosition = motionPosition;
+ mLastY = Integer.MIN_VALUE;
+ break;
+ }
+ }
+
+ if (performButtonActionOnTouchDown(ev)) {
+ if (mTouchMode == TOUCH_MODE_DOWN) {
+ removeCallbacks(mPendingCheckForTap);
+ }
+ }
+ }
+
+ private void onTouchMove(MotionEvent ev) {
+ int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ if (pointerIndex == -1) {
+ pointerIndex = 0;
+ mActivePointerId = ev.getPointerId(pointerIndex);
+ }
+
+ if (mDataChanged) {
+ // Re-sync everything if data has been changed
+ // since the scroll operation can query the adapter.
+ layoutChildren();
+ }
+
+ final int y = (int) ev.getY(pointerIndex);
+
+ switch (mTouchMode) {
case TOUCH_MODE_DOWN:
case TOUCH_MODE_TAP:
case TOUCH_MODE_DONE_WAITING:
@@ -3399,162 +3464,205 @@
case TOUCH_MODE_OVERSCROLL:
scrollIfNeeded(y);
break;
+ }
+ }
+
+ private void onTouchUp(MotionEvent ev) {
+ switch (mTouchMode) {
+ case TOUCH_MODE_DOWN:
+ case TOUCH_MODE_TAP:
+ case TOUCH_MODE_DONE_WAITING:
+ final int motionPosition = mMotionPosition;
+ final View child = getChildAt(motionPosition - mFirstPosition);
+
+ final float x = ev.getX();
+ final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
+
+ if (child != null && !child.hasFocusable() && inList) {
+ if (mTouchMode != TOUCH_MODE_DOWN) {
+ child.setPressed(false);
+ }
+
+ if (mPerformClick == null) {
+ mPerformClick = new PerformClick();
+ }
+
+ final AbsListView.PerformClick performClick = mPerformClick;
+ performClick.mClickMotionPosition = motionPosition;
+ performClick.rememberWindowAttachCount();
+
+ mResurrectToPosition = motionPosition;
+
+ if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
+ final Handler handler = getHandler();
+ if (handler != null) {
+ handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
+ mPendingCheckForTap : mPendingCheckForLongPress);
+ }
+ mLayoutMode = LAYOUT_NORMAL;
+ if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
+ mTouchMode = TOUCH_MODE_TAP;
+ setSelectedPositionInt(mMotionPosition);
+ layoutChildren();
+ child.setPressed(true);
+ positionSelector(mMotionPosition, child);
+ setPressed(true);
+ if (mSelector != null) {
+ Drawable d = mSelector.getCurrent();
+ if (d != null && d instanceof TransitionDrawable) {
+ ((TransitionDrawable) d).resetTransition();
+ }
+ }
+ if (mTouchModeReset != null) {
+ removeCallbacks(mTouchModeReset);
+ }
+ mTouchModeReset = new Runnable() {
+ @Override
+ public void run() {
+ mTouchModeReset = null;
+ mTouchMode = TOUCH_MODE_REST;
+ child.setPressed(false);
+ setPressed(false);
+ if (!mDataChanged) {
+ performClick.run();
+ }
+ }
+ };
+ postDelayed(mTouchModeReset,
+ ViewConfiguration.getPressedStateDuration());
+ } else {
+ mTouchMode = TOUCH_MODE_REST;
+ updateSelectorState();
+ }
+ return;
+ } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
+ performClick.run();
+ }
}
+ mTouchMode = TOUCH_MODE_REST;
+ updateSelectorState();
+ break;
+ case TOUCH_MODE_SCROLL:
+ final int childCount = getChildCount();
+ if (childCount > 0) {
+ final int firstChildTop = getChildAt(0).getTop();
+ final int lastChildBottom = getChildAt(childCount - 1).getBottom();
+ final int contentTop = mListPadding.top;
+ final int contentBottom = getHeight() - mListPadding.bottom;
+ if (mFirstPosition == 0 && firstChildTop >= contentTop &&
+ mFirstPosition + childCount < mItemCount &&
+ lastChildBottom <= getHeight() - contentBottom) {
+ mTouchMode = TOUCH_MODE_REST;
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+ } else {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+
+ final int initialVelocity = (int)
+ (velocityTracker.getYVelocity(mActivePointerId) * mVelocityScale);
+ // Fling if we have enough velocity and we aren't at a boundary.
+ // Since we can potentially overfling more than we can overscroll, don't
+ // allow the weird behavior where you can scroll to a boundary then
+ // fling further.
+ if (Math.abs(initialVelocity) > mMinimumVelocity &&
+ !((mFirstPosition == 0 &&
+ firstChildTop == contentTop - mOverscrollDistance) ||
+ (mFirstPosition + childCount == mItemCount &&
+ lastChildBottom == contentBottom + mOverscrollDistance))) {
+ if (mFlingRunnable == null) {
+ mFlingRunnable = new FlingRunnable();
+ }
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+
+ mFlingRunnable.start(-initialVelocity);
+ } else {
+ mTouchMode = TOUCH_MODE_REST;
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+ if (mFlingRunnable != null) {
+ mFlingRunnable.endFling();
+ }
+ if (mPositionScroller != null) {
+ mPositionScroller.stop();
+ }
+ }
+ }
+ } else {
+ mTouchMode = TOUCH_MODE_REST;
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+ }
+ break;
+
+ case TOUCH_MODE_OVERSCROLL:
+ if (mFlingRunnable == null) {
+ mFlingRunnable = new FlingRunnable();
+ }
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+ if (Math.abs(initialVelocity) > mMinimumVelocity) {
+ mFlingRunnable.startOverfling(-initialVelocity);
+ } else {
+ mFlingRunnable.startSpringback();
+ }
+
break;
}
- case MotionEvent.ACTION_UP: {
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- case TOUCH_MODE_TAP:
- case TOUCH_MODE_DONE_WAITING:
- final int motionPosition = mMotionPosition;
- final View child = getChildAt(motionPosition - mFirstPosition);
+ setPressed(false);
- final float x = ev.getX();
- final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
+ if (mEdgeGlowTop != null) {
+ mEdgeGlowTop.onRelease();
+ mEdgeGlowBottom.onRelease();
+ }
- if (child != null && !child.hasFocusable() && inList) {
- if (mTouchMode != TOUCH_MODE_DOWN) {
- child.setPressed(false);
- }
+ // Need to redraw since we probably aren't drawing the selector anymore
+ invalidate();
- if (mPerformClick == null) {
- mPerformClick = new PerformClick();
- }
+ final Handler handler = getHandler();
+ if (handler != null) {
+ handler.removeCallbacks(mPendingCheckForLongPress);
+ }
- final AbsListView.PerformClick performClick = mPerformClick;
- performClick.mClickMotionPosition = motionPosition;
- performClick.rememberWindowAttachCount();
+ recycleVelocityTracker();
- mResurrectToPosition = motionPosition;
+ mActivePointerId = INVALID_POINTER;
- if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
- final Handler handler = getHandler();
- if (handler != null) {
- handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
- mPendingCheckForTap : mPendingCheckForLongPress);
- }
- mLayoutMode = LAYOUT_NORMAL;
- if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
- mTouchMode = TOUCH_MODE_TAP;
- setSelectedPositionInt(mMotionPosition);
- layoutChildren();
- child.setPressed(true);
- positionSelector(mMotionPosition, child);
- setPressed(true);
- if (mSelector != null) {
- Drawable d = mSelector.getCurrent();
- if (d != null && d instanceof TransitionDrawable) {
- ((TransitionDrawable) d).resetTransition();
- }
- }
- if (mTouchModeReset != null) {
- removeCallbacks(mTouchModeReset);
- }
- mTouchModeReset = new Runnable() {
- @Override
- public void run() {
- mTouchModeReset = null;
- mTouchMode = TOUCH_MODE_REST;
- child.setPressed(false);
- setPressed(false);
- if (!mDataChanged) {
- performClick.run();
- }
- }
- };
- postDelayed(mTouchModeReset,
- ViewConfiguration.getPressedStateDuration());
- } else {
- mTouchMode = TOUCH_MODE_REST;
- updateSelectorState();
- }
- return true;
- } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
- performClick.run();
- }
- }
- mTouchMode = TOUCH_MODE_REST;
- updateSelectorState();
- break;
- case TOUCH_MODE_SCROLL:
- final int childCount = getChildCount();
- if (childCount > 0) {
- final int firstChildTop = getChildAt(0).getTop();
- final int lastChildBottom = getChildAt(childCount - 1).getBottom();
- final int contentTop = mListPadding.top;
- final int contentBottom = getHeight() - mListPadding.bottom;
- if (mFirstPosition == 0 && firstChildTop >= contentTop &&
- mFirstPosition + childCount < mItemCount &&
- lastChildBottom <= getHeight() - contentBottom) {
- mTouchMode = TOUCH_MODE_REST;
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- } else {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-
- final int initialVelocity = (int)
- (velocityTracker.getYVelocity(mActivePointerId) * mVelocityScale);
- // Fling if we have enough velocity and we aren't at a boundary.
- // Since we can potentially overfling more than we can overscroll, don't
- // allow the weird behavior where you can scroll to a boundary then
- // fling further.
- if (Math.abs(initialVelocity) > mMinimumVelocity &&
- !((mFirstPosition == 0 &&
- firstChildTop == contentTop - mOverscrollDistance) ||
- (mFirstPosition + childCount == mItemCount &&
- lastChildBottom == contentBottom + mOverscrollDistance))) {
- if (mFlingRunnable == null) {
- mFlingRunnable = new FlingRunnable();
- }
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
-
- mFlingRunnable.start(-initialVelocity);
- } else {
- mTouchMode = TOUCH_MODE_REST;
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- if (mFlingRunnable != null) {
- mFlingRunnable.endFling();
- }
- if (mPositionScroller != null) {
- mPositionScroller.stop();
- }
- }
- }
- } else {
- mTouchMode = TOUCH_MODE_REST;
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- }
- break;
-
- case TOUCH_MODE_OVERSCROLL:
- if (mFlingRunnable == null) {
- mFlingRunnable = new FlingRunnable();
- }
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
- if (Math.abs(initialVelocity) > mMinimumVelocity) {
- mFlingRunnable.startOverfling(-initialVelocity);
- } else {
- mFlingRunnable.startSpringback();
- }
-
- break;
+ if (PROFILE_SCROLLING) {
+ if (mScrollProfilingStarted) {
+ Debug.stopMethodTracing();
+ mScrollProfilingStarted = false;
}
+ }
+ if (mScrollStrictSpan != null) {
+ mScrollStrictSpan.finish();
+ mScrollStrictSpan = null;
+ }
+ }
+
+ private void onTouchCancel() {
+ switch (mTouchMode) {
+ case TOUCH_MODE_OVERSCROLL:
+ if (mFlingRunnable == null) {
+ mFlingRunnable = new FlingRunnable();
+ }
+ mFlingRunnable.startSpringback();
+ break;
+
+ case TOUCH_MODE_OVERFLING:
+ // Do nothing - let it play out.
+ break;
+
+ default:
+ mTouchMode = TOUCH_MODE_REST;
setPressed(false);
-
- if (mEdgeGlowTop != null) {
- mEdgeGlowTop.onRelease();
- mEdgeGlowBottom.onRelease();
+ View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+ if (motionView != null) {
+ motionView.setPressed(false);
}
-
- // Need to redraw since we probably aren't drawing the selector anymore
- invalidate();
+ clearScrollingCache();
final Handler handler = getHandler();
if (handler != null) {
@@ -3562,99 +3670,13 @@
}
recycleVelocityTracker();
-
- mActivePointerId = INVALID_POINTER;
-
- if (PROFILE_SCROLLING) {
- if (mScrollProfilingStarted) {
- Debug.stopMethodTracing();
- mScrollProfilingStarted = false;
- }
- }
-
- if (mScrollStrictSpan != null) {
- mScrollStrictSpan.finish();
- mScrollStrictSpan = null;
- }
- break;
}
- case MotionEvent.ACTION_CANCEL: {
- switch (mTouchMode) {
- case TOUCH_MODE_OVERSCROLL:
- if (mFlingRunnable == null) {
- mFlingRunnable = new FlingRunnable();
- }
- mFlingRunnable.startSpringback();
- break;
-
- case TOUCH_MODE_OVERFLING:
- // Do nothing - let it play out.
- break;
-
- default:
- mTouchMode = TOUCH_MODE_REST;
- setPressed(false);
- View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- motionView.setPressed(false);
- }
- clearScrollingCache();
-
- final Handler handler = getHandler();
- if (handler != null) {
- handler.removeCallbacks(mPendingCheckForLongPress);
- }
-
- recycleVelocityTracker();
- }
-
- if (mEdgeGlowTop != null) {
- mEdgeGlowTop.onRelease();
- mEdgeGlowBottom.onRelease();
- }
- mActivePointerId = INVALID_POINTER;
- break;
+ if (mEdgeGlowTop != null) {
+ mEdgeGlowTop.onRelease();
+ mEdgeGlowBottom.onRelease();
}
-
- case MotionEvent.ACTION_POINTER_UP: {
- onSecondaryPointerUp(ev);
- final int x = mMotionX;
- final int y = mMotionY;
- final int motionPosition = pointToPosition(x, y);
- if (motionPosition >= 0) {
- // Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
- mMotionPosition = motionPosition;
- }
- mLastY = y;
- break;
- }
-
- case MotionEvent.ACTION_POINTER_DOWN: {
- // New pointers take over dragging duties
- final int index = ev.getActionIndex();
- final int id = ev.getPointerId(index);
- final int x = (int) ev.getX(index);
- final int y = (int) ev.getY(index);
- mMotionCorrection = 0;
- mActivePointerId = id;
- mMotionX = x;
- mMotionY = y;
- final int motionPosition = pointToPosition(x, y);
- if (motionPosition >= 0) {
- // Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
- mMotionPosition = motionPosition;
- }
- mLastY = y;
- break;
- }
- }
-
- return true;
+ mActivePointerId = INVALID_POINTER;
}
@Override
@@ -3733,7 +3755,7 @@
if (scrollY != 0) {
// Pin to the top/bottom during overscroll
int restoreCount = canvas.save();
- canvas.translate(0, (float) scrollY);
+ canvas.translate(0, scrollY);
mFastScroller.draw(canvas);
canvas.restoreToCount(restoreCount);
} else {
@@ -3945,6 +3967,7 @@
private int mLastFlingY;
private final Runnable mCheckFlywheel = new Runnable() {
+ @Override
public void run() {
final int activeId = mActivePointerId;
final VelocityTracker vt = mVelocityTracker;
@@ -4066,6 +4089,7 @@
postDelayed(mCheckFlywheel, FLYWHEEL_TIMEOUT);
}
+ @Override
public void run() {
switch (mTouchMode) {
default:
@@ -4455,6 +4479,7 @@
removeCallbacks(this);
}
+ @Override
public void run() {
final int listHeight = getHeight();
final int firstPos = mFirstPosition;
@@ -4637,9 +4662,6 @@
/**
* The amount of friction applied to flings. The default value
* is {@link ViewConfiguration#getScrollFriction}.
- *
- * @return A scalar dimensionless value representing the coefficient of
- * friction.
*/
public void setFriction(float friction) {
if (mFlingRunnable == null) {
@@ -4806,6 +4828,7 @@
if (!isHardwareAccelerated()) {
if (mClearScrollingCache == null) {
mClearScrollingCache = new Runnable() {
+ @Override
public void run() {
if (mCachingStarted) {
mCachingStarted = mCachingActive = false;
@@ -5083,7 +5106,7 @@
requestLayout();
invalidate();
}
-
+
/**
* If there is a selection returns false.
* Otherwise resurrects the selection and returns true if resurrected.
@@ -5706,6 +5729,7 @@
return mFiltered;
}
+ @Override
public void onGlobalLayout() {
if (isShown()) {
// Show the popup if we are filtered
@@ -5725,6 +5749,7 @@
* For our text watcher that is associated with the text filter. Does
* nothing.
*/
+ @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@@ -5733,6 +5758,7 @@
* the actual filtering as the text changes, and takes care of hiding and
* showing the popup displaying the currently entered filter text.
*/
+ @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mPopup != null && isTextFilterEnabled()) {
int length = s.length();
@@ -5763,9 +5789,11 @@
* For our text watcher that is associated with the text filter. Does
* nothing.
*/
+ @Override
public void afterTextChanged(Editable s) {
}
+ @Override
public void onFilterComplete(int count) {
if (mSelectedPosition < 0 && count > 0) {
mResurrectToPosition = INVALID_POSITION;
@@ -5934,6 +5962,7 @@
* This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
* connected yet.
*/
+ @Override
public void deferNotifyDataSetChanged() {
mDeferNotifyDataSetChanged = true;
}
@@ -5941,6 +5970,7 @@
/**
* Called back when the adapter connects to the RemoteViewsService.
*/
+ @Override
public boolean onRemoteAdapterConnected() {
if (mRemoteAdapter != mAdapter) {
setAdapter(mRemoteAdapter);
@@ -5959,6 +5989,7 @@
/**
* Called back when the adapter disconnects from the RemoteViewsService.
*/
+ @Override
public void onRemoteAdapterDisconnected() {
// If the remote adapter disconnects, we keep it around
// since the currently displayed items are still cached.
@@ -6041,6 +6072,7 @@
return mWrapped != null;
}
+ @Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
if (mWrapped.onCreateActionMode(mode, menu)) {
// Initialize checked graphic state?
@@ -6050,14 +6082,17 @@
return false;
}
+ @Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return mWrapped.onPrepareActionMode(mode, menu);
}
+ @Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return mWrapped.onActionItemClicked(mode, item);
}
+ @Override
public void onDestroyActionMode(ActionMode mode) {
mWrapped.onDestroyActionMode(mode);
mChoiceActionMode = null;
@@ -6072,6 +6107,7 @@
setLongClickable(true);
}
+ @Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
mWrapped.onItemCheckedStateChanged(mode, position, id, checked);
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index a19c6a8..6970cde 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -1248,17 +1248,14 @@
* @param calendar A day in the new focus month.
*/
private void setMonthDisplayed(Calendar calendar) {
- final int newMonthDisplayed = calendar.get(Calendar.MONTH);
- if (mCurrentMonthDisplayed != newMonthDisplayed) {
- mCurrentMonthDisplayed = newMonthDisplayed;
- mAdapter.setFocusMonth(mCurrentMonthDisplayed);
- final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
- | DateUtils.FORMAT_SHOW_YEAR;
- final long millis = calendar.getTimeInMillis();
- String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
- mMonthName.setText(newMonthName);
- mMonthName.invalidate();
- }
+ mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+ mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+ final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
+ | DateUtils.FORMAT_SHOW_YEAR;
+ final long millis = calendar.getTimeInMillis();
+ String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
+ mMonthName.setText(newMonthName);
+ mMonthName.invalidate();
}
/**
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index acbb2b1..e092fff 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -1210,6 +1210,10 @@
mActionView.setIcon(icon);
}
+ public boolean hasIcon() {
+ return mActionView.hasIcon();
+ }
+
@Override
public void setLogo(int resId) {
mActionView.setLogo(resId);
@@ -1220,6 +1224,10 @@
mActionView.setLogo(logo);
}
+ public boolean hasLogo() {
+ return mActionView.hasLogo();
+ }
+
public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
if (!mDisplayHomeAsUpSet) {
setDisplayHomeAsUpEnabled(enable);
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index cf797bb..e300021 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -97,7 +97,7 @@
public void onAttach(Activity activity) {
super.onAttach(activity);
mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
- mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_ACTIVE_SCAN);
+ mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
}
@Override
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index c22cd26..a674776 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -16,6 +16,7 @@
package com.android.internal.app;
+import android.os.AsyncTask;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
@@ -621,9 +622,11 @@
view = mInflater.inflate(
com.android.internal.R.layout.resolve_list_item, parent, false);
+ final ViewHolder holder = new ViewHolder(view);
+ view.setTag(holder);
+
// Fix the icon size even if we have different sized resources
- ImageView icon = (ImageView)view.findViewById(R.id.icon);
- ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) icon.getLayoutParams();
+ ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
lp.width = lp.height = mIconSize;
} else {
view = convertView;
@@ -633,20 +636,30 @@
}
private final void bindView(View view, DisplayResolveInfo info) {
- TextView text = (TextView)view.findViewById(com.android.internal.R.id.text1);
- TextView text2 = (TextView)view.findViewById(com.android.internal.R.id.text2);
- ImageView icon = (ImageView)view.findViewById(R.id.icon);
- text.setText(info.displayLabel);
+ final ViewHolder holder = (ViewHolder) view.getTag();
+ holder.text.setText(info.displayLabel);
if (mShowExtended) {
- text2.setVisibility(View.VISIBLE);
- text2.setText(info.extendedInfo);
+ holder.text2.setVisibility(View.VISIBLE);
+ holder.text2.setText(info.extendedInfo);
} else {
- text2.setVisibility(View.GONE);
+ holder.text2.setVisibility(View.GONE);
}
if (info.displayIcon == null) {
- info.displayIcon = loadIconForResolveInfo(info.ri);
+ new LoadIconTask().execute(info);
}
- icon.setImageDrawable(info.displayIcon);
+ holder.icon.setImageDrawable(info.displayIcon);
+ }
+ }
+
+ static class ViewHolder {
+ public TextView text;
+ public TextView text2;
+ public ImageView icon;
+
+ public ViewHolder(View view) {
+ text = (TextView) view.findViewById(com.android.internal.R.id.text1);
+ text2 = (TextView) view.findViewById(com.android.internal.R.id.text2);
+ icon = (ImageView) view.findViewById(R.id.icon);
}
}
@@ -660,5 +673,21 @@
}
}
+
+ class LoadIconTask extends AsyncTask<DisplayResolveInfo, Void, DisplayResolveInfo> {
+ @Override
+ protected DisplayResolveInfo doInBackground(DisplayResolveInfo... params) {
+ final DisplayResolveInfo info = params[0];
+ if (info.displayIcon == null) {
+ info.displayIcon = loadIconForResolveInfo(info.ri);
+ }
+ return info;
+ }
+
+ @Override
+ protected void onPostExecute(DisplayResolveInfo info) {
+ mAdapter.notifyDataSetChanged();
+ }
+ }
}
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 95130c8..70e2bfc 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -17,12 +17,13 @@
package com.android.internal.view;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -40,6 +41,21 @@
}
/**
+ * Gets whether the device supports rotation. In general such a
+ * device has an accelerometer and has the portrait and landscape
+ * features.
+ *
+ * @param context Context for accessing system resources.
+ * @return Whether the device supports rotation.
+ */
+ public static boolean isRotationSupported(Context context) {
+ PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)
+ && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
+ && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
+ }
+
+ /**
* Returns true if the device supports the rotation-lock toggle feature
* in the system UI or system bar.
*
@@ -48,7 +64,8 @@
* settings.
*/
public static boolean isRotationLockToggleSupported(Context context) {
- return context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+ return isRotationSupported(context)
+ && context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}
/**
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index dda1a10..f2bd522 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -16,24 +16,12 @@
package com.android.internal.widget;
-import com.android.internal.R;
-import com.android.internal.view.menu.ActionMenuItem;
-import com.android.internal.view.menu.ActionMenuPresenter;
-import com.android.internal.view.menu.ActionMenuView;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuPresenter;
-import com.android.internal.view.menu.MenuView;
-import com.android.internal.view.menu.SubMenuBuilder;
-
import android.animation.LayoutTransition;
import android.app.ActionBar;
import android.app.ActionBar.OnNavigationListener;
-import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -42,7 +30,6 @@
import android.text.Layout;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.CollapsibleActionView;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -62,6 +49,15 @@
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
+import com.android.internal.R;
+import com.android.internal.view.menu.ActionMenuItem;
+import com.android.internal.view.menu.ActionMenuPresenter;
+import com.android.internal.view.menu.ActionMenuView;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
+import com.android.internal.view.menu.MenuView;
+import com.android.internal.view.menu.SubMenuBuilder;
/**
* @hide
@@ -188,34 +184,8 @@
ActionBar.NAVIGATION_MODE_STANDARD);
mTitle = a.getText(R.styleable.ActionBar_title);
mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
-
mLogo = a.getDrawable(R.styleable.ActionBar_logo);
- if (mLogo == null) {
- if (context instanceof Activity) {
- try {
- mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Activity component name not found!", e);
- }
- }
- if (mLogo == null) {
- mLogo = appInfo.loadLogo(pm);
- }
- }
-
mIcon = a.getDrawable(R.styleable.ActionBar_icon);
- if (mIcon == null) {
- if (context instanceof Activity) {
- try {
- mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Activity component name not found!", e);
- }
- }
- if (mIcon == null) {
- mIcon = appInfo.loadIcon(pm);
- }
- }
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -729,7 +699,11 @@
}
public void setIcon(int resId) {
- setIcon(mContext.getResources().getDrawable(resId));
+ setIcon(resId != 0 ? mContext.getResources().getDrawable(resId) : null);
+ }
+
+ public boolean hasIcon() {
+ return mIcon != null;
}
public void setLogo(Drawable logo) {
@@ -740,7 +714,11 @@
}
public void setLogo(int resId) {
- setLogo(mContext.getResources().getDrawable(resId));
+ setLogo(resId != 0 ? mContext.getResources().getDrawable(resId) : null);
+ }
+
+ public boolean hasLogo() {
+ return mLogo != null;
}
public void setNavigationMode(int mode) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index febccb4..188941b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -17,6 +17,10 @@
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+# When built as part of the system image we can enable certian non-NDK compliant
+# Skia optimizations.
+LOCAL_CFLAGS += -DSK_BUILD_FOR_ANDROID_FRAMEWORK
+
LOCAL_SRC_FILES:= \
AndroidRuntime.cpp \
Time.cpp \
@@ -159,10 +163,6 @@
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
$(TOP)/frameworks/av/include \
- external/skia/include/core \
- external/skia/include/effects \
- external/skia/include/images \
- external/skia/include/ports \
external/skia/src/core \
external/skia/src/images \
external/skia/include/utils \
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 5454c08..380f061 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -58,6 +58,10 @@
static void defaultSettingsForAndroid(SkPaint* paint) {
// GlyphID encoding is required because we are using Harfbuzz shaping
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+
+ SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
+ paintOpts.setUseFontFallbacks(true);
+ paint->setPaintOptionsAndroid(paintOpts);
}
class SkPaintGlue {
@@ -300,7 +304,10 @@
ScopedUtfChars localeChars(env, locale);
char langTag[ULOC_FULLNAME_CAPACITY];
toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str());
- obj->setLanguage(SkLanguage(langTag));
+
+ SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
+ paintOpts.setLanguage(langTag);
+ obj->setPaintOptionsAndroid(paintOpts);
}
static jfloat getTextSize(JNIEnv* env, jobject paint) {
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index cd84fff..73f3639 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -218,7 +218,8 @@
*/
TextLayoutCacheKey::TextLayoutCacheKey(): start(0), count(0), contextCount(0),
dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
- hinting(SkPaint::kNo_Hinting), variant(SkPaint::kDefault_Variant), language() {
+ hinting(SkPaint::kNo_Hinting) {
+ paintOpts.setUseFontFallbacks(true);
}
TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint, const UChar* text,
@@ -232,8 +233,7 @@
textScaleX = paint->getTextScaleX();
flags = paint->getFlags();
hinting = paint->getHinting();
- variant = paint->getFontVariant();
- language = paint->getLanguage();
+ paintOpts = paint->getPaintOptionsAndroid();
}
TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
@@ -248,8 +248,7 @@
textScaleX(other.textScaleX),
flags(other.flags),
hinting(other.hinting),
- variant(other.variant),
- language(other.language) {
+ paintOpts(other.paintOpts) {
}
int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
@@ -283,11 +282,8 @@
deltaInt = lhs.dirFlags - rhs.dirFlags;
if (deltaInt) return (deltaInt);
- deltaInt = lhs.variant - rhs.variant;
- if (deltaInt) return (deltaInt);
-
- if (lhs.language < rhs.language) return -1;
- if (lhs.language > rhs.language) return +1;
+ if (lhs.paintOpts != rhs.paintOpts)
+ return memcmp(&lhs.paintOpts, &rhs.paintOpts, sizeof(SkPaintOptionsAndroid));
return memcmp(lhs.getText(), rhs.getText(), lhs.contextCount * sizeof(UChar));
}
@@ -306,7 +302,7 @@
hash = JenkinsHashMix(hash, hash_type(textScaleX));
hash = JenkinsHashMix(hash, flags);
hash = JenkinsHashMix(hash, hinting);
- hash = JenkinsHashMix(hash, variant);
+ hash = JenkinsHashMix(hash, paintOpts.getFontVariant());
// Note: leaving out language is not problematic, as equality comparisons
// are still valid - the only bad thing that could happen is collisions.
hash = JenkinsHashMixShorts(hash, getText(), contextCount);
@@ -698,8 +694,7 @@
mShapingPaint.setTextScaleX(paint->getTextScaleX());
mShapingPaint.setFlags(paint->getFlags());
mShapingPaint.setHinting(paint->getHinting());
- mShapingPaint.setFontVariant(paint->getFontVariant());
- mShapingPaint.setLanguage(paint->getLanguage());
+ mShapingPaint.setPaintOptionsAndroid(paint->getPaintOptionsAndroid());
// Split the BiDi run into Script runs. Harfbuzz will populate the pos, length and script
// into the shaperItem
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index ab6ac72..54704ec 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -28,7 +28,6 @@
#include <utils/Singleton.h>
#include <SkAutoKern.h>
-#include <SkLanguage.h>
#include <SkPaint.h>
#include <SkTemplates.h>
#include <SkTypeface.h>
@@ -104,8 +103,7 @@
SkScalar textScaleX;
uint32_t flags;
SkPaint::Hinting hinting;
- SkPaint::FontVariant variant;
- SkLanguage language;
+ SkPaintOptionsAndroid paintOpts;
}; // TextLayoutCacheKey
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 9537ac4..08962e2 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -33,11 +33,11 @@
static jint DBG = false;
-static int doCommand(const char *ifname, const char *cmd, char *replybuf, int replybuflen)
+static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuflen)
{
size_t reply_len = replybuflen - 1;
- if (::wifi_command(ifname, cmd, replybuf, &reply_len) != 0)
+ if (::wifi_command(ifname, cmd, BUF_SIZE, replybuf, &reply_len) != 0)
return -1;
else {
// Strip off trailing newline
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3443d6e..6918099 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2298,8 +2298,7 @@
<activity android:name="android.accounts.CantAddAccountActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@android:style/Theme.Holo.Dialog"
- android:label="@string/error_message_title"
+ android:theme="@android:style/Theme.Holo.Dialog.NoActionBar"
android:process=":ui">
</activity>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index c3b1ac5..39915f9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string>
<string name="owner_name" msgid="2716755460376028154">"Eienaar"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Hierdie program werk nie met rekeninge vir beperkte profiele nie"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Geen program gevind om hierdie handeling te hanteer nie"</string>
<string name="revoke" msgid="5404479185228271586">"Herroep"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 12cfbf4..327f1cb 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"የአሁኑ ተጠቃሚ <xliff:g id="NAME">%1$s</xliff:g>።"</string>
<string name="owner_name" msgid="2716755460376028154">"ባለቤት"</string>
<string name="error_message_title" msgid="4510373083082500195">"ስህተት"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"ይህ መተግበሪያ የተገደቡ መገለጫዎች መለያዎችን አይደግፍም"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም"</string>
<string name="revoke" msgid="5404479185228271586">"ሻር"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 50c143b..19f2d6a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -556,7 +556,7 @@
<string name="permlab_useCredentials" msgid="235481396163877642">"استخدام الحسابات على الجهاز"</string>
<string name="permdesc_useCredentials" msgid="7984227147403346422">"للسماح للتطبيق بطلب الرموز المميزة للمصادقة."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"عرض اتصالات الشبكة"</string>
- <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"للمساح للتطبيق بعرض معلومات حول اتصالات الشبكة كعرض معلومات عن الشبكات المتوفرة والشبكات المتصلة."</string>
+ <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"للسماح للتطبيق بعرض معلومات حول اتصالات الشبكة كعرض معلومات عن الشبكات المتوفرة والشبكات المتصلة."</string>
<string name="permlab_createNetworkSockets" msgid="8018758136404323658">"إمكانية دخول كاملة إلى الشبكة"</string>
<string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"للسماح للتطبيق بإنشاء مقابس شبكات واستخدام بروتوكولات شبكات مخصصة. ويوفر المتصفح وتطبيقات أخرى طرقًا لإرسال البيانات إلى الإنترنت، ولذلك لا يعد هذا الإذن مطلوبًا لإرسال البيانات إلى الإنترنت."</string>
<string name="permlab_writeApnSettings" msgid="505660159675751896">"تغيير/اعتراض إعدادات الشبكة وحركة المرور"</string>
@@ -572,8 +572,8 @@
<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="default" msgid="6851949706025349926">"للمساح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة 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="default" msgid="8931682159331542137">"للسماح للتطبيق بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"المستخدم الحالي <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"المالك"</string>
<string name="error_message_title" msgid="4510373083082500195">"خطأ"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"هذا التطبيق لا يتوافق مع حسابات الملفات الشخصية المقيدة"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"لا يتوافق هذا التطبيق مع حسابات الملفات الشخصية المقيدة"</string>
<string name="app_not_found" msgid="3429141853498927379">"لم يتم العثور على تطبيق يمكنه التعامل مع هذا الإجراء."</string>
<string name="revoke" msgid="5404479185228271586">"إلغاء"</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 5cb4c43..ab0db23 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Бягучы карыстальнік <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Уладальнік"</string>
<string name="error_message_title" msgid="4510373083082500195">"Памылка"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Гэтае прыкладанне не падтрымлівае уліковыя запісы для карыстальнікаў з абмежаваннямi"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Гэта прыкладанне не падтрымлівае ўліковыя запісы для профiляў з абмежаваннямі"</string>
<string name="app_not_found" msgid="3429141853498927379">"Прыкладанне для гэтага дзеяння не знойдзенае"</string>
<string name="revoke" msgid="5404479185228271586">"Ануляваць"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index afa6c11..4d8a5cc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Текущ потребител <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Собственик"</string>
<string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Това приложение не поддържа профили за потребителски профили с ограничена функционалност"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Няма намерено приложение за извършване на това действие"</string>
<string name="revoke" msgid="5404479185228271586">"Отмяна"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index aaa911d..4eaf068 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -565,8 +565,8 @@
<string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Permet que l\'aplicació pugui canviar l\'estat de connectivitat de la xarxa."</string>
<string name="permlab_changeTetherState" msgid="5952584964373017960">"Canvia la connectivitat d\'ancoratge a xarxa"</string>
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permet que l\'aplicació canviï l\'estat de la connectivitat de la xarxa d\'ancoratge."</string>
- <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"canviar la configuració d\'ús de dades de referència"</string>
- <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permet que l\'aplicació canviï la configuració d\'ús de les dades de fons."</string>
+ <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"canviar la configuració d\'ús de dades en segon pla"</string>
+ <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Permet que l\'aplicació canviï la configuració d\'ús de les dades en segon pla."</string>
<string name="permlab_accessWifiState" msgid="5202012949247040011">"veure connexions Wi-Fi"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permet que l\'aplicació visualitzi informació sobre les xarxes Wi-Fi, com ara si la Wi-Fi està activada i el nom dels dispositius Wi-Fi connectats."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"connectar-se a xarxes Wi-Fi i desconnectar-se"</string>
@@ -1406,7 +1406,7 @@
<string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"S\'ha superat el límit de dades mòbils"</string>
<string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"S\'ha superat el límit de dades Wi-Fi"</string>
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> per sobre del límit especif."</string>
- <string name="data_usage_restricted_title" msgid="5965157361036321914">"Dades de referència restringides"</string>
+ <string name="data_usage_restricted_title" msgid="5965157361036321914">"Dades en segon pla restringides"</string>
<string name="data_usage_restricted_body" msgid="6741521330997452990">"Toca per eliminar la restricció."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificat de seguretat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Aquest certificat és vàlid."</string>
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Usuari actual: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Propietari"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"L\'aplicació no és compatible amb comptes de perfils restringits."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"No s\'ha trobat cap aplicació per processar aquesta acció"</string>
<string name="revoke" msgid="5404479185228271586">"Revoca"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index abe6dad..91498cd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Aktuální uživatel je <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
<string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Tato aplikace nepodporuje účty pro omezené profily."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Aplikace potřebná k provedení této akce nebyla nalezena"</string>
<string name="revoke" msgid="5404479185228271586">"Zrušit"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index e00597a..081fd2a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Nuværende bruger <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Ejer"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fejl"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Denne applikation understøtter ikke konti for begrænsede profiler"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Der blev ikke fundet nogen applikation, der kan håndtere denne handling"</string>
<string name="revoke" msgid="5404479185228271586">"Tilbagekald"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 655d5d0..53db449 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -940,7 +940,7 @@
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Vor 1 Monat"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vor mehr als 1 Monat"</string>
<plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Vor 1 Sekunde"</item>
+ <item quantity="one" msgid="4869870056547896011">"vor 1 Sekunde"</item>
<item quantity="other" msgid="3903706804349556379">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
</plurals>
<plurals name="num_minutes_ago">
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Aktueller Nutzer <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Eigentümer"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fehler"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Diese App unterstützt keine Konten für eingeschränkte Profile."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Für diese Aktion wurde keine App gefunden."</string>
<string name="revoke" msgid="5404479185228271586">"Aufheben"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5135847..78a707f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Τρέχων χρήστης <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Κάτοχος"</string>
<string name="error_message_title" msgid="4510373083082500195">"Σφάλμα"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Αυτή η εφαρμογή δεν υποστηρίζει λογαριασμούς για περιορισμένα προφίλ"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Δεν υπάρχει εφαρμογή για τη διαχείριση αυτής της ενέργειας"</string>
<string name="revoke" msgid="5404479185228271586">"Ανάκληση"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2d5e70c..b8c0d50 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Current user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Owner"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"This application does not support accounts for restricted profiles"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"This app doesn\'t support accounts for restricted profiles"</string>
<string name="app_not_found" msgid="3429141853498927379">"No application found to handle this action"</string>
<string name="revoke" msgid="5404479185228271586">"Revoke"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 501d56f..49f6e1f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Esta aplicación no admite cuentas de perfiles restringidos."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"No se encontró una aplicación para manejar esta acción."</string>
<string name="revoke" msgid="5404479185228271586">"Revocar"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0685e66..0a704c3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Propietario"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Esta aplicación no admite cuentas de perfiles restringidos"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
<string name="revoke" msgid="5404479185228271586">"Revocar"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b1997d1..8f6911c 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Praegune kasutaja <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Omanik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Viga"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"See rakendus ei toeta piiratud profiilide kontosid"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust"</string>
<string name="revoke" msgid="5404479185228271586">"Tühista"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b47bf9f..170e9ae 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"کاربر کنونی <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"دارنده"</string>
<string name="error_message_title" msgid="4510373083082500195">"خطا"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"این برنامه از حسابهای متعلق به نمایههای محدود پشتیبانی نمیکند"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"این برنامه از حسابهای متعلق به نمایههای محدود پشتیبانی نمیکند"</string>
<string name="app_not_found" msgid="3429141853498927379">"برنامهای برای انجام این عملکرد موجود نیست"</string>
<string name="revoke" msgid="5404479185228271586">"لغو"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index feeed53..15a5f95 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Nykyinen käyttäjä: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Omistaja"</string>
<string name="error_message_title" msgid="4510373083082500195">"Virhe"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Tämä sovellus ei tue rajoitettujen profiilien tilejä"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Tätä toimintoa käsittelevää sovellusta ei löydy"</string>
<string name="revoke" msgid="5404479185228271586">"Peruuta"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 97e0a82..9afa938 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Utilisateur actuel : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"Propriétaire"</string>
<string name="error_message_title" msgid="4510373083082500195">"Erreur"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Les comptes des profils limités ne sont pas acceptés pour cette application."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Aucune application trouvée pour gérer cette action."</string>
<string name="revoke" msgid="5404479185228271586">"Révoquer"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b135c2e..4df3a5b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
<string name="error_message_title" msgid="4510373083082500195">"त्रुटि"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"यह एप्लिकेशन प्रतिबंधित प्रोफ़ाइल के खातों का समर्थन नहीं करता है"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई एप्लिकेशन नहीं मिला"</string>
<string name="revoke" msgid="5404479185228271586">"निरस्त करें"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f033a16..a7208ee 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Vlasnik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Pogreška"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Aplikacija ne podržava račune za ograničene profile"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija za upravljanje ovom radnjom"</string>
<string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 516241f..3060fd1 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> az aktuális felhasználó."</string>
<string name="owner_name" msgid="2716755460376028154">"Tulajdonos"</string>
<string name="error_message_title" msgid="4510373083082500195">"Hiba"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ez az alkalmazás nem támogatja a korlátozott profilokkal rendelkező fiókokat"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nincs megfelelő alkalmazás a művelet elvégzésére."</string>
<string name="revoke" msgid="5404479185228271586">"Visszavonás"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 812d016..5504078 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Pengguna saat ini <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Kesalahan"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Aplikasi ini tidak mendukung akun untuk profil yang dibatasi"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Tidak ada aplikasi yang ditemukan untuk menangani tindakan ini"</string>
<string name="revoke" msgid="5404479185228271586">"Cabut"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 05bed06..a1e8bfc 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Utente corrente <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietario"</string>
<string name="error_message_title" msgid="4510373083082500195">"Errore"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Questa applicazione non supporta account relativi a profili con limitazioni"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nessuna applicazione trovata in grado di gestire questa azione"</string>
<string name="revoke" msgid="5404479185228271586">"Revoca"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1e0e204..d48f846 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"המשתמש הנוכחי <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"בעלים"</string>
<string name="error_message_title" msgid="4510373083082500195">"שגיאה"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"היישום הזה לא תומך בחשבונות עבור פרופילים מוגבלים"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"לא נמצא יישום שתומך בפעולה זו"</string>
<string name="revoke" msgid="5404479185228271586">"בטל"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3241159..9932924 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"現在のユーザーは<xliff:g id="NAME">%1$s</xliff:g>です。"</string>
<string name="owner_name" msgid="2716755460376028154">"所有者"</string>
<string name="error_message_title" msgid="4510373083082500195">"エラー"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"このアプリでは制限付きプロフィールのアカウントはサポートしていません"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"この操作を行うアプリが見つかりません"</string>
<string name="revoke" msgid="5404479185228271586">"取り消し"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b6e07c8..f66fb33 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"현재 사용자는 <xliff:g id="NAME">%1$s</xliff:g>님입니다."</string>
<string name="owner_name" msgid="2716755460376028154">"소유자"</string>
<string name="error_message_title" msgid="4510373083082500195">"오류"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"이 애플리케이션은 제한된 프로필의 계정을 지원하지 않습니다."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"이 작업을 처리하는 애플리케이션을 찾을 수 없습니다."</string>
<string name="revoke" msgid="5404479185228271586">"취소"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2ad0598..d4019f3 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Dabartinis naudotojas: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Savininkas"</string>
<string name="error_message_title" msgid="4510373083082500195">"Klaida"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ši programa nepalaiko apribotų profilių paskyrų"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nerasta programa šiam veiksmui apdoroti"</string>
<string name="revoke" msgid="5404479185228271586">"Anuliuoti"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index de30037..dac8a7b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Pašreizējais lietotājs: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Īpašnieks"</string>
<string name="error_message_title" msgid="4510373083082500195">"Kļūda"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Šajā lietojumprogrammā netiek atbalstīti ierobežotu profilu konti."</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Netika atrasta neviena lietojumprogramma, kas var veikt šo darbību."</string>
<string name="revoke" msgid="5404479185228271586">"Atsaukt"</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b518ea9..bcc9493 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Pengguna semasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Pemilik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Ralat"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Apl ini tidak menyokong akaun untuk profil yang disekat"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Tidak menemui aplikasi untuk mengendalikan tindakan ini"</string>
<string name="revoke" msgid="5404479185228271586">"Batalkan"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 080a05c..5993cc9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Gjeldende bruker: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Eier"</string>
<string name="error_message_title" msgid="4510373083082500195">"Feil"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Denne appen støtter ikke kontoer for begrensede profiler"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Finner ingen apper som kan utføre denne handlingen"</string>
<string name="revoke" msgid="5404479185228271586">"Opphev"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 299658e..b8e5deb 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Eigenaar"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fout"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Deze app biedt geen ondersteuning voor accounts voor beperkte profielen"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Er is geen app gevonden om deze actie uit te voeren"</string>
<string name="revoke" msgid="5404479185228271586">"Intrekken"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index babfe61..642237c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -52,9 +52,9 @@
<string name="needPuk2" msgid="4526033371987193070">"Wprowadź kod PUK2, aby odblokować kartę SIM."</string>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
- <string name="ClipMmi" msgid="6952821216480289285">"Identyfikator rozmówcy przy połączeniach przychodzących"</string>
- <string name="ClirMmi" msgid="7784673673446833091">"Identyfikator rozmówcy przy połączeniach wychodzących"</string>
- <string name="CfMmi" msgid="5123218989141573515">"Przekazywanie połączeń"</string>
+ <string name="ClipMmi" msgid="6952821216480289285">"Nazwa rozmówcy przy połączeniach przychodzących"</string>
+ <string name="ClirMmi" msgid="7784673673446833091">"Nazwa rozmówcy przy połączeniach wychodzących"</string>
+ <string name="CfMmi" msgid="5123218989141573515">"Przekierowanie połączeń"</string>
<string name="CwMmi" msgid="9129678056795016867">"Połączenia oczekujące"</string>
<string name="BaMmi" msgid="455193067926770581">"Blokada dzwonienia"</string>
<string name="PwdMmi" msgid="7043715687905254199">"Zmiana hasła"</string>
@@ -65,10 +65,10 @@
<string name="RuacMmi" msgid="7827887459138308886">"Odrzucanie niepożądanych, irytujących połączeń"</string>
<string name="CndMmi" msgid="3116446237081575808">"Dostarczanie numeru telefonującego"</string>
<string name="DndMmi" msgid="1265478932418334331">"Nie przeszkadzać"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony"</string>
- <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Nazwa rozmówcy ustawiona jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Nazwa rozmówcy ustawiona jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nazwa rozmówcy ustawiona jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nazwa rozmówcy ustawiona jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Usługa nie jest świadczona."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nie możesz zmienić ustawienia identyfikatora rozmówcy."</string>
<string name="RestrictedChangedTitle" msgid="5592189398956187498">"Zmieniono ograniczenie dostępu"</string>
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Właściciel"</string>
<string name="error_message_title" msgid="4510373083082500195">"Błąd"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ta aplikacja nie obsługuje kont w przypadku profili z ograniczeniami"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
<string name="revoke" msgid="5404479185228271586">"Cofnij"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6d76248..ff912b9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"<xliff:g id="NAME">%1$s</xliff:g> do utilizador atual."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
<string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Esta aplicação não suporta contas de perfis restritos"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Não foram encontradas aplicações para executar esta ação"</string>
<string name="revoke" msgid="5404479185228271586">"Revogar"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 252fc27..9698884 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -205,7 +205,7 @@
<string name="permgrouplab_appInfo" msgid="8028789762634147725">"Informações sobre seus aplicativos"</string>
<string name="permgroupdesc_appInfo" msgid="3950378538049625907">"Capacidade de afetar o comportamento de outros aplicativos no dispositivo."</string>
<string name="permgrouplab_wallpaper" msgid="3850280158041175998">"Plano de fundo"</string>
- <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Alterar as configurações de papel de parede do dispositivo."</string>
+ <string name="permgroupdesc_wallpaper" msgid="5630417854750540154">"Alterar as configurações de plano de fundo do dispositivo."</string>
<string name="permgrouplab_systemClock" msgid="406535759236612992">"Relógio"</string>
<string name="permgroupdesc_systemClock" msgid="3944359833624094992">"Alterar a hora ou fuso horário no dispositivo."</string>
<string name="permgrouplab_statusBar" msgid="2095862568113945398">"Barra de status"</string>
@@ -533,7 +533,7 @@
<string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Executa como um teste do fabricante de nível inferior, permitindo o acesso completo ao hardware do tablet. Disponível apenas quando um tablet está em execução no modo de teste do fabricante."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Executa como um teste do fabricante de nível inferior, permitindo o acesso completo ao hardware do telefone. Disponível apenas quando um telefone está em execução no modo de teste do fabricante."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"definir plano de fundo"</string>
- <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Permite que o aplicativo defina o papel de parede do sistema."</string>
+ <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Permite que o aplicativo defina o plano de fundo do sistema."</string>
<string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ajustar tamanho do plano de fundo"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Permite que o aplicativo defina as dicas de tamanho do plano de fundo do sistema."</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"redefinir o sistema para os padrões de fábrica"</string>
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Usuário atual <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietário"</string>
<string name="error_message_title" msgid="4510373083082500195">"Erro"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Este aplicativo não suporta contas para perfis restritos"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nenhum aplicativo encontrado para executar a ação"</string>
<string name="revoke" msgid="5404479185228271586">"Revogar"</string>
</resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 4404d875..b2a0bca 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -2435,7 +2435,7 @@
<skip />
<!-- no translation found for error_message_title (4510373083082500195) -->
<skip />
- <!-- no translation found for app_no_restricted_accounts (4011285085817350390) -->
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
<skip />
<!-- no translation found for app_not_found (3429141853498927379) -->
<skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4267fe1..b7866f6 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Proprietar"</string>
<string name="error_message_title" msgid="4510373083082500195">"Eroare"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Această aplicație nu acceptă conturi pentru profilurile cu permisiuni limitate"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Nicio aplicație pentru gestionarea acestei acțiuni"</string>
<string name="revoke" msgid="5404479185228271586">"Revocați"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b05bef7..3b8b907 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Выбран аккаунт пользователя <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Владелец"</string>
<string name="error_message_title" msgid="4510373083082500195">"Ошибка"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Это приложение не поддерживается в аккаунтах для профилей с ограниченным доступом"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Невозможно обработать это действие"</string>
<string name="revoke" msgid="5404479185228271586">"Отменить"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 96b44f7..2d62a47 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Aktuálny používateľ je <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Vlastník"</string>
<string name="error_message_title" msgid="4510373083082500195">"Chyba"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Táto aplikácia nepodporuje účty pre profily s obmedzením"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Táto aplikácia nepodporuje účty pre profily s obmedzením"</string>
<string name="app_not_found" msgid="3429141853498927379">"Aplikácia potrebná na spracovanie tejto akcie sa nenašla"</string>
<string name="revoke" msgid="5404479185228271586">"Odvolať"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5280b06..fd0b91f 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Trenutni uporabnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Lastnik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Napaka"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ta aplikacija ne podpira računov za profile z omejitvami"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Najdena ni bila nobena aplikacija za izvedbo tega dejanja"</string>
<string name="revoke" msgid="5404479185228271586">"Prekliči"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 79a3d87..742375f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Актуелни корисник <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Власник"</string>
<string name="error_message_title" msgid="4510373083082500195">"Грешка"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ова апликација не подржава налоге за ограничене профиле"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Није пронађена ниједна апликација која би могла да обави ову радњу"</string>
<string name="revoke" msgid="5404479185228271586">"Опозови"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 0775d0a..1a316bd 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Nuvarande användare: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Ägare"</string>
<string name="error_message_title" msgid="4510373083082500195">"Fel"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Den här appen stöder inte konton för begränsade profiler"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Ingen app som kan hantera åtgärden hittades"</string>
<string name="revoke" msgid="5404479185228271586">"Återkalla"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 450e6a3..bf03bdc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Mtumiaji wa sasa <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Mmiliki"</string>
<string name="error_message_title" msgid="4510373083082500195">"Hitilafu"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Programu hii haiwezi kutumiwa na akaunti za wasifu zilizowekewa vikwazo"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
<string name="revoke" msgid="5404479185228271586">"Batilisha"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index fd3ab94..f917448 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="owner_name" msgid="2716755460376028154">"เจ้าของ"</string>
<string name="error_message_title" msgid="4510373083082500195">"ข้อผิดพลาด"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"แอปพลิเคชันนี้ไม่สนับสนุนบัญชีที่มีโปรไฟล์ที่ถูกจำกัด"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"แอปนี้ไม่สนับสนุนบัญชีที่มีโปรไฟล์ที่ถูกจำกัด"</string>
<string name="app_not_found" msgid="3429141853498927379">"ไม่พบแอปพลิเคชันสำหรับการทำงานนี้"</string>
<string name="revoke" msgid="5404479185228271586">"เพิกถอน"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ce46219..53aaa0e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Kasalukuyang user <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"May-ari"</string>
<string name="error_message_title" msgid="4510373083082500195">"Error"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Hindi sinusuportahan ng application na ito ang mga account para sa mga pinaghihigpitang profile"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Walang nakitang application na mangangasiwa sa pagkilos na ito"</string>
<string name="revoke" msgid="5404479185228271586">"Bawiin"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c6e8519..1c25ab7 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Geçerli kullanıcı: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Sahibi"</string>
<string name="error_message_title" msgid="4510373083082500195">"Hata"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Bu uygulama kısıtlanmış profillerin hesaplarını desteklemez"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Bu eylemi gerçekleştirecek bir uygulama bulunamadı"</string>
<string name="revoke" msgid="5404479185228271586">"İptal et"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 216a9b1..9070582 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Поточний користувач: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Власник"</string>
<string name="error_message_title" msgid="4510373083082500195">"Помилка"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ця програма не підтримує облікові записи для обмежених профілів"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Не знайдено програму для обробки цієї дії"</string>
<string name="revoke" msgid="5404479185228271586">"Анулювати"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7f076b9..5d4f0a7 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"Người dùng hiện tại <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Chủ sở hữu"</string>
<string name="error_message_title" msgid="4510373083082500195">"Lỗi"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Ứng dụng này không hỗ trợ tài khoản cho các tiểu sử bị hạn chế"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"Không tìm thấy ứng dụng nào để xử lý tác vụ này"</string>
<string name="revoke" msgid="5404479185228271586">"Thu hồi"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 2e93751..9878860 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -451,17 +451,17 @@
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"允许安装位置信息提供程序"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"创建用于测试的模拟位置源或安装新的位置提供程序。此权限可让该应用覆盖由其他位置源(如 GPS)或位置提供程序返回的位置和/或状态信息。"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"精确位置(基于 GPS 和网络)"</string>
- <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统 (GPS) 或网络位置信息源(例如基站和 Wi-Fi)获取您的精确位置信息。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
+ <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统 (GPS) 或网络位置信息源(例如基站和 WLAN)获取您的精确位置信息。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
<string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"大致位置(基于网络)"</string>
- <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和 Wi-Fi)的位置服务。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和 WLAN)的位置服务。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"访问 SurfaceFlinger"</string>
<string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"允许应用使用 SurfaceFlinger 低级功能。"</string>
<string name="permlab_readFrameBuffer" msgid="6690504248178498136">"读取帧缓冲区"</string>
<string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"允许应用读取帧缓冲区的内容。"</string>
- <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"配置 Wi-Fi 显示设备"</string>
- <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允许应用配置并连接到 Wi-Fi 显示设备。"</string>
- <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 Wi-Fi 显示设备"</string>
- <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允许应用控制 Wi-Fi 显示设备的基础功能。"</string>
+ <string name="permlab_configureWifiDisplay" msgid="5595661694746742168">"配置 WLAN 显示设备"</string>
+ <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允许应用配置并连接到 WLAN 显示设备。"</string>
+ <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 WLAN 显示设备"</string>
+ <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允许应用控制 WLAN 显示设备的基础功能。"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允许该应用修改全局音频设置,例如音量和用于输出的扬声器。"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
@@ -567,13 +567,13 @@
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"允许应用更改绑定网络连接的状态。"</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"更改后台数据使用设置"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允许应用更改后台数据使用设置。"</string>
- <string name="permlab_accessWifiState" msgid="5202012949247040011">"查看 Wi-Fi 连接"</string>
- <string name="permdesc_accessWifiState" msgid="5002798077387803726">"允许该应用查看 Wi-Fi 网络的相关信息,例如是否启用了 Wi-Fi 以及连接的 Wi-Fi 设备的名称。"</string>
- <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="default" msgid="6851949706025349926">"允许该应用使用多播地址接收发送到 Wi-Fi 网络上所有设备(而不仅仅是您的手机)的数据包。该操作的耗电量比非多播模式要大。"</string>
+ <string name="permlab_accessWifiState" msgid="5202012949247040011">"查看 WLAN 连接"</string>
+ <string name="permdesc_accessWifiState" msgid="5002798077387803726">"允许该应用查看 WLAN 网络的相关信息,例如是否启用了 WLAN 以及连接的 WLAN 设备的名称。"</string>
+ <string name="permlab_changeWifiState" msgid="6550641188749128035">"连接 WLAN 和断开连接"</string>
+ <string name="permdesc_changeWifiState" msgid="7137950297386127533">"允许该应用与 WLAN 接入点建立和断开连接,以及更改 WLAN 网络的设备配置。"</string>
+ <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"允许接收 WLAN 多播"</string>
+ <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"允许该应用使用多播地址接收发送到 WLAN 网络上所有设备(而不仅仅是您的平板电脑)的数据包。该操作的耗电量比非多播模式要大。"</string>
+ <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"允许该应用使用多播地址接收发送到 WLAN 网络上所有设备(而不仅仅是您的手机)的数据包。该操作的耗电量比非多播模式要大。"</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"访问蓝牙设置"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"允许应用配置本地蓝牙平板电脑,以及发现远程设备并进行配对。"</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"允许应用配置本地蓝牙手机,以及发现远程设备并进行配对。"</string>
@@ -1130,23 +1130,23 @@
<string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"未知铃声"</string>
<plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"有可用的 Wi-Fi 网络"</item>
- <item quantity="other" msgid="4192424489168397386">"有可用的 Wi-Fi 网络"</item>
+ <item quantity="one" msgid="6654123987418168693">"有可用的 WLAN 网络"</item>
+ <item quantity="other" msgid="4192424489168397386">"有可用的 WLAN 网络"</item>
</plurals>
<plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"打开可用的 Wi-Fi 网络"</item>
- <item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
+ <item quantity="one" msgid="1634101450343277345">"打开可用的 WLAN 网络"</item>
+ <item quantity="other" msgid="7915895323644292768">"打开可用的 WLAN 网络"</item>
</plurals>
- <string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到 Wi-Fi 网络"</string>
+ <string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到 WLAN 网络"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"登录网络"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
<skip />
- <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 Wi-Fi"</string>
+ <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 WLAN"</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互联网连接状况不佳。"</string>
- <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
- <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"启动 Wi-Fi Direct。此操作将会关闭 Wi-Fi 客户端/热点。"</string>
- <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"无法启动 Wi-Fi Direct。"</string>
- <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"已启用 Wi-Fi Direct"</string>
+ <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WLAN Direct"</string>
+ <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"启动 WLAN Direct。此操作将会关闭 WLAN 客户端/热点。"</string>
+ <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"无法启动 WLAN Direct。"</string>
+ <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"已启用 WLAN Direct"</string>
<string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"通过触摸进行设置"</string>
<string name="accept" msgid="1645267259272829559">"接受"</string>
<string name="decline" msgid="2112225451706137894">"拒绝"</string>
@@ -1156,8 +1156,8 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"收件人:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"键入所需的 PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
- <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"平板电脑连接到“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”时会暂时断开与 Wi-Fi 的连接"</string>
- <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 Wi-Fi 的连接。"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"平板电脑连接到“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”时会暂时断开与 WLAN 的连接"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"手机连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时会暂时断开与 WLAN 的连接。"</string>
<string name="select_character" msgid="3365550120617701745">"插入字符"</string>
<string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>在发送大量短信。是否允许该应用继续发送短信?"</string>
@@ -1399,12 +1399,12 @@
<string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G 数据已停用"</string>
<string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G 数据已停用"</string>
<string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"移动数据已停用"</string>
- <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"Wi-Fi 数据网络已停用"</string>
+ <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"WLAN 数据网络已停用"</string>
<string name="data_usage_limit_body" msgid="3317964706973601386">"触摸可启用。"</string>
<string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"已超出 2G-3G 数据流量限制"</string>
<string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"已超出 4G 数据使用上限"</string>
<string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"已超出移动数据流量上限"</string>
- <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"超出了 Wi-Fi 数据流量上限"</string>
+ <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"超出了 WLAN 数据流量上限"</string>
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"超出规定上限 <xliff:g id="SIZE">%s</xliff:g>。"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"后台数据受限制"</string>
<string name="data_usage_restricted_body" msgid="6741521330997452990">"触摸可去除限制。"</string>
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"当前用户是<xliff:g id="NAME">%1$s</xliff:g>。"</string>
<string name="owner_name" msgid="2716755460376028154">"机主"</string>
<string name="error_message_title" msgid="4510373083082500195">"错误"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"此应用不支持受限个人资料的帐户"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"找不到可处理此操作的应用"</string>
<string name="revoke" msgid="5404479185228271586">"撤消"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5d55678..f175fc1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1498,7 +1498,8 @@
<string name="user_switched" msgid="3768006783166984410">"目前的使用者是 <xliff:g id="NAME">%1$s</xliff:g>。"</string>
<string name="owner_name" msgid="2716755460376028154">"擁有者"</string>
<string name="error_message_title" msgid="4510373083082500195">"錯誤"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"這個應用程式不支援設有限制的個人資料所屬帳戶"</string>
+ <!-- no translation found for app_no_restricted_accounts (5739463249673727736) -->
+ <skip />
<string name="app_not_found" msgid="3429141853498927379">"找不到支援此操作的應用程式"</string>
<string name="revoke" msgid="5404479185228271586">"撤銷"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index df86b74..eed5e04 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1498,7 +1498,7 @@
<string name="user_switched" msgid="3768006783166984410">"Umsebenzisi wamanje <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="owner_name" msgid="2716755460376028154">"Umnikazi"</string>
<string name="error_message_title" msgid="4510373083082500195">"Iphutha"</string>
- <string name="app_no_restricted_accounts" msgid="4011285085817350390">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wamaphrofayela akhawulelwe"</string>
+ <string name="app_no_restricted_accounts" msgid="5739463249673727736">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wamaphrofayela akhawulelwe"</string>
<string name="app_not_found" msgid="3429141853498927379">"Alukho uhlelo lokusebenza olutholakele lokuphatha lesi senzo"</string>
<string name="revoke" msgid="5404479185228271586">"Chitha"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5d71f75..459a634 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4057,10 +4057,6 @@
<attr name="drawable" />
</declare-styleable>
- <declare-styleable name="MipmapDrawableItem">
- <attr name="drawable" />
- </declare-styleable>
-
<!-- Drawable used to rotate another drawable. -->
<declare-styleable name="RotateDrawable">
<attr name="visible" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f282188..d40eb64 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4123,7 +4123,7 @@
<!-- Error message title [CHAR LIMIT=35] -->
<string name="error_message_title">Error</string>
<!-- Message informing user that app is not permitted to access accounts. [CHAR LIMIT=none] -->
- <string name="app_no_restricted_accounts">This application does not support accounts for restricted profiles</string>
+ <string name="app_no_restricted_accounts">This app doesn\'t support accounts for restricted profiles</string>
<!-- Message informing user that the requested activity could not be found [CHAR LIMIT=none] -->
<string name="app_not_found">No application found to handle this action</string>
<string name="revoke">Revoke</string>
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 6956634..43eead9 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -57,7 +57,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013.
+<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -83,7 +83,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013
+<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -130,7 +130,7 @@
-<p style="clear:both"><em>Data collected during a 14-day period ending on May 1, 2013</em></p>
+<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013</em></p>
@@ -148,7 +148,7 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chf=bg%2Cs%2C00000000&chd=t%3A1.8%2C3.7%2C38.5%2C0.1%2C27.5%2C28.4&chco=c4df9b%2C6fad0c&chl=Eclair%7CFroyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean",
+ "chart": "//chart.googleapis.com/chart?chl=Eclair%7CFroyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean&chd=t%3A1.6%2C3.2%2C36.5%2C0.1%2C25.6%2C33.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=500x250",
"data": [
{
"api": 4,
@@ -158,12 +158,12 @@
{
"api": 7,
"name": "Eclair",
- "perc": "1.7"
+ "perc": "1.5"
},
{
"api": 8,
"name": "Froyo",
- "perc": "3.7"
+ "perc": "3.2"
},
{
"api": 9,
@@ -173,7 +173,7 @@
{
"api": 10,
"name": "Gingerbread",
- "perc": "38.4"
+ "perc": "36.4"
},
{
"api": 13,
@@ -183,17 +183,17 @@
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "27.5"
+ "perc": "25.6"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "26.1"
+ "perc": "29.0"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "2.3"
+ "perc": "4.0"
}
]
}
@@ -205,35 +205,34 @@
var SCREEN_DATA =
[
-
{
"data": {
"Large": {
"hdpi": "0.4",
"ldpi": "0.6",
- "mdpi": "2.9",
+ "mdpi": "3.0",
"tvdpi": "1.0",
- "xhdpi": "0.7"
+ "xhdpi": "0.6"
},
"Normal": {
- "hdpi": "37.3",
+ "hdpi": "36.0",
"ldpi": "0.1",
- "mdpi": "16.1",
- "xhdpi": "24.9",
- "xxhdpi": "1.3"
+ "mdpi": "16.0",
+ "xhdpi": "24.5",
+ "xxhdpi": "3.3"
},
"Small": {
- "ldpi": "9.8"
+ "hdpi": "0.1",
+ "ldpi": "9.9"
},
"Xlarge": {
- "hdpi": "0.1",
- "ldpi": "0.2",
- "mdpi": "4.5",
+ "hdpi": "0.2",
+ "mdpi": "4.2",
"xhdpi": "0.1"
}
},
- "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chf=bg%2Cs%2C00000000&chd=t%3A10.7%2C23.5%2C1.0%2C37.8%2C25.7%2C1.3&chco=c4df9b%2C6fad0c&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
- "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chf=bg%2Cs%2C00000000&chd=t%3A4.9%2C5.6%2C79.7%2C9.8&chco=c4df9b%2C6fad0c&chl=Xlarge%7CLarge%7CNormal%7CSmall"
+ "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A10.6%2C23.2%2C1.0%2C36.7%2C25.2%2C3.3&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250",
+ "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.5%2C5.6%2C79.9%2C10.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250"
}
];
diff --git a/docs/html/about/index.jd b/docs/html/about/index.jd
index 0b72701..1573cc3 100644
--- a/docs/html/about/index.jd
+++ b/docs/html/about/index.jd
@@ -1,4 +1,5 @@
page.title=Android, the world's most popular mobile platform
+excludeFromSuggestions=true
walkthru=0
header.hide=0
diff --git a/docs/html/about/start.jd b/docs/html/about/start.jd
index fbe70e3..727c975 100644
--- a/docs/html/about/start.jd
+++ b/docs/html/about/start.jd
@@ -1,4 +1,5 @@
page.title=Get Started
+excludeFromSuggestions=true
walkthru=0
@jd:body
diff --git a/docs/html/channels/io2013.jd b/docs/html/channels/io2013.jd
new file mode 100644
index 0000000..977eb2f
--- /dev/null
+++ b/docs/html/channels/io2013.jd
@@ -0,0 +1,346 @@
+fullpage=true
+page.title=Google I/O 13
+@jd:body
+
+<style>
+#ioplayer-frame {
+ z-index:10;
+ width:703px;
+ height:396px;
+ margin:0;
+ position:relative;
+}
+
+#noplayer-message {
+ position:absolute;
+ top:50%;left:0;
+ width:100%;
+ z-index:-1;
+ text-align:center;
+ display:none;
+}
+
+h1 {
+ font-weight:100;
+ font-size:40px;
+ line-height:30px;
+ margin:30px 0 10px 0px;
+ color:#000;
+}
+
+h2 {
+ font-weight:100;
+ font-size:30px;
+ line-height:30px;
+ margin:12px 0 10px 0px;
+ color:#000;
+ float:left;
+ display:block;
+}
+
+.col-4 h2 {
+ margin-top:40px;
+}
+
+ul.videos {
+ list-style:none;
+ margin:0;
+ width:auto;
+}
+ul.videos li {
+ display:block;
+ float:left;
+ position:relative;
+ margin:0 2px 2px 0;
+ background-repeat:no-repeat !important;
+ background-size:320px auto;
+ background-position:10% 50%;
+ z-index:1; /* IE: the description is 2 */
+}
+ul.videos li a {
+ color:#fff !important;
+ display:block;
+ margin:0;
+ padding:8px 12px;
+ width:209px;
+ height:134px;
+ box-shadow:inset 500px 500px 999px rgba(000, 000, 000, 0.2);
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,0.8)), color-stop(1, transparent));
+ background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.8), transparent);
+ background-image: -moz-linear-gradient(top, rgba(0,0,0,0.8), transparent);
+ background-image: -o-linear-gradient(top, rgba(0,0,0,0.8), transparent);
+ background-image: linear-gradient(to bottom, rgba(0,0,0,0.8), transparent);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc000000', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */
+}
+ul.videos.featured li {
+ margin:0 0 2px;
+}
+ul.videos.featured li a {
+ margin:0;
+ height:115px;
+}
+ul.videos li a:hover {
+ box-shadow:inset 500px 500px 999px rgba(255,255,255, 0.6);
+}
+ul.videos li h4 {
+ text-shadow:1px 1px 0 rgba(0,0,0,0.8);
+ font-size:18px;
+ line-height:22px;
+ color:#fff;
+ margin:0;
+ height:100%; /* IE: to fill clickable area */
+}
+
+ul.videos li .description-frame {
+ display:none;
+ z-index:2; /* IE: the li is 1 */
+}
+ul.videos li a:hover .description-frame {
+ display:block;
+ position:absolute;
+ top:80px;
+ left:8px;
+ z-index:99;
+}
+ul.videos .description {
+ background:#fff;
+ width:200px;
+ padding:8px;
+ -webkit-border-radius:1px;
+ -moz-border-radius:1px;
+ border-radius:1px;
+ -moz-box-shadow: 0 2px 3px 2px rgba(000,000,000, 0.4);
+ -webkit-box-shadow: 0 2px 3px 2px rgba(000,000,000, 0.4);
+ box-shadow: 0 2px 3px 2px rgba(000,000,000, 0.4);
+ font-size:11px;
+ line-height:12px;
+ color:#000;
+ overflow:hidden;
+}
+ul.videos .arrow-up {
+ position:absolute;
+ left:15px;
+ top:-11px;
+ width:0;
+ height:0;
+ border-bottom:12px solid #fff;
+ border-left:12px solid transparent;
+ border-right:12px solid transparent;
+}
+ul.videos .arrow-down {
+ position:absolute;
+ left:15px;
+ bottom:-11px;
+ width:0;
+ height:0;
+ border-top:12px solid #fff;
+ border-left:12px solid transparent;
+ border-right:12px solid transparent;
+}
+
+ul.videos span.tag {
+ font-size:.9em;
+ font-weight:normal;
+ display: block;
+ position: absolute;
+ bottom: 0;
+ color: #fff;
+ left: 0;
+ padding: 4px;
+ border-top-right-radius:4px;
+ text-transform:uppercase;
+ text-shadow: none;
+}
+ul.videos span.tag.design {
+ background-color:rgba(51, 181, 229, .7);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc33b5e5', endColorstr='#cc33b5e5',GradientType=0 ); /* IE6-9 */
+}
+ul.videos span.tag.develop {
+ background-color:rgba(255, 136, 0, .7);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ccff8800', endColorstr='#ccff8800',GradientType=0 ); /* IE6-9 */
+}
+ul.videos span.tag.distribute {
+ background-color:rgba(153, 204, 0, .7);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc99cc00', endColorstr='#cc99cc00',GradientType=0 ); /* IE6-9 */
+}
+
+</style>
+
+
+
+
+
+
+
+<div class="wrap">
+
+ <div class="col-12" style="width:704px;margin:0">
+ <h1>Android @ Google I/O 13</h1>
+ <div id="ioplayer-frame">
+ <div id="noplayer-message">
+ <!-- busted flash player message -->
+ Your video is supposed to appear here.<br/>
+ Make sure you have the <a href="//get.adobe.com/flashplayer/" target="_blank">Flash® Player</a>.
+ </div>
+ <div id="player"><!-- Youtube embeds here... actually replaces this div --></div>
+ </div>
+ </div>
+
+ <div class="col-4" style="margin:0;width:234px;padding:0 0 0 2px">
+ <h2 class="norule">Most Popular</h2>
+ <ul class="videos featured" id="playlist2">
+ </ul>
+ </div>
+</div>
+
+<div class="wrap">
+
+ <div style="position:absolute;width:940px;text-align:right">
+ <a href="//www.youtube.com/AndroidDevelopers" target="_blank">
+ More on YouTube
+ <img src="//www.youtube.com/favicon.ico" style="border:0;width:16px;height:16px;vertical-align:middle;margin:0 2px 3px 2px">
+ </a>
+ </div>
+ <div style="width:944px;overflow:hidden;padding:0 0 20px">
+ <h2 class="norule">All Videos</h2>
+ <ul class="videos" id="playlist1" style="clear:left">
+ <span id="videos-design"></span>
+ <span id="videos-develop"></span>
+ <span id="videos-distribute"></span>
+ </ul>
+ </div>
+
+</div>
+
+<br class="clearfix"/>
+
+
+
+
+
+
+
+
+
+
+
+<script src="//swfobject.googlecode.com/svn/trunk/swfobject/swfobject.js" type="text/javascript"></script>
+<script type="text/javascript">
+
+/* Load a video into the player box.
+ * @param id The YouTube video ID
+ * @param title The video title to display in the player box (character escaped)
+ * @param autoplay Whether to automatically play the video
+ */
+function loadVideo(id, title, autoplay) {
+ var url = '//www.youtube.com/v/' + id + '&rel=1&border=0&fs=1' + (autoplay?'&autoplay=1':'');
+ swfobject.embedSWF(url, 'player', '704', '397', '9.0.0', false, false, {allowfullscreen: 'true'});
+ $('body,html').animate({ scrollTop: 0 }, "slow");
+ setTimeout(function(){$('#noplayer-message').show()}, 2000);
+}
+
+
+function buildPlaylistDesign(data) {
+ buildPlaylist(data, $('ul#playlist1 #videos-design'), "design");
+}
+
+function buildPlaylistDevelop(data) {
+ buildPlaylist(data, $('ul#playlist1 #videos-develop'), "develop");
+}
+
+function buildPlaylistDistribute(data) {
+ buildPlaylist(data, $('ul#playlist1 #videos-distribute'), "distribute");
+}
+
+function buildPlaylist2(data) {
+ buildPlaylist(data, $('ul#playlist2'));
+}
+
+function buildPlaylist(data, ul, tag) {
+
+ var MAX_DESC_LENGTH = 200; // the length at which we will trim the description
+ var feed = data.feed;
+ var entries = feed.entry || [];
+ var playlistId = feed.yt$playlistId.$t;
+
+ // Loop through each entry (each video) and add it to the '#DevelopersLive' list
+ for (var i = 0; i < entries.length; i++) {
+ var entry = entries[i];
+ var title = entry.title.$t;
+ var id = entry.media$group.yt$videoid.$t;
+ // get 180x320 thumbnail
+ var thumbs = entry.media$group.media$thumbnail;
+ var thumbUrl;
+ for (var j = 0; j < thumbs.length; j++) {
+ if (thumbs[j].yt$name == "hqdefault") {
+ thumbUrl = thumbs[j].url;
+ }
+ }
+
+ // chop out the google io title
+ title = title.substr(title.indexOf("-") + 1, title.length);
+
+ var fullDescription = entry.media$group.media$description.$t;
+ var playerUrl = entry.media$group.media$content[0].url;
+ var shortDescription = fullDescription.substr(0, MAX_DESC_LENGTH);
+ // further shorten description if there's a url (remove it)
+ var httpindex = shortDescription.indexOf("http://");
+ if (httpindex != -1) {
+ shortDescription = shortDescription.substring(0,httpindex);
+ }
+ shortDescription += shortDescription.length == MAX_DESC_LENGTH ? "..." : ""; // add ellipsis if we've chopped the description
+
+ var a = $('<a href="#" id="' + id + '" '
+ + 'onclick="loadVideo(\'' + id + '\',\'' + escape(title) + '\',true); return false;" />');
+ var pShortDescription = $('<div class="description-frame"><div class="arrow-up"></div>'
+ + '<div class="description">' + shortDescription + '</div></div>');
+ var h4Title = "<h4>" + title + "</h4>";
+ var li = $('<li style="background-image:url(\'' + thumbUrl +'\')" />');
+
+ li.append(a);
+ a.append(h4Title).append(pShortDescription);
+
+ if (tag !== undefined) {
+ var $tag = $('<span class="tag ' + tag + '">' + tag + '</span>');
+ a.append($tag);
+ }
+
+ ul.append(li);
+
+
+ // put the first video in the player
+ if ((tag == "design") && (i == 0)) {
+ loadVideo(id, escape(title), false);
+ }
+ }
+}
+
+
+/* Request the playlist feeds from YouTube */
+function showDevelopersLivePlaylist() {
+ var playlistId = "PLWz5rJ2EKKc-qVhMuAprIFYFbCotdgJKq"; /* IO 13 - Design */
+ $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+ + playlistId +
+ "?v=2&alt=json-in-script&max-results=50&callback=buildPlaylistDesign&orderby=position");
+
+ playlistId = "PLWz5rJ2EKKc9rkwO9yBosRvkQBJd5utmR"; /* IO 13 - Develop */
+ $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+ + playlistId +
+ "?v=2&alt=json-in-script&max-results=50&callback=buildPlaylistDevelop&orderby=position");
+
+ playlistId = "PLWz5rJ2EKKc-1WjgQqL0B4OQtbLfhMlB2"; /* IO 13 - Distribute */
+ $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+ + playlistId +
+ "?v=2&alt=json-in-script&max-results=50&callback=buildPlaylistDistribute&orderby=position");
+
+
+ playlistId = "PLWz5rJ2EKKc9WGUwq2gQ-coU3fSyexgOx"; /* IO 13 - The Android Sessions */
+ $.getScript("//gdata.youtube.com/feeds/api/playlists/"
+ + playlistId +
+ "?v=2&alt=json-in-script&max-results=3&callback=buildPlaylist2&orderby=viewCount");
+}
+
+showDevelopersLivePlaylist();
+
+
+</script>
\ No newline at end of file
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 886677a..5acf60d 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -1,4 +1,4 @@
-page.title=Google Cloud Messaging for Android
+page.title=GCM Architectural Overview
@jd:body
<div id="qv-wrapper">
diff --git a/docs/html/google/play-services/gcm.jd b/docs/html/google/play-services/gcm.jd
index 67b55ea..a9da73f 100644
--- a/docs/html/google/play-services/gcm.jd
+++ b/docs/html/google/play-services/gcm.jd
@@ -1,4 +1,4 @@
-page.title=GCM Extensions for Android
+page.title=GCM Extensions
page.tags="cloud","push","messaging"
header.hide=1
@jd:body
diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd
index 2342087..069a603 100644
--- a/docs/html/guide/appendix/media-formats.jd
+++ b/docs/html/guide/appendix/media-formats.jd
@@ -1,4 +1,4 @@
-page.title=Android Supported Media Formats
+page.title=Supported Media Formats
page.tags="video","audio","mpeg","mp4","m4a","mp3","3gp","3gpp","flac","wave","wav"
@jd:body
diff --git a/docs/html/guide/faq/commontasks.jd b/docs/html/guide/faq/commontasks.jd
index 7b90de2..086721f 100644
--- a/docs/html/guide/faq/commontasks.jd
+++ b/docs/html/guide/faq/commontasks.jd
@@ -1,6 +1,5 @@
page.title=Common Tasks and How to Do Them in Android
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
@jd:body
<ul>
diff --git a/docs/html/guide/faq/framework.jd b/docs/html/guide/faq/framework.jd
index 4a7a3fc..c851e72 100644
--- a/docs/html/guide/faq/framework.jd
+++ b/docs/html/guide/faq/framework.jd
@@ -1,6 +1,5 @@
page.title=Android Application Framework FAQ
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
@jd:body
<ul>
diff --git a/docs/html/guide/faq/index.jd b/docs/html/guide/faq/index.jd
index 9a2614b..0c5fb0e 100644
--- a/docs/html/guide/faq/index.jd
+++ b/docs/html/guide/faq/index.jd
@@ -1,4 +1,5 @@
page.title=Android FAQs
+excludeFromSuggestions=true
@jd:body
<dl>
diff --git a/docs/html/guide/faq/licensingandoss.jd b/docs/html/guide/faq/licensingandoss.jd
index c267fe81..d1dd9a7 100644
--- a/docs/html/guide/faq/licensingandoss.jd
+++ b/docs/html/guide/faq/licensingandoss.jd
@@ -1,6 +1,5 @@
page.title=Android Open Source Licensing FAQ
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
@jd:body
<ul>
diff --git a/docs/html/guide/faq/security.jd b/docs/html/guide/faq/security.jd
index a6e07c8..96fc7f5 100644
--- a/docs/html/guide/faq/security.jd
+++ b/docs/html/guide/faq/security.jd
@@ -1,6 +1,5 @@
page.title=Android Security FAQ
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
@jd:body
<ul>
diff --git a/docs/html/guide/faq/troubleshooting.jd b/docs/html/guide/faq/troubleshooting.jd
index f19f5ec..8bb7eeb 100644
--- a/docs/html/guide/faq/troubleshooting.jd
+++ b/docs/html/guide/faq/troubleshooting.jd
@@ -1,6 +1,5 @@
page.title=Troubleshooting
-parent.title=FAQs, Tips, and How-to
-parent.link=index.html
+excludeFromSuggestions=true
@jd:body
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index ff35d2e..5f9f530 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -76,9 +76,16 @@
<span class="en">Permissions</span>
</a>
</li>
- <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
<span class="en">App Widgets</span>
- </a></li>
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>guide/topics/appwidgets/host.html">
+ <span class="en">App Widget Host</span>
+ </a></li>
+ </ul>
+ </li>
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-intro.html">
<span class="en">Android Manifest</span>
diff --git a/docs/html/guide/topics/appwidgets/host.jd b/docs/html/guide/topics/appwidgets/host.jd
new file mode 100644
index 0000000..da7408f
--- /dev/null
+++ b/docs/html/guide/topics/appwidgets/host.jd
@@ -0,0 +1,392 @@
+page.title=App Widget Host
+page.tags="AppWidgetHost","home screen","launcher"
+@jd:body
+
+<div id="qv-wrapper">
+ <div id="qv">
+
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#host-binding">Binding App Widgets</a>
+ <ol>
+ <li><a href="#binding-pre">Binding app widgets on Android 4.0 and lower</a></li>
+ <li><a href="#binding-41">Binding app widgets on Android 4.1 and higher</a></li>
+ </ol>
+ </li>
+ <li><a href="#host-state">Host Responsibilities</a>
+ <ol>
+ <li><a href="#30">Android 3.0</a></li>
+ <li><a href="#31">Android 3.1</a></li>
+ <li><a href="#40">Android 4.0</a></li>
+ <li><a href="#41">Android 4.1</li>
+ <li><a href="#42">Android 4.2</a></li>
+ </ol>
+ </li>
+ </ol>
+ </div>
+</div>
+
+
+<p>The Android Home screen available on most Android devices allows the user
+to embed <a href="{@docRoot}guide/topics/appwidgets/index.html">app widgets</a> for quick
+access to content. If you're building a Home replacement or a similar app,
+you can also allow the user to embed app widgets by implementing an
+{@link android.appwidget.AppWidgetHost}.
+This is not something that most apps will ever need to do, but if you are
+creating your own host, it's important to understand the contractual obligations
+a host implicitly agrees to.</p>
+
+<p>This document focuses on the responsibilities involved in implementing a custom
+{@link android.appwidget.AppWidgetHost}. For an example of how to implement an
+{@link android.appwidget.AppWidgetHost}, see the source code for the
+Android Home screen
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java">
+Launcher</a>.
+
+
+<p>Here is an overview of key classes and concepts involved in implementing a custom
+{@link android.appwidget.AppWidgetHost}:</p>
+<ul>
+ <li><strong>App Widget Host</strong>—
+ The {@link android.appwidget.AppWidgetHost} provides the interaction
+with the AppWidget service for apps, like the home screen, that want to embed
+app widgets in their UI. An {@link android.appwidget.AppWidgetHost} must have
+an ID that is unique within the host's own package. This ID remains persistent
+across all uses of the host. The ID is typically a hard-coded value that you assign
+in your application.</li>
+
+ <li><strong>App Widget ID</strong>—
+ Each app widget instance is assigned a unique ID at the time of binding
+(see {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()},
+discussed in more detail in <a href="#binding">Binding app widgets</a>).
+The unique ID is obtained by the host using {@link android.appwidget.AppWidgetHost#allocateAppWidgetId() allocateAppWidgetId()}. This ID is persistent across the lifetime of the widget,
+that is, until it is deleted from the host. Any host-specific state (such as the
+size and location of the widget) should be persisted by the hosting package and
+associated with the app widget ID.
+</li>
+
+ <li><strong>App Widget Host View</strong>—
+ {@link android.appwidget.AppWidgetHostView} can be thought of as a frame
+that the widget is wrapped in whenever it needs to be displayed. An app widget
+is assigned to an {@link android.appwidget.AppWidgetHostView} every time the
+widget is inflated by the host. </li>
+ <li><strong>Options Bundle</strong>—
+The {@link android.appwidget.AppWidgetHost} uses the options bundle to communicate
+information to the {@link android.appwidget.AppWidgetProvider} about how the
+widget is being displayed (for example, size range, and whether the widget is on
+a lockscreen or the home screen). This information allows the
+{@link android.appwidget.AppWidgetProvider} to tailor the widget's contents
+and appearance based on how and where it is displayed.
+You use
+{@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions(android.os.Bundle) updateAppWidgetOptions()}
+and
+{@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}
+
+to modify an app widget's
+bundle. Both of these methods trigger a callback to the
+{@link android.appwidget.AppWidgetProvider}.</p></li>
+</ul>
+
+<h2 id="host-binding">Binding App Widgets</h2>
+
+<p>When a user adds an app widget to a host, a process called
+<em>binding</em> occurs. <em>Binding</em> refers to associating
+a particular app widget ID to a specific host and to a specific
+{@link android.appwidget.AppWidgetProvider}. There are different
+ways of achieving this, depending on what version of Android your
+app is running on.</p>
+
+<h3 id="binding-pre">Binding app widgets on Android 4.0 and lower</h3>
+
+<p>On devices running Android version 4.0 and lower, users add app widgets
+via a system activity that allows users to select a widget. This implicitly
+does a permission check—that is, by adding the app widget, the user is
+implicitly granting permission to your app to add app widgets to the host.
+Here is an example that illustrates
+this approach, taken from the original
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">Launcher</a>. In this snippet, an event handler invokes
+{@link android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()}
+with the request code {@code REQUEST_PICK_APPWIDGET} in response to a
+user action:</p>
+
+<pre>
+private static final int REQUEST_CREATE_APPWIDGET = 5;
+private static final int REQUEST_PICK_APPWIDGET = 9;
+...
+public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ ...
+ case AddAdapter.ITEM_APPWIDGET: {
+ ...
+ int appWidgetId =
+ Launcher.this.mAppWidgetHost.allocateAppWidgetId();
+ Intent pickIntent =
+ new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
+ pickIntent.putExtra
+ (AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ ...
+ startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
+ break;
+ }
+ ...
+}</pre>
+
+<p>When the system activity finishes, it returns a result with the user's chosen
+app widget to your activity. In the following example, the activity responds
+by calling {@code addAppWidget()} to add the app widget:</p>
+
+<pre>public final class Launcher extends Activity
+ implements View.OnClickListener, OnLongClickListener {
+ ...
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mWaitingForResult = false;
+
+ if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
+ switch (requestCode) {
+ ...
+ case REQUEST_PICK_APPWIDGET:
+ addAppWidget(data);
+ break;
+ case REQUEST_CREATE_APPWIDGET:
+ completeAddAppWidget(data, mAddItemCellInfo, !mDesktopLocked);
+ break;
+ }
+ }
+ ...
+ }
+}</pre>
+
+<p>The method {@code addAppWidget()} checks to see if the app widget
+needs to be configured before it's added:</p>
+
+<pre>void addAppWidget(Intent data) {
+ int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+
+ String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);
+ AppWidgetProviderInfo appWidget =
+ mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+
+ if (appWidget.configure != null) {
+ // Launch over to configure widget, if needed.
+ Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+ intent.setComponent(appWidget.configure);
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
+ } else {
+ // Otherwise, finish adding the widget.
+ }
+}</pre>
+
+<p>For more discussion of configuration,
+see <a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating an
+App Widget Configuration Activity</a>.</p>
+
+<p>Once the app widget is ready, the next step is to do the
+actual work of adding it to the workspace. The
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">original Launcher</a> uses a method called {@code completeAddAppWidget()}
+to do this.</p>
+
+<h3 id="binding-41">Binding app widgets on Android 4.1 and higher</h3>
+
+<p>Android 4.1 adds APIs for a more streamlined binding process.
+These APIs also make it possible for a host to provide a custom UI for
+binding. To use this improved process, your app must declare the
+{@link android.Manifest.permission#BIND_APPWIDGET} permission in its manifest:</p>
+
+<pre><uses-permission android:name="android.permission.BIND_APPWIDGET" />
+</pre>
+
+
+<p>But this is just the first step. At runtime the user must
+explicitly grant permission to your app to allow it to add app widgets
+to the host. To test whether your app has permission to add the widget,
+you use the
+{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}
+method.
+If {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}
+returns {@code false}, your app must display a dialog prompting the
+user to grant permission
+("allow" or "always allow," to cover all future app widget additions).
+This snippet gives an example of how to display the dialog:</p>
+
+<pre>Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
+intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
+// This is the options bundle discussed above
+intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
+</pre>
+
+<p>The host also has to check whether the user added
+an app widget that needs configuration. For more discussion of this topic,
+see
+<a href="{@docRoot}guide/topics/appwidgets/index.html#Configuring">Creating
+an App Widget Configuration Activity</a>.</p>
+
+<h2 id="host-state">Host Responsibilities</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h2>What Version are You Targeting?</h2>
+ <p>The approach you use in implementing your host should depend on what Android version
+you're targeting. Many of the features described in this section were introduced
+in 3.0 or later. For example:</p>
+<ul>
+<li>Android 3.0 (API Level 11) introduces auto-advance behavior for widgets.</li>
+<li>Android 3.1 (API Level 12) introduces the ability to resize widgets.</li>
+<li>Android 4.0 (API Level 15) introduces a change in padding policy that
+puts the responsibility on the
+host to manage padding.</li>
+<li>Android 4.1 (API Level 16) adds an API that allows the widget provider
+to get more detailed information about the environment in which its
+widget instances are being hosted.</li>
+<li>Android 4.2 (API Level 17) introduces the options bundle and the
+{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int,android.content.ComponentName,android.os.Bundle) bindAppWidgetIdIfAllowed()}
+method. It also introduces lockscreen widgets.</li>
+</ul>
+<p>If you are targeting earlier devices, refer to the original
+<a href="https://android.googlesource.com/platform/packages/apps/Launcher/+/master/src/com/android/launcher/Launcher.java">Launcher</a> as an example.
+</div>
+</div>
+
+<p>Widget developers can specify a number of configuration settings
+for widgets using the <a href="{@docRoot}guide/topics/appwidgets/index.html#MetaData">
+AppWidgetProviderInfo metadata</a>.
+These configuration options, discussed in more detail below, can be
+retrieved by the host from the {@link android.appwidget.AppWidgetProviderInfo}
+object associated with a widget provider.</p>
+
+<p>Regardless of the version of Android you are targeting, all hosts
+have the following responsibilities:</p>
+
+<ul>
+<li>When adding a widget, you must allocate the widget ID as described above.
+You must also make sure that when a widget is removed from the host, you call {@link android.appwidget.AppWidgetHost#deleteAppWidgetId deleteAppWidgetId()}
+to deallocate the widget ID.</li>
+
+<li>When adding a widget, be sure to launch its configuration activity
+if it exists, as described in
+<a href="{@docRoot}guide/topics/appwidgets/index.html#UpdatingFromTheConfiguration">
+Updating the App Widget
+from the Configuration Activity</a>. This is a necessary step for many app widgets before
+they can be properly displayed.</li>
+
+<li>Every app widget specifies a minimum width and height in dps, as defined in the {@link android.appwidget.AppWidgetProviderInfo} metadata
+(using {@link android.appwidget.AppWidgetProviderInfo#minWidth android:minWidth} and
+{@link android.appwidget.AppWidgetProviderInfo#minHeight android:minHeight}).
+Make sure that the widget is laid out with at least this many dps.
+For example, many hosts align icons and widgets in a grid. In this scenario,
+by default the host should add the app widget using the minimum number of
+cells that satisfy the {@code minWidth} and {@code minHeight} constraints.</li>
+
+</ul>
+
+<p>In addition to the requirements listed above, specific platform
+versions introduce features that place new responsibilities on the
+host. These are described in the following sections.</p>
+
+<h3 id="30">Android 3.0</h3>
+
+<p>Android 3.0 (API Level 11) introduces the ability for a widget to specify {@link android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId autoAdvanceViewId()}.
+This view ID should point to an instance of an
+{@link android.widget.Advanceable}, such as {@link android.widget.StackView}
+or {@link android.widget.AdapterViewFlipper}. This indicates that the host
+should call {@link android.widget.Advanceable#advance advance()} on this
+view at an interval deemed appropriate by the host (taking into account whether
+it makes sense to advance the widget—for example, the host probably
+wouldn't want to advance a widget if it were on another page, or
+if the screen were turned off).</p>
+
+<h3 id="31">Android 3.1</h3>
+
+<p>Android 3.1 (API Level 12) introduces the ability to resize widgets.
+A widget can specify that it is resizable using the
+{@link android.appwidget.AppWidgetProviderInfo#resizeMode android:resizeMode}
+attribute in the {@link android.appwidget.AppWidgetProviderInfo}
+metadata, and indicate whether it supports horizontal and/or
+vertical resizing. Introduced in Android 4.0 (API Level 14), the widget can also specify a
+{@link android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
+and/or {@link android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.</p>
+
+<p>It is the host’s responsibility to make it possible for the
+widget to be resized horizontally and/or vertically, as specified
+by the widget. A widget that specifies that it is resizable can be
+resized arbitrarily large, but should not be resized smaller than
+the values specified by {@link
+android.appwidget.AppWidgetProviderInfo#minResizeWidth android:minResizeWidth}
+and {@link
+android.appwidget.AppWidgetProviderInfo#minResizeHeight android:minResizeHeight}.
+For a sample implementation, see <a href="https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/AppWidgetResizeFrame.java">
+{@code AppWidgetResizeFrame}</a> in {@code Launcher2}.</p>
+
+
+<h3 id="40">Android 4.0</h3>
+
+<p>Android 4.0 (API Level 15) introduces a change in padding policy that
+puts the responsibility on the host to manage padding. As of 4.0, app
+widgets no longer include their own padding. Instead, the system adds
+padding for each widget, based the characteristics of the current screen.
+This leads to a more uniform, consistent presentation of widgets in a grid.
+To assist applications that host app widgets, the platform provides
+the method
+{@link android.appwidget.AppWidgetHostView#getDefaultPaddingForWidget getDefaultPaddingForWidget()}.
+Applications can call this method to get the system-defined padding
+and account for it when computing the number of cells to allocate to the widget.</p>
+
+<h3 id="41">Android 4.1</h3>
+
+<p>Android 4.1 (API Level 16) adds an API that allows the widget provider
+to get more detailed information about the environment in which its
+widget instances are being hosted. Specifically, the host hints to the
+widget provider about the size at which the widget is being displayed.
+It is the host’s responsibility to provide this size information.</p>
+
+<p>The host provides this information via
+{@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()}.
+The size is specified as a minimum and maximum width/height in dps.
+The reason that a range is specified (as opposed to a fixed size)
+is because the width and height of a widget may change with orientation.
+You don’t want the host to have to update all of its widgets on rotation,
+as this could cause serious system slowdown. These values should be
+updated once upon the widget being placed, any time the widget is resized,
+and any time the launcher inflates the widget for the first time in a
+given boot (as the values aren’t persisted across boot).</p>
+
+
+<h3 id="42">Android 4.2</h3>
+
+<p>Android 4.2 (API Level 17) adds the ability for the options bundle
+to be specified at bind time. This is the ideal way to specify app
+widget options, including size, as it gives the {@link
+android.appwidget.AppWidgetProvider} immediate access to the options
+data on the first update. This can be achieved by using the method {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int,android.content.ComponentName,android.os.Bundle) bindAppWidgetIdIfAllowed()}. For more discussion of this topic,
+see <a href="#host-binding">Binding app widgets</a>.</p>
+
+<p>Android 4.2 also introduces lockscreen widgets. When hosting widgets
+on the lockscreen, the host must specify this information within the app
+widget options bundle (the {@link
+android.appwidget.AppWidgetProvider} can use this information to style
+the widget appropriately). To designate a widget as a lockscreen widget, use {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions updateAppWidgetOptions()}
+and include the field
+{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_HOST_CATEGORY}
+with the value {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
+This option defaults to
+{@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN},
+so it is not explicitly required to set this for a home screen host.</p>
+
+<p>Make sure that your host adds only app widgets that are appropriate
+for your app—for example, if your host is a home screen, ensure
+that the
+{@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory}
+attribute in the
+{@link android.appwidget.AppWidgetProviderInfo} metadata includes
+the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN}.
+Similarly, for the lockscreen, ensure that field includes the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. For more
+discussion of this topic, see
+<a href="{@docRoot}guide/topics/appwidgets/index.html#lockscreen">
+Enabling App Widgets on the Lockscreen</a>.</p>
+
+
+
+
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 774c66a..d8ad844 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -22,15 +22,16 @@
<ol>
<li><a href="#UpdatingFromTheConfiguration">Updating the App Widget
from
- the configuration Activity</a></li>
+ the Configuration Activity</a></li>
</ol>
</li>
<li><a href="#preview">Setting a Preview Image</a></li>
- <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen
+ <li><a href="#lockscreen">Enabling App Widgets on the Lockscreen</a>
<ol>
- <li><a href="#lockscreen-sizing">Sizing guidelines</li>
+ <li><a href="#lockscreen-sizing">Sizing guidelines</a></li>
</ol>
</li>
+
<li><a href="#collections">Using App Widgets with Collections</a>
<ol>
<li><a href="#collection_sample">Sample application</a></li>
@@ -66,7 +67,9 @@
<img src="{@docRoot}images/appwidgets/appwidget.png" alt="" />
<p>This document describes how to publish an App Widget using an App Widget
-provider.</p>
+provider. For a discussion of creating your own {@link android.appwidget.AppWidgetHost}
+to host app widgets, see <a href="{@docRoot}guide/topics/appwidgets/host.html">
+App Widget Host</a>.</p>
<div class="note design">
<p><strong>Widget Design</strong></p>
@@ -100,7 +103,7 @@
and allows him or her
to modify App Widget settings at create-time.</p>
-<p>The following sections describe how to setup each of these components.</p>
+<p>The following sections describe how to set up each of these components.</p>
<h2 id="Manifest">Declaring an App Widget in the Manifest</h2>
@@ -165,8 +168,8 @@
<pre>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="294dp"
- android:minHeight="72dp"
+ android:minWidth="40dp"
+ android:minHeight="40dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/preview"
android:initialLayout="@layout/example_appwidget"
@@ -270,6 +273,14 @@
To declare a widget as resizeable horizontally and vertically, supply the value
"horizontal|vertical". Introduced in Android 3.1.</li>
+<li>The <code>minResizeHeight</code> attribute specifies the minimum height (in dps) to which
+the widget can be resized. This field has no effect if it is greater than {@code minHeight} or if
+vertical resizing isn't enabled (see <code>resizeMode</code>). Introduced in Android 4.0.</li>
+
+<li>The <code> minResizeWidth </code> attribute specifies the minimum width (in dps) to which
+the widget can be resized. This field has no effect if it is greater than {@code minWidth} or if
+horizontal resizing isn't enabled (see <code>resizeMode</code>). Introduced in Android 4.0.</li>
+
<li>The <code>widgetCategory</code> attribute declares whether your App Widget can be displayed on the home screen,
the lock screen (keyguard), or both. Values for this attribute include "home_screen" and "keyguard". A widget that
is displayed on both needs to ensure that it follows the design guidelines for both widget classes. For more
@@ -788,12 +799,12 @@
<h2 id="collections">Using App Widgets with Collections</h2>
-<p>Android 3.0 introduces App Widgets with collections. These kinds of App
+<p>Android 3.0 introduces app widgets with collections. These kinds of App
Widgets use the {@link android.widget.RemoteViewsService} to display collections
that are backed by remote data, such as from a <a
href="{@docRoot}guide/topics/providers/content-providers.html">content
provider</a>. The data provided by the {@link android.widget.RemoteViewsService}
-is presented in the App Widget using one of the following view types, which
+is presented in the app widget using one of the following view types, which
we’ll refer to as “collection views:”</p>
<dl>
@@ -900,15 +911,15 @@
</ul>
<h3 id="implementing_collections">Implementing app widgets with collections</h3>
-<p>To implement an App Widget with collections, you follow the same basic steps
+<p>To implement an app widget with collections, you follow the same basic steps
you would use to implement any app widget. The following sections describe the
-additional steps you need to perform to implement an App Widget with
+additional steps you need to perform to implement an app widget with
collections.</p>
<h4>Manifest for app widgets with collections</h4>
<p> In addition to the requirements listed in <a href="#Manifest">Declaring an
-App Widget in the Manifest</a>, to make it possible for App Widgets with
+app widget in the Manifest</a>, to make it possible for app widgets with
collections to bind to your {@link android.widget.RemoteViewsService}, you must
declare the service in your manifest file with the permission {@link
android.Manifest.permission#BIND_REMOTEVIEWS}. This prevents other applications
@@ -987,7 +998,7 @@
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, and
the widget can serve up the appropriate data. When you call this method, you
must pass an intent that points to your implementation of {@link
-android.widget.RemoteViewsService} and the App Widget ID that specifies the app
+android.widget.RemoteViewsService} and the app widget ID that specifies the app
widget to update.</p>
@@ -1009,7 +1020,7 @@
// Add the app widget ID to the intent extras.
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
- // Instantiate the RemoteViews object for the App Widget layout.
+ // Instantiate the RemoteViews object for the app widget layout.
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
// Set up the RemoteViews object to use a RemoteViews adapter.
// This adapter connects
@@ -1367,15 +1378,15 @@
<h3 id="fresh">Keeping Collection Data Fresh</h3>
-<p>The following figure illustrates the flow that occurs in an App Widget that
+<p>The following figure illustrates the flow that occurs in an app widget that
uses
-collections when updates occur. It shows how the App Widget code interacts with
+collections when updates occur. It shows how the app widget code interacts with
the {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory}, and how you can trigger updates:</p>
<img src="{@docRoot}images/appwidgets/appwidget_collections.png" alt="" />
-<p>One feature of App Widgets that use collections is the ability to provide
+<p>One feature of app widgets that use collections is the ability to provide
users with up-to-date content. For example, consider the Android 3.0 Gmail
app widget, which provides users with a snapshot of their inbox. To make this
possible, you need to be able to trigger your {@link
diff --git a/docs/html/images/home/io-videos-2013.png b/docs/html/images/home/io-videos-2013.png
new file mode 100644
index 0000000..8655e8f
--- /dev/null
+++ b/docs/html/images/home/io-videos-2013.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 0799802..3435283 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -13,21 +13,25 @@
<div class="frame">
<ul>
<li class="item carousel-home">
- <div class="content-left col-10">
- <a href="https://developers.google.com/live/android/browse">
- <img src="{@docRoot}images/home/io-gdl-2013.png" style="margin:60px 0 0">
- </a>
+ <div class="content-left col-11" style="padding-top:10px;">
+ <a href="{@docRoot}channels/io2013.html">
+ <img src="{@docRoot}images/home/io-videos-2013.png" style="margin:60px 0 0;
+ box-shadow: 3px 10px 18px 1px #999;">
+ </a>
</div>
- <div class="content-right col-5">
+ <div class="content-right col-4">
<h1>Watch the Android talks from Google I/O</h1>
<p>If you weren't able to attend Google I/O in person or couldn't make it
to all the talks, you can catch up on the action
with all the recordings, brought to you by
<a href="http://developers.google.com/live">Google Developers Live</a>.</p>
- <p><a href="https://developers.google.com/live/android/browse" class="button"
+ <p><a href="{@docRoot}channels/io2013.html" class="button"
>See the Android talks</a></p>
</div>
</li>
+
+
+
<li class="item carousel-home">
<div class="content-left col-11" style="padding-top:65px;">
<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
diff --git a/docs/html/sdk/installing/migrate.jd b/docs/html/sdk/installing/migrate.jd
index d988a95..20a698b 100644
--- a/docs/html/sdk/installing/migrate.jd
+++ b/docs/html/sdk/installing/migrate.jd
@@ -15,26 +15,27 @@
<li>In Eclipse, select <strong>File > Export</strong>.</li>
<li>In the window that appears, open <strong>Android</strong> and select <strong>Generate Gradle
build files</strong>.</li>
-<li>Select the projects you want to export for Android Studio and click
+<li>Select the project you want to export for Android Studio and click
<strong>Finish</strong>.</li>
</ol>
-<p>Your selected projects remain in the same location but now contain a {@code build.gradle}
-file and are ready for Android Studio.</p>
+<p>Your selected project remains in the same location but now contains a {@code build.gradle}
+file and is ready for Android Studio.</p>
<h2 id="Export">Import into Android Studio</h2>
<ol>
- <li>In Android Studio, select <strong>File > Import Project</strong>.</li>
- <li>Locate a project you exported from Eclipse, select the project's root directory and
- click <strong>OK</strong>.</li>
- <li>Select <strong>Create project from existing sources</strong> and click
- <strong>Next</strong>.</li>
- <li>Follow the walk-through to complete the import process.</li>
+ <li>In Android Studio, close any projects currently open. You should see the
+ <strong>Welcome to Android Studio</strong> window.</li>
+ <li>Click <strong>Import Project</strong>.</li>
+ <li>Locate the project you exported from Eclipse, expand it, select the
+ <strong>build.gradle</strong> file and click <strong>OK</strong>.</li>
+ <li>In the following dialog, leave <strong>Use gradle wrapper</strong> selected and click
+ <strong>OK</strong>. (You do not need to specify the Gradle home.)</li>
</ol>
-<p>Now that your projects are imported to Android Studio,
+<p>Now that your project is imported to Android Studio,
read <a href="{@docRoot}sdk/installing/studio-tips.html">Tips and Tricks</a> for some
help getting started.</p>
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index fda233d..ea1549d 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -1,6 +1,4 @@
-page.title=Using the Android Emulator
-parent.title=Managing Virtual Devices
-parent.link=index.html
+page.title=Using the Emulator
@jd:body
<div id="qv-wrapper">
diff --git a/docs/html/tools/extras/support-library.jd b/docs/html/tools/extras/support-library.jd
index 9cc0361..60168f4 100644
--- a/docs/html/tools/extras/support-library.jd
+++ b/docs/html/tools/extras/support-library.jd
@@ -565,7 +565,7 @@
<li>Proceed to install the package.</li>
</ol>
-<p>When done, all files (including source code, samples, and the {@code .jar} files) are saved
+<p>When done, all files (including source code, samples, and the JAR files) are saved
into the <code><sdk>/extras/android/support/</code> directory. This directory contains
each of the different support libraries, such as the library for API level 4 and up and the library
for API level 13 and up, each named with the respective version (such as {@code v4/}).</p>
@@ -574,20 +574,57 @@
<h2 id="SettingUp">Setting Up a Project to Use a Library</h2>
<p>To add one of the libraries to your Android project:</p>
+<dl>
+ <dt>
+ Add the JAR file to your project.
+ </dt>
+ <dd>
+ Copy the JAR file for the library you want to use into your Android project. To do this:
+ <ul>
+ <li>
+ Create the directory {@code libs/} at the root of your project
+ (next to {@code src/}, {@code res/}, and so forth).
+ </li>
+ <li>
+ Locate the JAR file for the library you want to use and copy it into the
+ {@code libs/} directory.
+ <p>
+ For example, the library that supports API level 4 and up is located at
+ {@code <sdk>/extras/android/support/v4/android-support-v4.jar}.
+ </p>
+ </li>
+ </ul>
+ <p>
+ Your build system may expect to find the JAR file in a directory other than
+ {@code libs}. Read the documentation for your build system to learn where to put the
+ JAR file.
+ </p>
+ </dd>
+ <dt>
+ If necessary, add the {@code libs/} directory to your build path.
+ </dt>
+ <dd>
+ Read the documentation for your build system to learn how to add the JAR file to the
+ build path.
+ </dd>
+</dl>
+<p>
+ To confirm that you've added the JAR file to the correct directory and added it to the build
+ path:
+</p>
<ol>
- <li>In your Android project, create a directory named {@code libs} at the root of your
-project (next to {@code src/}, {@code res/}, etc.)</li>
- <li>Locate the JAR file for the library you want to use and copy it into the {@code
-libs/} directory.
- <p>For example, the library that supports API level 4 and up is located at {@code
-<sdk>/extras/android/support/v4/android-support-v4.jar}.</p>
- </li>
- <li>Add the JAR to your project build path.
- <p>In Eclipse, right-click the JAR file in the Package Explorer, select <strong>Build
-Path</strong> > <strong>Add to Build Path</strong>.</p>
- </li>
+ <li>
+ Edit one of your source files to add an {@code import} statement that imports a
+ class from the {@code android.support.*} package.
+ </li>
+ <li>
+ Build your app. The code should compile cleanly.
+ </li>
+ <li>
+ As a double-check, run your app. It should run correctly, without any runtime exceptions
+ indicating that the class in {@code android.support.*} can't be found.
+ </li>
</ol>
-
<p>Your application is now ready to use the library APIs. All the
provided APIs are available in the {@code android.support} package (for
example, {@code android.support.v4}).</p>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index a63492e..6389880 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -53,7 +53,7 @@
<ul>
<li><a href="<?cs var:toroot ?>tools/devices/managing-avds.html"><span class="en">With AVD Manager</span></a></li>
<li><a href="<?cs var:toroot ?>tools/devices/managing-avds-cmdline.html"><span class="en">From the Command Line</span></a></li>
- <li><a href="<?cs var:toroot ?>tools/devices/emulator.html"><span class="en">Using the Android Emulator</span></a></li>
+ <li><a href="<?cs var:toroot ?>tools/devices/emulator.html"><span class="en">Using the Emulator</span></a></li>
</ul>
</li>
<li><a href="<?cs var:toroot ?>tools/device.html"><span class="en">Using Hardware Devices</span></a></li>
diff --git a/docs/html/training/location/receive-location-updates.jd b/docs/html/training/location/receive-location-updates.jd
index eb4ffa3..c33f075 100644
--- a/docs/html/training/location/receive-location-updates.jd
+++ b/docs/html/training/location/receive-location-updates.jd
@@ -567,7 +567,12 @@
protected void onStop() {
// If the client is connected
if (mLocationClient.isConnected()) {
- stopPeriodicUpdates();
+ /*
+ * Remove location updates for a listener.
+ * The current Activity is the listener, so
+ * the argument is "this".
+ */
+ removeLocationUpdates(this);
}
/*
* After disconnect() is called, the client is
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 6d236d9..c8fce9e 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -869,10 +869,6 @@
drawable = new StateListDrawable();
} else if (name.equals("level-list")) {
drawable = new LevelListDrawable();
- /* Probably not doing this.
- } else if (name.equals("mipmap")) {
- drawable = new MipmapDrawable();
- */
} else if (name.equals("layer-list")) {
drawable = new LayerDrawable();
} else if (name.equals("transition")) {
diff --git a/graphics/java/android/graphics/drawable/MipmapDrawable.java b/graphics/java/android/graphics/drawable/MipmapDrawable.java
deleted file mode 100644
index cd39719..0000000
--- a/graphics/java/android/graphics/drawable/MipmapDrawable.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-
-import java.io.IOException;
-
-/**
- * @hide -- we are probably moving to do MipMaps in another way (more integrated
- * with the resource system).
- *
- * A resource that manages a number of alternate Drawables, and which actually draws the one which
- * size matches the most closely the drawing bounds. Providing several pre-scaled version of the
- * drawable helps minimizing the aliasing artifacts that can be introduced by the scaling.
- *
- * <p>
- * Use {@link #addDrawable(Drawable)} to define the different Drawables that will represent the
- * mipmap levels of this MipmapDrawable. The mipmap Drawable that will actually be used when this
- * MipmapDrawable is drawn is the one which has the smallest intrinsic height greater or equal than
- * the bounds' height. This selection ensures that the best available mipmap level is scaled down to
- * draw this MipmapDrawable.
- * </p>
- *
- * If the bounds' height is larger than the largest mipmap, the largest mipmap will be scaled up.
- * Note that Drawables without intrinsic height (i.e. with a negative value, such as Color) will
- * only be used if no other mipmap Drawable are provided. The Drawables' intrinsic heights should
- * not be changed after the Drawable has been added to this MipmapDrawable.
- *
- * <p>
- * The different mipmaps' parameters (opacity, padding, color filter, gravity...) should typically
- * be similar to ensure a continuous visual appearance when the MipmapDrawable is scaled. The aspect
- * ratio of the different mipmaps should especially be equal.
- * </p>
- *
- * A typical example use of a MipmapDrawable would be for an image which is intended to be scaled at
- * various sizes, and for which one wants to provide pre-scaled versions to precisely control its
- * appearance.
- *
- * <p>
- * The intrinsic size of a MipmapDrawable are inferred from those of the largest mipmap (in terms of
- * {@link Drawable#getIntrinsicHeight()}). On the opposite, its minimum
- * size is defined by the smallest provided mipmap.
- * </p>
-
- * It can be defined in an XML file with the <code><mipmap></code> element.
- * Each mipmap Drawable is defined in a nested <code><item></code>. For example:
- * <pre>
- * <mipmap xmlns:android="http://schemas.android.com/apk/res/android">
- * <item android:drawable="@drawable/my_image_8" />
- * <item android:drawable="@drawable/my_image_32" />
- * <item android:drawable="@drawable/my_image_128" />
- * </mipmap>
- *</pre>
- * <p>
- * With this XML saved into the res/drawable/ folder of the project, it can be referenced as
- * the drawable for an {@link android.widget.ImageView}. Assuming that the heights of the provided
- * drawables are respectively 8, 32 and 128 pixels, the first one will be scaled down when the
- * bounds' height is lower or equal than 8 pixels. The second drawable will then be used up to a
- * height of 32 pixels and the largest drawable will be used for greater heights.
- * </p>
- * @attr ref android.R.styleable#MipmapDrawableItem_drawable
- */
-public class MipmapDrawable extends DrawableContainer {
- private final MipmapContainerState mMipmapContainerState;
- private boolean mMutated;
-
- public MipmapDrawable() {
- this(null, null);
- }
-
- /**
- * Adds a Drawable to the list of available mipmap Drawables. The Drawable actually used when
- * this MipmapDrawable is drawn is determined from its bounds.
- *
- * This method has no effect if drawable is null.
- *
- * @param drawable The Drawable that will be added to list of available mipmap Drawables.
- */
-
- public void addDrawable(Drawable drawable) {
- if (drawable != null) {
- mMipmapContainerState.addDrawable(drawable);
- onDrawableAdded();
- }
- }
-
- private void onDrawableAdded() {
- // selectDrawable assumes that the container content does not change.
- // When a Drawable is added, the same index can correspond to a new Drawable, and since
- // selectDrawable has a fast exit case when oldIndex==newIndex, the new drawable could end
- // up not being used in place of the previous one if they happen to share the same index.
- // This make sure the new computed index can actually replace the previous one.
- selectDrawable(-1);
- onBoundsChange(getBounds());
- }
-
- // overrides from Drawable
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- final int index = mMipmapContainerState.indexForBounds(bounds);
-
- // Will call invalidateSelf() if needed
- selectDrawable(index);
-
- super.onBoundsChange(bounds);
- }
-
- @Override
- public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
- throws XmlPullParserException, IOException {
-
- super.inflate(r, parser, attrs);
-
- int type;
-
- final int innerDepth = parser.getDepth() + 1;
- int depth;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth
- || type != XmlPullParser.END_TAG)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (depth > innerDepth || !parser.getName().equals("item")) {
- continue;
- }
-
- TypedArray a = r.obtainAttributes(attrs,
- com.android.internal.R.styleable.MipmapDrawableItem);
-
- int drawableRes = a.getResourceId(
- com.android.internal.R.styleable.MipmapDrawableItem_drawable, 0);
-
- a.recycle();
-
- Drawable dr;
- if (drawableRes != 0) {
- dr = r.getDrawable(drawableRes);
- } else {
- while ((type = parser.next()) == XmlPullParser.TEXT) {
- }
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException(
- parser.getPositionDescription()
- + ": <item> tag requires a 'drawable' attribute or "
- + "child tag defining a drawable");
- }
- dr = Drawable.createFromXmlInner(r, parser, attrs);
- }
-
- mMipmapContainerState.addDrawable(dr);
- }
-
- onDrawableAdded();
- }
-
- @Override
- public Drawable mutate() {
- if (!mMutated && super.mutate() == this) {
- mMipmapContainerState.mMipmapHeights = mMipmapContainerState.mMipmapHeights.clone();
- mMutated = true;
- }
- return this;
- }
-
- private final static class MipmapContainerState extends DrawableContainerState {
- private int[] mMipmapHeights;
-
- MipmapContainerState(MipmapContainerState orig, MipmapDrawable owner, Resources res) {
- super(orig, owner, res);
-
- if (orig != null) {
- mMipmapHeights = orig.mMipmapHeights;
- } else {
- mMipmapHeights = new int[getChildren().length];
- }
-
- // Change the default value
- setConstantSize(true);
- }
-
- /**
- * Returns the index of the child mipmap drawable that will best fit the provided bounds.
- * This index is determined by comparing bounds' height and children intrinsic heights.
- * The returned mipmap index is the smallest mipmap which height is greater or equal than
- * the bounds' height. If the bounds' height is larger than the largest mipmap, the largest
- * mipmap index is returned.
- *
- * @param bounds The bounds of the MipMapDrawable.
- * @return The index of the child Drawable that will best fit these bounds, or -1 if there
- * are no children mipmaps.
- */
- public int indexForBounds(Rect bounds) {
- final int boundsHeight = bounds.height();
- final int N = getChildCount();
- for (int i = 0; i < N; i++) {
- if (boundsHeight <= mMipmapHeights[i]) {
- return i;
- }
- }
-
- // No mipmap larger than bounds found. Use largest one which will be scaled up.
- if (N > 0) {
- return N - 1;
- }
- // No Drawable mipmap at all
- return -1;
- }
-
- /**
- * Adds a Drawable to the list of available mipmap Drawables. This list can be retrieved
- * using {@link DrawableContainer.DrawableContainerState#getChildren()} and this method
- * ensures that it is always sorted by increasing {@link Drawable#getIntrinsicHeight()}.
- *
- * @param drawable The Drawable that will be added to children list
- */
- public void addDrawable(Drawable drawable) {
- // Insert drawable in last position, correctly resetting cached values and
- // especially mComputedConstantSize
- int pos = addChild(drawable);
-
- // Bubble sort the last drawable to restore the sort by intrinsic height
- final int drawableHeight = drawable.getIntrinsicHeight();
-
- while (pos > 0) {
- final Drawable previousDrawable = mDrawables[pos-1];
- final int previousIntrinsicHeight = previousDrawable.getIntrinsicHeight();
-
- if (drawableHeight < previousIntrinsicHeight) {
- mDrawables[pos] = previousDrawable;
- mMipmapHeights[pos] = previousIntrinsicHeight;
-
- mDrawables[pos-1] = drawable;
- mMipmapHeights[pos-1] = drawableHeight;
- pos--;
- } else {
- break;
- }
- }
- }
-
- /**
- * Intrinsic sizes are those of the largest available mipmap.
- * Minimum sizes are those of the smallest available mipmap.
- */
- @Override
- protected void computeConstantSize() {
- final int N = getChildCount();
- if (N > 0) {
- final Drawable smallestDrawable = mDrawables[0];
- mConstantMinimumWidth = smallestDrawable.getMinimumWidth();
- mConstantMinimumHeight = smallestDrawable.getMinimumHeight();
-
- final Drawable largestDrawable = mDrawables[N-1];
- mConstantWidth = largestDrawable.getIntrinsicWidth();
- mConstantHeight = largestDrawable.getIntrinsicHeight();
- } else {
- mConstantWidth = mConstantHeight = -1;
- mConstantMinimumWidth = mConstantMinimumHeight = 0;
- }
- mComputedConstantSize = true;
- }
-
- @Override
- public Drawable newDrawable() {
- return new MipmapDrawable(this, null);
- }
-
- @Override
- public Drawable newDrawable(Resources res) {
- return new MipmapDrawable(this, res);
- }
-
- @Override
- public void growArray(int oldSize, int newSize) {
- super.growArray(oldSize, newSize);
- int[] newInts = new int[newSize];
- System.arraycopy(mMipmapHeights, 0, newInts, 0, oldSize);
- mMipmapHeights = newInts;
- }
- }
-
- private MipmapDrawable(MipmapContainerState state, Resources res) {
- MipmapContainerState as = new MipmapContainerState(state, this, res);
- mMipmapContainerState = as;
- setConstantState(as);
- onDrawableAdded();
- }
-}
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 3d4d40a..e1b8c6c 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -1736,6 +1736,9 @@
int usage) {
rs.validate();
+ if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
+ throw new RSIllegalArgumentException("Unsupported usage specified.");
+ }
Bitmap b = BitmapFactory.decodeResource(res, id);
Allocation alloc = createFromBitmap(rs, b, mips, usage);
b.recycle();
@@ -1763,7 +1766,7 @@
if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
return createFromBitmapResource(rs, res, id,
MipmapControl.MIPMAP_NONE,
- USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
+ USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
}
return createFromBitmapResource(rs, res, id,
MipmapControl.MIPMAP_NONE,
diff --git a/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java b/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java
deleted file mode 100644
index 5fcc3bc..0000000
--- a/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.MipmapDrawable;
-import android.graphics.drawable.DrawableContainer.DrawableContainerState;
-import android.test.InstrumentationTestCase;
-
-public class MipmapDrawableTest extends InstrumentationTestCase {
- private MockMipmapDrawable mMipmapDrawable;
-
- private DrawableContainerState mDrawableContainerState;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mMipmapDrawable = new MockMipmapDrawable();
- mDrawableContainerState = (DrawableContainerState) mMipmapDrawable.getConstantState();
- }
-
- public void testMipmapDrawable() {
- new MipmapDrawable();
- // Check the values set in the constructor
- assertNotNull(new MipmapDrawable().getConstantState());
- assertTrue(new MockMipmapDrawable().hasCalledOnBoundsChanged());
- }
-
- public void testAddDrawable() {
- assertEquals(0, mDrawableContainerState.getChildCount());
-
- // nothing happens if drawable is null
- mMipmapDrawable.reset();
- mMipmapDrawable.addDrawable(null);
- assertEquals(0, mDrawableContainerState.getChildCount());
- assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
-
- mMipmapDrawable.reset();
- mMipmapDrawable.addDrawable(new MockDrawable());
- assertEquals(1, mDrawableContainerState.getChildCount());
- assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
- mMipmapDrawable.reset();
- mMipmapDrawable.addDrawable(new MockDrawable());
- assertEquals(2, mDrawableContainerState.getChildCount());
- assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
- }
-
- public void testSortedByHeight() {
- Drawable small = new MockDrawable(8);
- Drawable medium = new MockDrawable(32);
- Drawable large = new MockDrawable(128);
-
- mMipmapDrawable.addDrawable(medium);
- assertSame(medium, mDrawableContainerState.getChildren()[0]);
-
- mMipmapDrawable.addDrawable(small);
- assertSame(small, mDrawableContainerState.getChildren()[0]);
- assertSame(medium, mDrawableContainerState.getChildren()[1]);
-
- mMipmapDrawable.addDrawable(large);
- assertSame(small, mDrawableContainerState.getChildren()[0]);
- assertSame(medium, mDrawableContainerState.getChildren()[1]);
- assertSame(large, mDrawableContainerState.getChildren()[2]);
-
- mMipmapDrawable.addDrawable(small);
- assertSame(small, mDrawableContainerState.getChildren()[0]);
- assertSame(small, mDrawableContainerState.getChildren()[1]);
- assertSame(medium, mDrawableContainerState.getChildren()[2]);
- assertSame(large, mDrawableContainerState.getChildren()[3]);
-
- mMipmapDrawable.addDrawable(medium);
- assertSame(small, mDrawableContainerState.getChildren()[0]);
- assertSame(small, mDrawableContainerState.getChildren()[1]);
- assertSame(medium, mDrawableContainerState.getChildren()[2]);
- assertSame(medium, mDrawableContainerState.getChildren()[3]);
- assertSame(large, mDrawableContainerState.getChildren()[4]);
-
- mMipmapDrawable.addDrawable(large);
- assertSame(small, mDrawableContainerState.getChildren()[0]);
- assertSame(small, mDrawableContainerState.getChildren()[1]);
- assertSame(medium, mDrawableContainerState.getChildren()[2]);
- assertSame(medium, mDrawableContainerState.getChildren()[3]);
- assertSame(large, mDrawableContainerState.getChildren()[4]);
- assertSame(large, mDrawableContainerState.getChildren()[5]);
- }
-
- public void testSetBoundsOneItem() {
- // the method is not called if same bounds are set
- mMipmapDrawable.reset();
- mMipmapDrawable.setBounds(mMipmapDrawable.getBounds());
- assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
-
- // the method is called if different bounds are set, even without drawables
- mMipmapDrawable.reset();
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
- assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
- // adding an item should check bounds to see if new drawable is more appropriate
- mMipmapDrawable.reset();
- Drawable item = new MockDrawable(42);
- mMipmapDrawable.addDrawable(item);
- assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
- // the method is called if different bounds are set
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
- assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
-
- // check that correct drawable is selected for any size.
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() - 1));
- assertSame(item, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight()));
- assertSame(item, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() + 1));
- assertSame(item, mMipmapDrawable.getCurrent());
- }
-
- public void testSetBounds() {
- Drawable small = new MockDrawable(8);
- Drawable medium = new MockDrawable(32);
- Drawable large = new MockDrawable(128);
-
- mMipmapDrawable.addDrawable(large);
- mMipmapDrawable.addDrawable(small);
- mMipmapDrawable.addDrawable(medium);
-
- // check that correct drawable is selected.
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() - 1));
- assertSame(small, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight()));
- assertSame(small, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() + 1));
- assertSame(medium, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() - 1));
- assertSame(medium, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight()));
- assertSame(medium, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() + 1));
- assertSame(large, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() - 1));
- assertSame(large, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight()));
- assertSame(large, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() + 1));
- assertSame(large, mMipmapDrawable.getCurrent());
- }
-
- public void testSizes() {
- // Check default value with no mipmap defined
- assertEquals(-1, mMipmapDrawable.getIntrinsicHeight());
- assertEquals(-1, mMipmapDrawable.getIntrinsicWidth());
- assertEquals(0, mMipmapDrawable.getMinimumHeight());
- assertEquals(0, mMipmapDrawable.getMinimumWidth());
-
- Drawable small = new MockDrawable(8, 4);
- Drawable medium = new MockDrawable(32, 16);
- Drawable large = new MockDrawable(128, 64);
-
- mMipmapDrawable.addDrawable(medium);
- assertEquals(medium.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
- assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
-
- mMipmapDrawable.addDrawable(large);
- assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
- assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
-
- mMipmapDrawable.addDrawable(small);
- assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
- assertEquals(small.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
- }
-
- public void testReplacementWhenAdded() {
- Drawable small = new MockDrawable(8);
- Drawable medium = new MockDrawable(32);
- Drawable large = new MockDrawable(128);
-
- // Small bounds, so that the smallest mipmap should always be selected
- mMipmapDrawable.setBounds(new Rect(0, 0, 0, 0));
-
- // Providing smaller versions, that should immediately be used as current
- mMipmapDrawable.addDrawable(large);
- assertSame(large, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.addDrawable(medium);
- assertSame(medium, mMipmapDrawable.getCurrent());
-
- mMipmapDrawable.addDrawable(small);
- assertSame(small, mMipmapDrawable.getCurrent());
- }
-
- private class MockMipmapDrawable extends MipmapDrawable {
- private boolean mHasCalledOnBoundsChanged;
-
- public boolean hasCalledOnBoundsChanged() {
- return mHasCalledOnBoundsChanged;
- }
-
- public void reset() {
- mHasCalledOnBoundsChanged = false;
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
- mHasCalledOnBoundsChanged = true;
- }
- }
-
- private class MockDrawable extends Drawable {
- int mIntrinsicHeight;
- int mMinimumHeight;
-
- public MockDrawable() {
- this(0);
- }
-
- public MockDrawable(int intrinsicHeight) {
- this(intrinsicHeight, intrinsicHeight);
- }
-
- public MockDrawable(int intrinsicHeight, int minimumHeight) {
- mIntrinsicHeight = intrinsicHeight;
- mMinimumHeight = minimumHeight;
- }
-
- @Override
- public void draw(Canvas canvas) {
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mIntrinsicHeight;
- }
-
- @Override
- public int getMinimumHeight() {
- return mMinimumHeight;
- }
- }
-}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 33ba229..9e13ca4 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -71,7 +71,9 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.Surface;
import android.view.VolumePanel;
+import android.view.WindowManager;
import com.android.internal.telephony.ITelephony;
import com.android.internal.util.XmlUtils;
@@ -431,6 +433,7 @@
private volatile IRingtonePlayer mRingtonePlayer;
private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
+ private int mDeviceRotation = Surface.ROTATION_0;
// Request to override default use of A2DP for media.
private boolean mBluetoothA2dpEnabled;
@@ -452,7 +455,9 @@
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
+ // TODO merge orientation and rotation
private final boolean mMonitorOrientation;
+ private final boolean mMonitorRotation;
private boolean mDockAudioMediaEnabled = true;
@@ -545,14 +550,21 @@
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- // Register a configuration change listener only if requested by system properties
- // to monitor orientation changes (off by default)
+ // TODO merge orientation and rotation
mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false);
if (mMonitorOrientation) {
Log.v(TAG, "monitoring device orientation");
// initialize orientation in AudioSystem
setOrientationForAudioSystem();
}
+ mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
+ if (mMonitorRotation) {
+ mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay().getRotation();
+ Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation);
+ // initialize rotation in AudioSystem
+ setRotationForAudioSystem();
+ }
context.registerReceiver(mReceiver, intentFilter);
@@ -3497,6 +3509,9 @@
if (mMonitorOrientation) {
setOrientationForAudioSystem();
}
+ if (mMonitorRotation) {
+ setRotationForAudioSystem();
+ }
synchronized (mBluetoothA2dpEnabledLock) {
AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
@@ -6375,15 +6390,17 @@
// Device orientation
//==========================================================================================
/**
- * Handles device configuration changes that may map to a change in the orientation.
- * This feature is optional, and is defined by the definition and value of the
- * "ro.audio.monitorOrientation" system property.
+ * Handles device configuration changes that may map to a change in the orientation
+ * or orientation.
+ * Monitoring orientation and rotation is optional, and is defined by the definition and value
+ * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties.
*/
private void handleConfigurationChanged(Context context) {
try {
// reading new orientation "safely" (i.e. under try catch) in case anything
// goes wrong when obtaining resources and configuration
Configuration config = context.getResources().getConfiguration();
+ // TODO merge rotation and orientation
if (mMonitorOrientation) {
int newOrientation = config.orientation;
if (newOrientation != mDeviceOrientation) {
@@ -6391,6 +6408,14 @@
setOrientationForAudioSystem();
}
}
+ if (mMonitorRotation) {
+ int newRotation = ((WindowManager) context.getSystemService(
+ Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
+ if (newRotation != mDeviceRotation) {
+ mDeviceRotation = newRotation;
+ setRotationForAudioSystem();
+ }
+ }
sendMsg(mAudioHandler,
MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
SENDMSG_REPLACE,
@@ -6439,7 +6464,7 @@
}
mVolumePanel.setLayoutDirection(config.getLayoutDirection());
} catch (Exception e) {
- Log.e(TAG, "Error retrieving device orientation: " + e);
+ Log.e(TAG, "Error handling configuration change: ", e);
}
}
@@ -6466,6 +6491,25 @@
}
}
+ private void setRotationForAudioSystem() {
+ switch (mDeviceRotation) {
+ case Surface.ROTATION_0:
+ AudioSystem.setParameters("rotation=0");
+ break;
+ case Surface.ROTATION_90:
+ AudioSystem.setParameters("rotation=90");
+ break;
+ case Surface.ROTATION_180:
+ AudioSystem.setParameters("rotation=180");
+ break;
+ case Surface.ROTATION_270:
+ AudioSystem.setParameters("rotation=270");
+ break;
+ default:
+ Log.e(TAG, "Unknown device rotation");
+ }
+ }
+
// Handles request to override default use of A2DP for media.
public void setBluetoothA2dpOnInt(boolean on) {
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index c0fbd2e..774964e 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -35,20 +35,29 @@
* It is generally used like this:
*
* <pre>
- * MediaMuxer muxer = new MediaMuxer(...);
+ * MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
+ * // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
+ * // or MediaExtractor.getTrackFormat().
* MediaFormat audioFormat = new MediaFormat(...);
* MediaFormat videoFormat = new MediaFormat(...);
* int audioTrackIndex = muxer.addTrack(audioFormat);
* int videoTrackIndex = muxer.addTrack(videoFormat);
- * ByteBuffer inputBuffer = ByteBuffer.allocate(...);
+ * ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
+ * boolean finished = false;
+ * BufferInfo bufferInfo = new BufferInfo();
+ *
* muxer.start();
- * while(inputBuffer has new data) {
- * if (new data is audio sample) {
- * muxer.writeSampleData(audioTrackIndex, inputBuffer, ...);
- * } else if (new data is video sample) {
- * muxer.writeSampleData(videoTrackIndex, inputBuffer, ...);
+ * while(!finished) {
+ * // getInputBuffer() will fill the inputBuffer with one frame of encoded
+ * // sample from either MediaCodec or MediaExtractor, set isAudioSample to
+ * // true when the sample is audio data, set up all the fields of bufferInfo,
+ * // and return true if there are no more samples.
+ * finished = getInputBuffer(inputBuffer, isAudioSample, bufferInfo);
+ * if (!finished) {
+ * int currentTrackIndex = isAudioSample ? audioTrackIndex : videoTrackIndex;
+ * muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
* }
- * }
+ * };
* muxer.stop();
* muxer.release();
* </pre>
@@ -74,16 +83,6 @@
public static final int MUXER_OUTPUT_MPEG_4 = 0;
};
- /**
- * The sample is a sync sample, which does not require other video samples
- * to decode. This flag is used in {@link #writeSampleData} to indicate
- * which sample is a sync sample.
- */
- /* Keep this flag in sync with its equivalent in
- * include/media/stagefright/MediaMuxer.h.
- */
- public static final int SAMPLE_FLAG_SYNC = 1;
-
// All the native functions are listed here.
private static native int nativeSetup(FileDescriptor fd, int format);
private static native void nativeRelease(int nativeObject);
@@ -260,10 +259,13 @@
* Writes an encoded sample into the muxer.
* <p>The application needs to make sure that the samples are written into
* the right tracks. Also, it needs to make sure the samples for each track
- * are written in chronological order.</p>
+ * are written in chronological order (e.g. in the order they are provided
+ * by the encoder.)</p>
* @param byteBuf The encoded sample.
* @param trackIndex The track index for this sample.
* @param bufferInfo The buffer information related to this sample.
+ * MediaMuxer uses the flags provided in {@link MediaCodec.BufferInfo},
+ * to signal sync frames.
*/
public void writeSampleData(int trackIndex, ByteBuffer byteBuf,
BufferInfo bufferInfo) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index f745163..b729640 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -16,9 +16,14 @@
package android.media;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
+import android.net.Proxy;
+import android.net.ProxyProperties;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -864,6 +869,7 @@
*/
public void setDataSource(Context context, Uri uri, Map<String, String> headers)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+ disableProxyListener();
String scheme = uri.getScheme();
if(scheme == null || scheme.equals("file")) {
@@ -896,8 +902,13 @@
}
Log.d(TAG, "Couldn't open file on client side, trying server side");
+
setDataSource(uri.toString(), headers);
- return;
+
+ if (scheme.equalsIgnoreCase("http")
+ || scheme.equalsIgnoreCase("https")) {
+ setupProxyListener(context);
+ }
}
/**
@@ -948,6 +959,8 @@
private void setDataSource(String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+ disableProxyListener();
+
final Uri uri = Uri.parse(path);
if ("file".equals(uri.getScheme())) {
path = uri.getPath();
@@ -991,7 +1004,13 @@
* @param length the length in bytes of the data to be played
* @throws IllegalStateException if it is called in an invalid state
*/
- public native void setDataSource(FileDescriptor fd, long offset, long length)
+ public void setDataSource(FileDescriptor fd, long offset, long length)
+ throws IOException, IllegalArgumentException, IllegalStateException {
+ disableProxyListener();
+ _setDataSource(fd, offset, length);
+ }
+
+ private native void _setDataSource(FileDescriptor fd, long offset, long length)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
@@ -1332,6 +1351,8 @@
_reset();
// make sure none of the listeners get called anymore
mEventHandler.removeCallbacksAndMessages(null);
+
+ disableProxyListener();
}
private native void _reset();
@@ -2449,4 +2470,57 @@
return (mode == VIDEO_SCALING_MODE_SCALE_TO_FIT ||
mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
}
+
+ private Context mProxyContext = null;
+ private ProxyReceiver mProxyReceiver = null;
+
+ private void setupProxyListener(Context context) {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Proxy.PROXY_CHANGE_ACTION);
+ mProxyReceiver = new ProxyReceiver();
+ mProxyContext = context;
+
+ Intent currentProxy =
+ context.getApplicationContext().registerReceiver(mProxyReceiver, filter);
+
+ if (currentProxy != null) {
+ handleProxyBroadcast(currentProxy);
+ }
+ }
+
+ private void disableProxyListener() {
+ if (mProxyReceiver == null) {
+ return;
+ }
+
+ Context appContext = mProxyContext.getApplicationContext();
+ if (appContext != null) {
+ appContext.unregisterReceiver(mProxyReceiver);
+ }
+
+ mProxyReceiver = null;
+ mProxyContext = null;
+ }
+
+ private void handleProxyBroadcast(Intent intent) {
+ ProxyProperties props =
+ (ProxyProperties)intent.getExtra(Proxy.EXTRA_PROXY_INFO);
+
+ if (props == null || props.getHost() == null) {
+ updateProxyConfig(null);
+ } else {
+ updateProxyConfig(props);
+ }
+ }
+
+ private class ProxyReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {
+ handleProxyBroadcast(intent);
+ }
+ }
+ }
+
+ private native void updateProxyConfig(ProxyProperties props);
}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index e6693b9..d653d94 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -231,7 +231,7 @@
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
CallbackInfo cbi = mCallbacks.get(i);
- if ((cbi.flags & CALLBACK_FLAG_ACTIVE_SCAN) != 0
+ if ((cbi.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0
&& (cbi.type & type) != 0) {
return true;
}
@@ -330,7 +330,7 @@
* discover and select a new route.
* </p>
*/
- public static final int CALLBACK_FLAG_ACTIVE_SCAN = 1 << 0;
+ public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1 << 0;
/**
* Flag for {@link #addCallback}: Do not filter route events.
@@ -439,7 +439,7 @@
* @param types Types of routes this callback is interested in
* @param cb Callback to add
* @param flags Flags to control the behavior of the callback.
- * May be zero or a combination of {@link #CALLBACK_FLAG_ACTIVE_SCAN} and
+ * May be zero or a combination of {@link #CALLBACK_FLAG_PERFORM_ACTIVE_SCAN} and
* {@link #CALLBACK_FLAG_UNFILTERED_EVENTS}.
*/
public void addCallback(int types, Callback cb, int flags) {
@@ -453,7 +453,7 @@
info = new CallbackInfo(cb, types, flags, this);
sStatic.mCallbacks.add(info);
}
- if ((info.flags & CALLBACK_FLAG_ACTIVE_SCAN) != 0) {
+ if ((info.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) {
sStatic.updateActiveScan();
}
}
@@ -467,7 +467,7 @@
int index = findCallbackInfo(cb);
if (index >= 0) {
CallbackInfo info = sStatic.mCallbacks.remove(index);
- if ((info.flags & CALLBACK_FLAG_ACTIVE_SCAN) != 0) {
+ if ((info.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) {
sStatic.updateActiveScan();
}
} else {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c5098ce..7c607ea 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -55,6 +55,10 @@
jfieldID surface_texture;
jmethodID post_event;
+
+ jmethodID proxyConfigGetHost;
+ jmethodID proxyConfigGetPort;
+ jmethodID proxyConfigGetExclusionList;
};
static fields_t fields;
@@ -622,6 +626,20 @@
if (fields.surface_texture == NULL) {
return;
}
+
+ clazz = env->FindClass("android/net/ProxyProperties");
+ if (clazz == NULL) {
+ return;
+ }
+
+ fields.proxyConfigGetHost =
+ env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;");
+
+ fields.proxyConfigGetPort =
+ env->GetMethodID(clazz, "getPort", "()I");
+
+ fields.proxyConfigGetExclusionList =
+ env->GetMethodID(clazz, "getExclusionList", "()Ljava/lang/String;");
}
static void
@@ -823,6 +841,49 @@
;
}
+static void
+android_media_MediaPlayer_updateProxyConfig(
+ JNIEnv *env, jobject thiz, jobject proxyProps)
+{
+ ALOGV("updateProxyConfig");
+ sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz);
+ if (thisplayer == NULL) {
+ return;
+ }
+
+ if (proxyProps == NULL) {
+ thisplayer->updateProxyConfig(
+ NULL /* host */, 0 /* port */, NULL /* exclusionList */);
+ } else {
+ jstring hostObj = (jstring)env->CallObjectMethod(
+ proxyProps, fields.proxyConfigGetHost);
+
+ const char *host = env->GetStringUTFChars(hostObj, NULL);
+
+ int port = env->CallIntMethod(proxyProps, fields.proxyConfigGetPort);
+
+ jstring exclusionListObj = (jstring)env->CallObjectMethod(
+ proxyProps, fields.proxyConfigGetExclusionList);
+
+ const char *exclusionList =
+ env->GetStringUTFChars(exclusionListObj, NULL);
+
+ if (host != NULL && exclusionListObj != NULL) {
+ thisplayer->updateProxyConfig(host, port, exclusionList);
+ }
+
+ if (exclusionList != NULL) {
+ env->ReleaseStringUTFChars(exclusionListObj, exclusionList);
+ exclusionList = NULL;
+ }
+
+ if (host != NULL) {
+ env->ReleaseStringUTFChars(hostObj, host);
+ host = NULL;
+ }
+ }
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -832,7 +893,7 @@
(void *)android_media_MediaPlayer_setDataSourceAndHeaders
},
- {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
+ {"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
{"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface},
{"prepare", "()V", (void *)android_media_MediaPlayer_prepare},
{"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
@@ -867,6 +928,7 @@
{"getParameter", "(ILandroid/os/Parcel;)V", (void *)android_media_MediaPlayer_getParameter},
{"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint},
{"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer},
+ {"updateProxyConfig", "(Landroid/net/ProxyProperties;)V", (void *)android_media_MediaPlayer_updateProxyConfig},
};
static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
index fa59fa4..23b9705 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
@@ -19,6 +19,8 @@
import android.test.InstrumentationTestRunner;
import android.test.InstrumentationTestSuite;
import com.android.mediaframeworktest.stress.CameraStressTest;
+import com.android.mediaframeworktest.functional.camera.CameraFunctionalTest;
+import com.android.mediaframeworktest.functional.camera.CameraPairwiseTest;
import junit.framework.TestSuite;
@@ -28,6 +30,8 @@
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(CameraStressTest.class);
+ suite.addTestSuite(CameraFunctionalTest.class);
+ suite.addTestSuite(CameraPairwiseTest.class);
return suite;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraTestHelper.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraTestHelper.java
new file mode 100644
index 0000000..8bf741c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraTestHelper.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2013 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.mediaframeworktest;
+
+import android.hardware.Camera;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.ShutterCallback;
+import android.os.Environment;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+public class CameraTestHelper {
+
+ public Camera mCamera;
+ private String TAG = "CameraTestHelper";
+ private static final int CAMERA_ID = 0;
+ private static final long WAIT_GENERIC = 3 * 1000; // 3 seconds
+ private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
+ protected static final String CAMERA_STRESS_IMAGES_DIRECTORY = "cameraStressImages";
+ private static final String CAMERA_STRESS_IMAGES_PREFIX = "camera-stress-test";
+ private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
+
+ private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
+ public void onError(int error, android.hardware.Camera camera) {
+ Assert.fail(String.format("Camera error, code: %d", error));
+ }
+ }
+
+ private ShutterCallback shutterCallback = new ShutterCallback() {
+ @Override
+ public void onShutter() {
+ Log.v(TAG, "Shutter");
+ }
+ };
+
+ private PictureCallback rawCallback = new PictureCallback() {
+ @Override
+ public void onPictureTaken(byte[] data, Camera camera) {
+ Log.v(TAG, "Raw picture taken");
+ }
+ };
+
+ private PictureCallback jpegCallback = new PictureCallback() {
+ @Override
+ public void onPictureTaken(byte[] data, Camera camera) {
+ FileOutputStream fos = null;
+
+ try {
+ Log.v(TAG, "JPEG picture taken");
+ fos = new FileOutputStream(String.format("%s/%s/%s-%d.jpg",
+ Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY,
+ CAMERA_STRESS_IMAGES_PREFIX, System.currentTimeMillis()));
+ fos.write(data);
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "File not found: " + e.toString());
+ } catch (IOException e) {
+ Log.e(TAG, "Error accessing file: " + e.toString());
+ } finally {
+ try {
+ if (fos != null) {
+ fos.close();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing file: " + e.toString());
+ }
+ }
+ }
+ };
+
+ /**
+ * Helper method for prepping test
+ */
+ public void setupCameraTest() {
+ // Create the test images directory if it doesn't exist
+ File stressImagesDirectory = new File(String.format("%s/%s",
+ Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
+ if (!stressImagesDirectory.exists()) {
+ stressImagesDirectory.mkdir();
+ }
+
+ mCamera = Camera.open(CAMERA_ID);
+ }
+
+ /**
+ * Helper method for getting the available parameters of the default camera
+ */
+ public Parameters getCameraParameters() {
+ mCamera = Camera.open(CAMERA_ID);
+ Parameters params = mCamera.getParameters();
+ mCamera.release();
+ return params;
+ }
+
+ /**
+ * Helper method for taking a photo
+ */
+ public void capturePhoto() throws Exception {
+ mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
+ Thread.sleep(WAIT_GENERIC);
+ mCamera.stopPreview();
+ mCamera.release();
+ }
+
+ /**
+ * Helper method for cleaning up pics taken during tests
+ */
+ public void cleanupTestImages() {
+ try {
+ File stressImagesDirectory = new File(String.format("%s/%s",
+ Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
+ File[] stressImages = stressImagesDirectory.listFiles();
+ for (File f : stressImages) {
+ f.delete();
+ }
+ } catch (SecurityException e) {
+ Log.e(TAG, "Security manager access violation: " + e.toString());
+ }
+ }
+
+ /**
+ * Helper method for setting the camera parameters
+ */
+ public void setParameters(Parameters params) {
+ try {
+ mCamera.setParameters(params);
+ } catch (Exception e) {
+ Log.e(TAG, "Error setting camera parameters");
+ }
+ }
+
+ /**
+ * Helper method for starting up the camera preview
+ */
+ public void startCameraPreview(SurfaceHolder surfaceHolder) throws Exception {
+ mCamera.setErrorCallback(mCameraErrorCallback);
+ mCamera.setPreviewDisplay(surfaceHolder);
+ mCamera.startPreview();
+ Thread.sleep(WAIT_GENERIC);
+ }
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
index ed9bb97..10df2e6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -48,9 +48,9 @@
import java.io.FileDescriptor;
import java.net.InetAddress;
-
+
public class MediaFrameworkTest extends Activity implements SurfaceHolder.Callback {
-
+
//public static Surface video_sf;
public static SurfaceView mSurfaceView;
private MediaController mMediaController;
@@ -58,10 +58,10 @@
private MediaPlayer mpmidi;
private MediaPlayer mpmp3;
private String testfilepath = "/sdcard/awb.awb";
-
+
public static AssetFileDescriptor midiafd;
public static AssetFileDescriptor mp3afd;
-
+
public static Bitmap mDestBitmap;
public static ImageView mOverlayView;
private SurfaceHolder mSurfaceHolder = null;
@@ -82,10 +82,10 @@
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.addCallback(this);
-
+
//Get the midi fd
midiafd = this.getResources().openRawResourceFd(R.raw.testmidi);
-
+
//Get the mp3 fd
mp3afd = this.getResources().openRawResourceFd(R.raw.testmp3);
mOverlayView.setLayoutParams(lp);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraFunctionalTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraFunctionalTest.java
new file mode 100644
index 0000000..e6f0aaf
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraFunctionalTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2013 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.mediaframeworktest.functional.camera;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.CameraTestHelper;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.hardware.Camera;
+import android.hardware.Camera.Parameters;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import com.android.mediaframeworktest.CameraStressTestRunner;
+
+import junit.framework.Assert;
+
+/**
+ * Junit / Instrumentation test case for the following camera APIs:
+ * - flash
+ * - exposure compensation
+ * - white balance
+ * - focus mode
+ *
+ * adb shell am instrument
+ * -e class com.android.mediaframeworktest.functional.camera.CameraFunctionalTest
+ * -w com.android.mediaframework/.CameraStressTestRunner
+ */
+public class CameraFunctionalTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+ private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
+ private CameraTestHelper mCameraTestHelper;
+ private Handler mHandler;
+ private Thread mLooperThread;
+ private Writer mOutput;
+
+ private String TAG = "CameraFunctionalTest";
+
+ public CameraFunctionalTest() {
+ super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+ }
+
+ protected void setUp() throws Exception {
+ final Semaphore sem = new Semaphore(0);
+ mLooperThread = new Thread() {
+ @Override
+ public void run() {
+ Log.v(TAG, "starting looper");
+ Looper.prepare();
+ mHandler = new Handler();
+ sem.release();
+ Looper.loop();
+ Log.v(TAG, "quit looper");
+ }
+ };
+ mLooperThread.start();
+ if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+ fail("Failed to start the looper.");
+ }
+ getActivity();
+ super.setUp();
+
+ mCameraTestHelper = new CameraTestHelper();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mHandler != null) {
+ mHandler.getLooper().quit();
+ mHandler = null;
+ }
+ if (mLooperThread != null) {
+ mLooperThread.join(WAIT_TIMEOUT);
+ if (mLooperThread.isAlive()) {
+ fail("Failed to stop the looper.");
+ }
+ mLooperThread = null;
+ }
+ super.tearDown();
+ }
+
+ private void runOnLooper(final Runnable command) throws InterruptedException {
+ final Semaphore sem = new Semaphore(0);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ command.run();
+ } finally {
+ sem.release();
+ }
+ }
+ });
+ if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+ fail("Failed to run the command on the looper.");
+ }
+ }
+
+ /**
+ * Functional test iterating on the range of supported exposure compensation levels
+ */
+ @LargeTest
+ public void testFunctionalCameraExposureCompensation() throws Exception {
+ try {
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Parameters params = mCameraTestHelper.getCameraParameters();
+
+ int min = params.getMinExposureCompensation();
+ int max = params.getMaxExposureCompensation();
+ assertFalse("Adjusting exposure not supported", (max == 0 && min == 0));
+ float step = params.getExposureCompensationStep();
+ int stepsPerEV = (int) Math.round(Math.pow((double) step, -1));
+
+ // only get integer values for exposure compensation
+ for (int i = min; i <= max; i += stepsPerEV) {
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCameraTestHelper.setupCameraTest();
+ }
+ });
+ Log.v(TAG, "Setting exposure compensation index to " + i);
+ params.setExposureCompensation(i);
+ mCameraTestHelper.setParameters(params);
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ mCameraTestHelper.capturePhoto();
+ }
+ mCameraTestHelper.cleanupTestImages();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera exposure compensation test Exception");
+ }
+ }
+
+ /**
+ * Functional test iterating on the various flash modes (on, off, auto, torch)
+ */
+ @LargeTest
+ public void testFunctionalCameraFlashModes() throws Exception {
+ try {
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Parameters params = mCameraTestHelper.getCameraParameters();
+ List<String> supportedFlashModes = params.getSupportedFlashModes();
+ assertNotNull("No flash modes supported", supportedFlashModes);
+
+ for (int i = 0; i < supportedFlashModes.size(); i++) {
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCameraTestHelper.setupCameraTest();
+ }
+ });
+ Log.v(TAG, "Setting flash mode to " + supportedFlashModes.get(i));
+ params.setFlashMode(supportedFlashModes.get(i));
+ mCameraTestHelper.setParameters(params);
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ mCameraTestHelper.capturePhoto();
+ }
+ mCameraTestHelper.cleanupTestImages();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera flash mode test Exception");
+ }
+ }
+
+ /**
+ * Functional test iterating on the various focus modes (auto, infinitiy, macro, etc.)
+ */
+ @LargeTest
+ public void testFunctionalCameraFocusModes() throws Exception {
+ try {
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Parameters params = mCameraTestHelper.getCameraParameters();
+ List<String> supportedFocusModes = params.getSupportedFocusModes();
+ assertNotNull("No focus modes supported", supportedFocusModes);
+
+ for (int i = 0; i < supportedFocusModes.size(); i++) {
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCameraTestHelper.setupCameraTest();
+ }
+ });
+ Log.v(TAG, "Setting focus mode to: " + supportedFocusModes.get(i));
+ params.setFocusMode(supportedFocusModes.get(i));
+ mCameraTestHelper.setParameters(params);
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ mCameraTestHelper.capturePhoto();
+ }
+ mCameraTestHelper.cleanupTestImages();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera focus modes test Exception");
+ }
+ }
+
+ /**
+ * Functional test iterating on the various white balances (auto, daylight, cloudy, etc.)
+ */
+ @LargeTest
+ public void testFunctionalCameraWhiteBalance() throws Exception {
+ try {
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Parameters params = mCameraTestHelper.getCameraParameters();
+ List<String> supportedWhiteBalance = params.getSupportedWhiteBalance();
+ assertNotNull("No white balance modes supported", supportedWhiteBalance);
+
+ for (int i = 0; i < supportedWhiteBalance.size(); i++) {
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCameraTestHelper.setupCameraTest();
+ }
+ });
+ Log.v(TAG, "Setting white balance to: " + supportedWhiteBalance.get(i));
+ params.setWhiteBalance(supportedWhiteBalance.get(i));
+ mCameraTestHelper.setParameters(params);
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ mCameraTestHelper.capturePhoto();
+ }
+ mCameraTestHelper.cleanupTestImages();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera focus modes test Exception");
+ }
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraPairwiseTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraPairwiseTest.java
new file mode 100644
index 0000000..61b708a
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/camera/CameraPairwiseTest.java
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2013 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.mediaframeworktest.functional.camera;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.ShutterCallback;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.CameraStressTestRunner;
+import com.android.mediaframeworktest.CameraTestHelper;
+import junit.framework.Assert;
+
+/**
+ * Junit / Instrumentation test case for camera API pairwise testing
+ * Settings tested against: flash mode, exposure compensation, white balance,
+ * scene mode, picture size, and geotagging
+ *
+ * adb shell am instrument
+ * - e class com.android.mediaframeworktest.stress.CameraPairwiseTest
+ * - w com.android.mediaframeworktest/.CameraStressTestRunner
+ */
+public class CameraPairwiseTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+ private CameraTestHelper mCameraTestHelper;
+ private Handler mHandler;
+ private Thread mLooperThread;
+ private String TAG = "CameraPairwiseTest";
+
+ private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
+
+ // coordinates of the Getty Museuem in Los Angeles
+ private static final double MOCK_LATITUDE = 34.076621;
+ private static final double MOCK_LONGITUDE = -118.473215;
+
+ // camera setting enums
+ public enum Flash { ON, OFF, AUTO };
+ public enum Exposure { MIN, MAX, NONE };
+ public enum WhiteBalance { DAYLIGHT, FLUORESCENT, CLOUDY, INCANDESCENT, AUTO };
+ public enum SceneMode { SUNSET, ACTION, PARTY, NIGHT, AUTO };
+ public enum PictureSize { SMALL, MEDIUM, LARGE };
+ public enum Geotagging { ON, OFF };
+
+ public CameraPairwiseTest() {
+ super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+ }
+
+ protected void setUp() throws Exception {
+ final Semaphore sem = new Semaphore(0);
+ mLooperThread = new Thread() {
+ @Override
+ public void run() {
+ Log.v(TAG, "starting looper");
+ Looper.prepare();
+ mHandler = new Handler();
+ sem.release();
+ Looper.loop();
+ Log.v(TAG, "quit looper");
+ }
+ };
+ mLooperThread.start();
+ if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+ fail("Failed to start the looper.");
+ }
+ getActivity();
+ super.setUp();
+
+ mCameraTestHelper = new CameraTestHelper();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mHandler != null) {
+ mHandler.getLooper().quit();
+ mHandler = null;
+ }
+ if (mLooperThread != null) {
+ mLooperThread.join(WAIT_TIMEOUT);
+ if (mLooperThread.isAlive()) {
+ fail("Failed to stop the looper.");
+ }
+ mLooperThread = null;
+ }
+ super.tearDown();
+ }
+
+ private void runOnLooper(final Runnable command) throws InterruptedException {
+ final Semaphore sem = new Semaphore(0);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ command.run();
+ } finally {
+ sem.release();
+ }
+ }
+ });
+ if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+ fail("Failed to run the command on the looper.");
+ }
+ }
+
+ /**
+ * Flash: Auto / Exposure: None / WB: Daylight
+ * Scene: Sunset / Pic: Medium / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario01() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
+ PictureSize.MEDIUM, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: Min / WB: Fluorescent
+ * Scene: Auto / Pic: Large / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario02() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.MIN, WhiteBalance.FLUORESCENT, SceneMode.AUTO,
+ PictureSize.LARGE, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Off / Exposure: Max / WB: Auto
+ * Scene: Night / Pic: Small / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario03() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.AUTO, SceneMode.NIGHT,
+ PictureSize.SMALL, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Off / Exposure: Max / WB: Cloudy
+ * Scene: Auto / Pic: Med / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario04() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.CLOUDY, SceneMode.AUTO,
+ PictureSize.MEDIUM, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Auto / Exposure: Max / WB: Incandescent
+ * Scene: Auto / Pic: Large / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario05() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.INCANDESCENT,
+ SceneMode.AUTO, PictureSize.LARGE, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: None / WB: Cloudy
+ * Scene: Auto / Pic: Small / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario06() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.CLOUDY, SceneMode.AUTO,
+ PictureSize.SMALL, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Auto / Exposure: Min / WB: Auto
+ * Scene: Action / Pic: Small / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario07() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.AUTO, SceneMode.ACTION,
+ PictureSize.SMALL, Geotagging.ON);
+ }
+
+ /**
+ * Flash: On / Exposure: Min / WB: Auto
+ * Scene: Action / Pic: Medium / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario08() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.MIN, WhiteBalance.AUTO, SceneMode.ACTION,
+ PictureSize.MEDIUM, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Off / Exposure: Min / WB: Auto
+ * Scene: Night / Pic: Large / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario09() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.AUTO, SceneMode.NIGHT,
+ PictureSize.LARGE, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Off / Exposure: Min / WB: Daylight
+ * Scene: Sunset / Pic: Small / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario10() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
+ PictureSize.SMALL, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: Max / WB: Daylight
+ * Scene: Sunset / Pic: Large / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario11() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
+ PictureSize.LARGE, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Auto / Exposure: Min / WB: Cloudy
+ * Scene: Auto / Pic: Large / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario12() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.CLOUDY, SceneMode.AUTO,
+ PictureSize.LARGE, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Off / Exposure: None / WB: Auto
+ * Scene: Party / Pic: Medium / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario13() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.NONE, WhiteBalance.AUTO, SceneMode.PARTY,
+ PictureSize.MEDIUM, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Auto / Exposure: None / WB: Auto
+ * Scene: Night / Pic: Small / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario14() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.AUTO, SceneMode.NIGHT,
+ PictureSize.SMALL, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: None / WB: Incandescent
+ * Scene: Auto / Pic: Medium / Geo: on
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario15() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.INCANDESCENT, SceneMode.AUTO,
+ PictureSize.MEDIUM, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Auto / Exposure: Min / WB: Auto
+ * Scene: Party / Pic: Small / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario16() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.AUTO, SceneMode.PARTY,
+ PictureSize.SMALL, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Off / Exposure: Min / WB: Incandescent
+ * Scene: Auto / Pic: Small / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario17() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.INCANDESCENT, SceneMode.AUTO,
+ PictureSize.SMALL, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: None / WB: Auto
+ * Scene: Party / Pic: Large / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario18() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.AUTO, SceneMode.PARTY,
+ PictureSize.LARGE, Geotagging.OFF);
+ }
+
+ /**
+ * Flash Off / Exposure: None / WB: Auto
+ * Scene: Action / Pic: Large / Geo: off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario19() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.NONE, WhiteBalance.AUTO, SceneMode.ACTION,
+ PictureSize.LARGE, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Off / Exposure: Max / WB: Fluorescent
+ * Scene: Auto / Pic: Medium / Geo: Off
+ */
+ @LargeTest
+ public void testCameraPairwiseScenario20() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.FLUORESCENT, SceneMode.AUTO,
+ PictureSize.MEDIUM, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Off / Exposure: Min / WB: Auto
+ * Scene: Auto / Pic: Medium / Geo: off
+ */
+ public void testCameraPairwiseScenario21() throws Exception {
+ genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.AUTO, SceneMode.AUTO,
+ PictureSize.MEDIUM, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: Max / WB: Auto
+ * Scene: Action / Pic: Small / Geo: off
+ */
+ public void testCameraPairwiseScenario22() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.AUTO, SceneMode.ACTION,
+ PictureSize.SMALL, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: On / Exposure: Max / WB: Auto
+ * Scene: Night / Pic: Medium / Geo: on
+ */
+ public void testCameraPairwiseScenario23() throws Exception {
+ genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.AUTO, SceneMode.NIGHT,
+ PictureSize.MEDIUM, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Auto / Exposure: None / WB: Fluorescent
+ * Scene: Auto / Pic: Small / Geo: on
+ */
+ public void testCameraPairwiseScenario24() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.FLUORESCENT,
+ SceneMode.AUTO, PictureSize.SMALL, Geotagging.ON);
+ }
+
+ /**
+ * Flash: Auto / Exposure: Max / WB: Daylight
+ * Scene: Auto / Pic: Medium / Geo: off
+ */
+ public void testCameraPairwiseScenario25() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.DAYLIGHT, SceneMode.AUTO,
+ PictureSize.MEDIUM, Geotagging.OFF);
+ }
+
+ /**
+ * Flash: Auto / Exposure: Max / WB: Auto
+ * Scene: Party / Pic: Medium / Geo: on
+ */
+ public void testCameraPairwiseScenario26() throws Exception {
+ genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.AUTO, SceneMode.PARTY,
+ PictureSize.MEDIUM, Geotagging.ON);
+ }
+
+ /**
+ * Generic pairwise test method
+ */
+ private void genericPairwiseTestCase(Flash flash, Exposure exposure, WhiteBalance whitebalance,
+ SceneMode scenemode, PictureSize picturesize, Geotagging geotagging) throws Exception {
+ try {
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Camera.Parameters params = mCameraTestHelper.getCameraParameters();
+
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCameraTestHelper.setupCameraTest();
+ }
+ });
+
+ // Configure flash setting
+ switch (flash) {
+ case ON:
+ params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
+ break;
+ case OFF:
+ params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
+ break;
+ case AUTO:
+ params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
+ break;
+ }
+
+ // Configure exposure setting
+ switch (exposure) {
+ case MIN:
+ params.setExposureCompensation(params.getMinExposureCompensation());
+ break;
+ case MAX:
+ params.setExposureCompensation(params.getMaxExposureCompensation());
+ break;
+ case NONE:
+ params.setExposureCompensation(0);
+ break;
+ }
+
+ // Configure white balance setting
+ switch (whitebalance) {
+ case DAYLIGHT:
+ params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
+ break;
+ case FLUORESCENT:
+ params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_FLUORESCENT);
+ break;
+ case INCANDESCENT:
+ params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_INCANDESCENT);
+ break;
+ case CLOUDY:
+ params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
+ break;
+ case AUTO:
+ params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
+ break;
+ }
+
+ // Configure scene mode setting
+ switch (scenemode) {
+ case SUNSET:
+ params.setSceneMode(Camera.Parameters.SCENE_MODE_SUNSET);
+ break;
+ case ACTION:
+ params.setSceneMode(Camera.Parameters.SCENE_MODE_ACTION);
+ break;
+ case PARTY:
+ params.setSceneMode(Camera.Parameters.SCENE_MODE_PARTY);
+ break;
+ case NIGHT:
+ params.setSceneMode(Camera.Parameters.SCENE_MODE_NIGHT);
+ break;
+ case AUTO:
+ params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
+ break;
+ }
+
+ // Configure picture size setting
+ List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
+ int mid = (int) Math.floor(supportedPictureSizes.size() / 2);
+ int low = supportedPictureSizes.size() - 1;
+ switch (picturesize) {
+ case SMALL:
+ params.setPictureSize(supportedPictureSizes.get(low).width,
+ supportedPictureSizes.get(low).height);
+ break;
+ case MEDIUM:
+ params.setPictureSize(supportedPictureSizes.get(mid).width,
+ supportedPictureSizes.get(mid).height);
+ break;
+ case LARGE:
+ params.setPictureSize(supportedPictureSizes.get(0).width,
+ supportedPictureSizes.get(mid).height);
+ break;
+ }
+
+ // Configure geotagging setting
+ switch (geotagging) {
+ case ON:
+ params.setGpsLatitude(MOCK_LATITUDE);
+ params.setGpsLongitude(MOCK_LONGITUDE);
+ break;
+ case OFF:
+ break;
+ }
+
+ mCameraTestHelper.setParameters(params);
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ mCameraTestHelper.capturePhoto();
+ mCameraTestHelper.cleanupTestImages();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Test case failed");
+ }
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
index ed1d8fc..a112c73 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
@@ -17,13 +17,11 @@
package com.android.mediaframeworktest.stress;
import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.CameraTestHelper;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FilenameFilter;
import java.io.FileWriter;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.util.concurrent.Semaphore;
@@ -31,8 +29,7 @@
import java.util.List;
import android.hardware.Camera;
-import android.hardware.Camera.PictureCallback;
-import android.hardware.Camera.ShutterCallback;
+import android.hardware.Camera.Parameters;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
@@ -45,32 +42,28 @@
import junit.framework.Assert;
/**
- * Junit / Instrumentation test case for the camera zoom and scene mode APIs
+ * Junit / Instrumentation test case for the following camera APIs:
+ * - camera zoom
+ * - scene mode
*
* adb shell am instrument
* -e class com.android.mediaframeworktest.stress.CameraStressTest
* -w com.android.mediaframeworktest/.CameraStressTestRunner
*/
public class CameraStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
- private String TAG = "CameraStressTest";
- private Camera mCamera;
- private static final int CAMERA_ID = 0;
- private static final int NUMBER_OF_ZOOM_LOOPS = 100;
private static final int NUMBER_OF_SCENE_MODE_LOOPS = 10;
- private static final long WAIT_GENERIC = 3 * 1000; // 3 seconds
+ private static final int NUMBER_OF_ZOOM_LOOPS = 100;
private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
- private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
- private static final String CAMERA_STRESS_IMAGES_DIRECTORY = "cameraStressImages";
- private static final String CAMERA_STRESS_IMAGES_PREFIX = "camera-stress-test";
private static final String CAMERA_STRESS_OUTPUT = "cameraStressOutput.txt";
- private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
- private Thread mLooperThread;
+ private CameraTestHelper mCameraTestHelper;
private Handler mHandler;
-
+ private Thread mLooperThread;
private Writer mOutput;
+ private String TAG = "CameraStressTest";
+
public CameraStressTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
}
@@ -95,19 +88,11 @@
getActivity();
super.setUp();
- File sdcard = Environment.getExternalStorageDirectory();
-
- // Create the test images directory if it doesn't exist
- File stressImagesDirectory = new File(String.format("%s/%s", sdcard,
- CAMERA_STRESS_IMAGES_DIRECTORY));
- if (!stressImagesDirectory.exists()) {
- stressImagesDirectory.mkdir();
- }
-
- // Start writing output file
- File stressOutFile = new File(String.format("%s/%s",sdcard, CAMERA_STRESS_OUTPUT));
+ mCameraTestHelper = new CameraTestHelper();
+ File stressOutFile = new File(String.format("%s/%s",
+ Environment.getExternalStorageDirectory(), CAMERA_STRESS_OUTPUT));
mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
- mOutput.write(this.getName() + ":\n");
+ mOutput.write(this.getName() + "\n");
}
@Override
@@ -123,10 +108,8 @@
}
mLooperThread = null;
}
-
mOutput.write("\n\n");
mOutput.close();
-
super.tearDown();
}
@@ -147,182 +130,14 @@
}
}
- private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
- public void onError(int error, android.hardware.Camera camera) {
- fail(String.format("Camera error, code: %d", error));
- }
- }
-
- private ShutterCallback shutterCallback = new ShutterCallback() {
- @Override
- public void onShutter() {
- Log.v(TAG, "Shutter");
- }
- };
-
- private PictureCallback rawCallback = new PictureCallback() {
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- Log.v(TAG, "Raw picture taken");
- }
- };
-
- private PictureCallback jpegCallback = new PictureCallback() {
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- FileOutputStream fos = null;
-
- try {
- Log.v(TAG, "JPEG picture taken");
- fos = new FileOutputStream(String.format("%s/%s/%s-%d.jpg",
- Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY,
- CAMERA_STRESS_IMAGES_PREFIX, System.currentTimeMillis()));
- fos.write(data);
- } catch (FileNotFoundException e) {
- Log.e(TAG, "File not found: " + e.toString());
- } catch (IOException e) {
- Log.e(TAG, "Error accessing file: " + e.toString());
- } finally {
- try {
- if (fos != null) {
- fos.close();
- }
- } catch (IOException e) {
- Log.e(TAG, "Error closing file: " + e.toString());
- }
- }
- }
- };
-
- // Helper method for cleaning up pics taken during testStressCameraZoom
- private void cleanupStressTestImages() {
- try {
- File stressImagesDirectory = new File(String.format("%s/%s",
- Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
- File[] zoomImages = null;
-
- FilenameFilter filter = new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.startsWith(CAMERA_STRESS_IMAGES_PREFIX);
- }
- };
-
- zoomImages = stressImagesDirectory.listFiles(filter);
-
- for (File f : zoomImages) {
- f.delete();
- }
- } catch (SecurityException e) {
- Log.e(TAG, "Security manager access violation: " + e.toString());
- }
- }
-
- // Helper method for starting up the camera preview
- private void startCameraPreview(SurfaceHolder surfaceHolder) {
- try {
- mCamera.setErrorCallback(mCameraErrorCallback);
- mCamera.setPreviewDisplay(surfaceHolder);
- mCamera.startPreview();
- Thread.sleep(WAIT_GENERIC);
- } catch (IOException e) {
- Log.e(TAG, "Error setting preview display: " + e.toString());
- } catch (InterruptedException e) {
- Log.e(TAG, "Error waiting for preview to come up: " + e.toString());
- } catch (Exception e) {
- Log.e(TAG, "Error starting up camera preview: " + e.toString());
- }
- }
-
- // Helper method for taking a photo
- private void capturePhoto() {
- try {
- mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
- Thread.sleep(WAIT_GENERIC);
- mCamera.stopPreview();
- mCamera.release();
- } catch (InterruptedException e) {
- Log.e(TAG, "Error waiting for photo to be taken: " + e.toString());
- } catch (Exception e) {
- Log.e(TAG, "Error capturing photo: " + e.toString());
- }
- }
-
- // Test case for stressing the camera zoom in/out feature
- @LargeTest
- public void testStressCameraZoom() throws Exception {
- SurfaceHolder mSurfaceHolder;
- mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
- mOutput.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
-
- try {
- Log.v(TAG, "Start preview");
- mOutput.write("No of loop: ");
-
- mCamera = Camera.open(CAMERA_ID);
- Camera.Parameters params = mCamera.getParameters();
- mCamera.release();
-
- if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
- Log.v(TAG, "Device camera does not support zoom");
- fail("Camera zoom stress test failed");
- } else {
- Log.v(TAG, "Device camera does support zoom");
-
- int nextZoomLevel = 0;
-
- for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
- runOnLooper(new Runnable() {
- @Override
- public void run() {
- mCamera = Camera.open(CAMERA_ID);
- }
- });
-
- startCameraPreview(mSurfaceHolder);
- params = mCamera.getParameters();
- int currentZoomLevel = params.getZoom();
-
- if (nextZoomLevel >= params.getMaxZoom()) {
- nextZoomLevel = 0;
- }
- ++nextZoomLevel;
-
- if (params.isSmoothZoomSupported()) {
- mCamera.startSmoothZoom(nextZoomLevel);
- } else {
- params.setZoom(nextZoomLevel);
- mCamera.setParameters(params);
- }
- Log.v(TAG, "Zooming from " + currentZoomLevel + " to " + nextZoomLevel);
-
- // sleep allows for zoom animation to finish
- Thread.sleep(WAIT_ZOOM_ANIMATION);
- capturePhoto();
-
- if (i == 0) {
- mOutput.write(Integer.toString(i));
- } else {
- mOutput.write(", " + i);
- }
- }
- }
- cleanupStressTestImages();
- } catch (Exception e) {
- Log.e(TAG, e.toString());
- fail("Camera zoom stress test Exception");
- }
- }
-
- // Test case for stressing the camera scene mode feature
+ /**
+ * Stress test iterating on the various scene modes (action, night, party, etc.)
+ */
@LargeTest
public void testStressCameraSceneModes() throws Exception {
- SurfaceHolder mSurfaceHolder;
- mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
-
try {
- mCamera = Camera.open(CAMERA_ID);
- Camera.Parameters params = mCamera.getParameters();
- mCamera.release();
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Parameters params = mCameraTestHelper.getCameraParameters();
List<String> supportedSceneModes = params.getSupportedSceneModes();
assertNotNull("No scene modes supported", supportedSceneModes);
@@ -336,27 +151,85 @@
runOnLooper(new Runnable() {
@Override
public void run() {
- mCamera = Camera.open(CAMERA_ID);
+ mCameraTestHelper.setupCameraTest();
}
});
-
- startCameraPreview(mSurfaceHolder);
- Log.v(TAG, "Setting mode to " + supportedSceneModes.get(i));
+ Log.v(TAG, "Setting scene mode to " + supportedSceneModes.get(i));
params.setSceneMode(supportedSceneModes.get(i));
- mCamera.setParameters(params);
- capturePhoto();
+ mCameraTestHelper.setParameters(params);
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ mCameraTestHelper.capturePhoto();
- if ((i == 0) && (j == 0)) {
+ if (i == 0 && j == 0) {
mOutput.write(Integer.toString(j + i * NUMBER_OF_SCENE_MODE_LOOPS));
} else {
mOutput.write(", " + (j + i * NUMBER_OF_SCENE_MODE_LOOPS));
}
}
}
- cleanupStressTestImages();
+ mCameraTestHelper.cleanupTestImages();
} catch (Exception e) {
Log.e(TAG, e.toString());
fail("Camera scene mode test Exception");
}
}
+
+ /**
+ * Stress test iterating on the range of supported camera zoom levels
+ */
+ @LargeTest
+ public void testStressCameraZoom() throws Exception {
+ try {
+ SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+ Parameters params = mCameraTestHelper.getCameraParameters();
+
+ if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
+ Log.v(TAG, "Device camera does not support zoom");
+ fail("Camera zoom stress test failed due to unsupported feature");
+ } else {
+ Log.v(TAG, "Device camera does support zoom");
+ Log.v(TAG, "Start preview");
+ mOutput.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
+ mOutput.write("No of loops: ");
+
+ int nextZoomLevel = 0;
+
+ for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
+ runOnLooper(new Runnable() {
+ @Override
+ public void run() {
+ mCameraTestHelper.setupCameraTest();
+ }
+ });
+
+ mCameraTestHelper.startCameraPreview(surfaceHolder);
+ params = mCameraTestHelper.mCamera.getParameters();
+ int currentZoomLevel = params.getZoom();
+
+ if (nextZoomLevel >= params.getMaxZoom()) {
+ nextZoomLevel = 0;
+ }
+ ++nextZoomLevel;
+
+ if (params.isSmoothZoomSupported()) {
+ mCameraTestHelper.mCamera.startSmoothZoom(nextZoomLevel);
+ } else {
+ params.setZoom(nextZoomLevel);
+ mCameraTestHelper.setParameters(params);
+ }
+ mCameraTestHelper.capturePhoto();
+
+ if (i == 0) {
+ mOutput.write(Integer.toString(i));
+ } else {
+ mOutput.write(", " + i);
+ }
+ }
+ }
+ mCameraTestHelper.cleanupTestImages();
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ fail("Camera zoom stress test Exception");
+ }
+ }
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 41da158..0970248 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -117,7 +117,6 @@
private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
- protected int mPlaybackState;
protected int mClientGeneration;
/*package*/ interface UserSwitcherCallback {
@@ -204,10 +203,9 @@
.getCachedDisplayClientState();
mTransportState = (dcs.clearing ? TRANSPORT_GONE :
(isMusicPlaying(dcs.playbackState) ? TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
- mPlaybackState = dcs.playbackState;
if (DEBUG) Log.v(TAG, "Initial transport state: "
- + mTransportState + ", pbstate=" + mPlaybackState);
+ + mTransportState + ", pbstate=" + dcs.playbackState);
}
private void cleanupAppWidgetIds() {
@@ -273,18 +271,27 @@
Log.v(TAG, (clearing ? "hide" : "show") + " transport, gen:" + clientGeneration);
}
mClientGeneration = clientGeneration;
- mTransportState = (clearing ? TRANSPORT_GONE : TRANSPORT_INVISIBLE);
- KeyguardHostView.this.post(mSwitchPageRunnable);
+ final int newState = (clearing ? TRANSPORT_GONE
+ : (mTransportState == TRANSPORT_VISIBLE ?
+ TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
+ if (newState != mTransportState) {
+ mTransportState = newState;
+ if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
+ KeyguardHostView.this.post(mSwitchPageRunnable);
+ }
}
@Override
public void onMusicPlaybackStateChanged(int playbackState, long eventTime) {
- mPlaybackState = playbackState;
if (DEBUGXPORT) Log.v(TAG, "music state changed: " + playbackState);
if (mTransportState != TRANSPORT_GONE) {
- mTransportState = (isMusicPlaying(mPlaybackState) ?
+ final int newState = (isMusicPlaying(playbackState) ?
TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE);
+ if (newState != mTransportState) {
+ mTransportState = newState;
+ if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
+ KeyguardHostView.this.post(mSwitchPageRunnable);
+ }
}
- KeyguardHostView.this.post(mSwitchPageRunnable);
}
};
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 89a8dd7..0ca5f98 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Kennisgewings verskyn hier"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Verkry enige tyd toegang tot hulle deur af te sleep."\n"Sleep weer af vir stelselkontroles."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Sleep op vanaf onderkant van skerm om stelselbalk te wys"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Sleep onderkant van skerm om balk te wys"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sleep van regterkant van skerm af om stelselbalk te wys"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e6dad88..4308ec3 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"ማሳወቂያዎች እዚህ ላይ ይታያሉ"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"ወደ ታች በማንሸራተት በማንኛውም ጊዜ ይድረሱባቸው።"\n"Swipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"የስርዓት አሞሌውን ለማሳየት ከማያ ገጹ ታችኛው ክፍል ጀምረው ወደላይ ያንሸራትቱ"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"አሞሌውን ለማሳየት የማያ ገጹ ታችኛው ክፍል ያንሸራትቱ"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"አሞሌውን ለማሳየት ከማያ ገጹ ቀኝ ክፍል ጀምረው ያንሸራትቱ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 110ebc0..1f0c757 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"تظهر الإشعارات هنا"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"يمكنك الدخول إليها في أي وقت بالتمرير السريع إلى أسفل."\n"يمكنك التمرير السريع إلى أسفل مرة أخرى للوصول إلى عناصر تحكم النظام."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"مرر سريعًا من أسفل الشاشة لإظهار شريط النظام"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"مرر سريعًا أسفل الشاشة لإظهار الشريط"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"مرر سريعًا من يمين الشاشة لإظهار شريط النظام"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c66e912..b45ddb6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АЎТА"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Апавяшчэнні з\'яўляюцца тут"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Атрымлівайце доступ да іх у любы час, праводзячы пальцам уніз."\n"Правядзіце пальцам уніз яшчэ раз, каб атрымаць доступ да сродкаў кіравання сістэмай."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Правядзіце па экрану знізу ўверх, каб адлюстраваць сістэмны радок"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Правядзіце па ніжняй частцы экрану, каб адлюстраваць радок"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Правядзіце ад правага краю экрану, каб адлюстраваць сістэмны радок"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index e3f7dc1..c161fbd 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Известията се показват тук"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Осъществявайте достъп до тях по всяко време, като прекарате пръст надолу."\n"Направете го отново за системните контроли."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Прекарайте пръст нагоре от долната част на екрана, за да се покаже системната лента"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Прекарайте пръст от долната част на екрана, за да се покаже лентата"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Прекарайте пръст отдясно на екрана, за да се покаже системната лента"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 580bfe7..5cf131d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Les notificacions apareixen aquí"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Accedeix-hi en qualsevol moment: només has de fer lliscar el dit cap avall."\n"Torna a fer lliscar el dit cap avall per fer que es mostrin els controls del sistema."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Fes lliscar el dit des de la part inferior de la pantalla perquè es mostri la barra del sistema"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Fes lliscar el dit des de la part inferior de la pantalla perquè es mostri la barra"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Fes lliscar el dit des de la dreta de la pantalla perquè es mostri la barra del sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a623612..0f03db1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Zde se zobrazují oznámení"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Můžete je kdykoli zobrazit tím, že přejedete prstem dolů."\n"Přejedete-li prstem dolů ještě jednou, zobrazí se ovládací prvky systému."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Systémový panel zobrazíte přejetím ze spodní části obrazovky nahoru"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Panel zobrazíte přejetím zdola nahoru"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Systémový panel zobrazíte přejetím z pravé strany obrazovky"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 7f7a51c..b6a92a6 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Underretninger vises her"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Få adgang til dem når som helst ved at stryge ned."\n"Stryg ned igen for at komme til systemindstillingerne."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Stryg op fra bunden af skærmen for at vise systembjælken."</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Stryg bunden af skærmen for at vise bjælken"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Stryg fra skærmens højre side for at vise systembjælken"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2b226b6..3a3c451 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Benachrichtigungen erscheinen hier"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Greifen Sie jederzeit auf sie zu, indem Sie nach unten wischen."\n"Wischen Sie für Systemeinstellungen erneut nach unten."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Zum Einblenden der Systemleiste auf dem Display von unten nach oben wischen"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Zum Einblenden der Leiste nach oben wischen"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Zum Einblenden der Systemleiste auf dem Display von rechts nach links wischen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index dae50a3..befd927 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Οι ειδοποιήσεις εμφανίζονται εδώ"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Μεταβείτε σε αυτές ανά πάσα στιγμή σύροντας προς τα κάτω."\n"Σύρετε ξανά προς τα κάτω για τα στοιχεία ελέγχου συστήματος."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Σύρετε προς τα επάνω από το κάτω μέρος της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Σύρετε από το κάτω μέρος της οθόνης για να εμφανίσετε τη γραμμή"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Σύρετε από τη δεξιά πλευρά της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7e74e40..1427c87 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down."\n"Swipe down again for system controls."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Swipe up from bottom of screen to reveal system bar"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Swipe bottom of screen to reveal bar"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Swipe from right of screen to reveal system bar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1fe4d46..21c6e750 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí."</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Desliza el dedo hacia arriba desde la parte inferior de la pantalla para mostrar la barra del sistema."</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Desliza el dedo desde la parte inferior de la pantalla para mostrar la barra."</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Desliza el dedo desde la parte derecha de la pantalla para mostrar la barra del sistema."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 19de9b6..b2cb952 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Desliza la pantalla hacia arriba desde la parte inferior para mostrar la barra del sistema"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Desliza la parte inferior de la pantalla para mostrar la barra"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Desliza la pantalla desde la derecha para mostrar la barra del sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 5339006..e2324b5 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Märguanded ilmuvad siia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Juurdepääs igal ajal sõrmega alla pühkides."\n"Süsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Süsteemiriba kuvamiseks pühkige ekraani allosast üles"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Riba kuvamiseks pühkige ekraani allosas"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Süsteemiriba kuvamiseks pühkige ekraani paremast servast"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e766df8..a3eb06b 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"اعلانها در اینجا نمایش داده میشوند"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"با کشیدن انگشت به طرف پایین به آنها دسترسی پیدا کنید."\n"برای کنترلهای سیستم دوباره انگشت خود را به سمت پایین بکشید."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"برای آشکارسازی نوار سیستم انگشت خود را از پایین صفحه به بالا بکشید"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"برای آشکارسازی نوار انگشت خود را روی پایین صفحه بکشید"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"برای آشکارسازی نوار سیستم انگشت خود را از سمت راست صفحه بکشید"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 8e80016..c975970 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Ilmoitukset näkyvät tässä"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Näet ilmoitukset liu\'uttamalla sormea alas ruudulla."\n"Voit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun alalaidasta ylöspäin"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Tuo palkki näkyviin liu\'uttamalla ruudun alaosasta"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun oikeasta laidasta vasemmalle"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 294c0ee..3b7f798 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas."\n"Répétez l\'opération pour accéder aux commandes du système."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Faites glisser votre doigt de bas en haut sur l\'écran pour afficher la barre système."</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Faites glisser votre doigt au bas de l\'écran pour afficher la barre."</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Faites glisser votre doigt de droite à gauche sur l\'écran pour afficher la barre système."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index cdcda79..05fffc36 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"सूचनाएं यहां दिखाई देती हैं"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"नीचे स्वाइप करके उन तक कभी भी पहुंचें."\n"सिस्टम नियंत्रणों के लिए पुन: नीचे स्वाइप करें."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"सिस्टम बार दिखाने के लिए स्क्रीन के नीचे से ऊपर की ओर स्वाइप करें"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"बार दिखाने के लिए स्क्रीन के नीचे स्वाइप करें"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"सिस्टम बार दिखाने के लिए स्क्रीन की दाईं ओर से स्वाइप करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 93e03d1..0f7f92f 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Obavijesti se prikazuju ovdje"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Pristupite im u bilo kojem trenutku tako da prstom trznete prema dolje. "\n"Ponovo prstom trznite prema dolje za kontrole sustava."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Prijeđite prstom od dna zaslona prema gore da bi se prikazala traka sustava"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Prijeđite prstom po dnu zaslona da bi se prikazala traka"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Prijeđite prstom od desne strane zaslona da bi se prikazala traka sustava"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 27bf2f5..82b3ddd 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Az értesítések itt jelennek meg."</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Bármikor elérheti őket, ha lefelé húzza az ujját."\n"Húzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Csúsztassa ujját a képernyő aljától felfelé a rendszersáv megjelenítéséhez"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Csúsztassa ujját a képernyő alján a sáv megjelenítéséhez"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Csúsztassa ujját a képernyő jobb oldalától a rendszersáv megjelenítéséhez"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 581c56c..d9597da 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan muncul di sini"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Akses kapan saja dengan menggesek ke bawah."\n"Gesek ke bawah sekali lagi untuk kontrol sistem."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Gesek ke atas dari bagian bawah layar untuk membuka bilah sistem"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Gesek bagian bawah layar untuk membuka bilah"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Gesek dari bagian kanan layar untuk membuka bilah sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 3d7cb76..6ef9a8e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Le notifiche vengono visualizzate qui"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Puoi accedervi in qualsiasi momento scorrendo verso il basso."\n"Fai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Fai scorrere il dito verso l\'alto dalla parte inferiore dello schermo per visualizzare la barra di sistema"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Fai scorrere parte inferiore dello schermo per visualizzare la barra"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Fai scorrere il dito dalla parte destra dello schermo per visualizzare la barra di sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8dd00d1..8a3f1550 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"הודעות מופיעות כאן"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"גש אליהם בכל עת על ידי החלקה למטה."\n"החלק למטה שוב למעבר למרכז הבקרה של המערכת."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"החלק מעלה מתחתית המסך כדי להציג את סרגל המערכת"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"החלק מתחתית המסך כדי להציג את הסרגל"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"החלק מצד ימין של המסך כדי להציג את סרגל המערכת"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b64d73e..95f24fd 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"ここに通知が表示されます"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"下にスワイプすると、いつでも通知を表示できます。"\n"システムを管理するにはもう一度下にスワイプしてください。"</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"システムバーを表示するには、画面下部から上方向にスワイプします"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"バーを表示するには、画面下部からスワイプします"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"システムバーを表示するには、画面右からスワイプします"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3f7c520..dc82a01 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"알림이 여기에 표시됨"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"아래로 스와이프하여 언제든 액세스하세요."\n"한 번 더 아래로 스와이프하면 시스템 관리로 이동합니다."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"화면 하단에서 위로 스와이프하여 시스템 표시줄 표시"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"화면 하단에서 스와이프하여 표시줄 표시"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"화면 오른쪽에서 스와이프하여 시스템 표시줄 표시"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 02d0c5b..b2c5d2c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pranešimai rodomi čia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Perbraukę žemyn bet kuriuo metu pasieksite pranešimus."\n"Jei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite aukštyn iš ekrano apačios"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Jei norite, kad būtų rodoma juosta, perbraukite ekrano apačioje"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite iš ekrano dešinės"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 372389f..41d1158 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Šeit tiek rādīti paziņojumi"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Piekļūstiet tiem jebkurā laikā, velkot uz leju."\n"Vēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Velciet augšup no ekrāna apakšdaļas, lai tiktu parādīta sistēmas josla."</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Velciet no ekrāna apakšdaļas, lai tiktu parādīta josla."</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Velciet no ekrāna labās malas, lai tiktu parādīta sistēmas josla."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8505377..cabd7b5 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah."\n"Leret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Leret ke atas dari bahagian bawah skrin untuk mendedahkan bar sistem"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Leret ke bahagian bawah skrin untuk mendedahkan bar"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Leret dari kanan skrin untuk mendedahkan bar sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7a7c5a5..31953c3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Varslene vises her"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Bruk dem når som helst ved å sveipe nedover."\n"Sveip nedover igjen for å gå til systemkontrollene."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Sveip opp fra bunnen av skjermen for å få frem systemfeltet"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Sveip på bunnen av skjermen for å få frem feltet"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sveip fra høyre på skjermen for å få frem systemfeltet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3a3c820..6661bfa 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Meldingen worden hier weergegeven"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"U kunt de meldingen op elk gewenst moment openen door met uw vinger omlaag te vegen."\n"Veeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Veeg omhoog vanaf de onderkant van het scherm om de systeembalk weer te geven"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Veeg onderkant van scherm om balk weer te geven"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Veeg vanaf de rechterkant van het scherm om de systeembalk weer te geven"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index fff1aa0..c97372d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Tutaj pokazują się powiadomienia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Możesz je otworzyć w dowolnej chwili, przesuwając w dół."\n"Przesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Przesuń palcem od dołu ekranu, by odkryć pasek systemu"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Przesuń palcem dół ekranu, by odkryć pasek"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Przesuń palcem od prawej strony ekranu, by odkryć pasek systemu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 5976e0e..eba6c18 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"As notificações são apresentadas aqui"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Pode aceder em qualquer altura, deslizando rapidamente para baixo com o dedo."\n"Deslize novamente para baixo para aceder aos controlos do sistema."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Deslize p/ cima a partir da parte inferior do ecrã p/ revelar a barra do sistema"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Deslize da parte inferior do ecrã p/ revelar a barra"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Deslize da direita do ecrã p/ revelar a barra do sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0cfd805..93b0e2d 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"As notificações aparecem aqui"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Acesse a qualquer momento deslizando para baixo."\n"Deslize para baixo novamente para acessar os controles do sistema."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Deslize de cima para baixo na tela para ver a barra do sistema"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Deslize para baixo para ver a barra"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Deslize da direita para a esquerda na tela para ver a barra do sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 606160b..948b959 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -376,4 +376,10 @@
<skip />
<!-- no translation found for status_bar_help_text (7874607155052076323) -->
<skip />
+ <!-- no translation found for hideybar_confirmation_message_bottom (4678097945183429216) -->
+ <skip />
+ <!-- no translation found for hideybar_confirmation_message_bottom_short (4014207345313478943) -->
+ <skip />
+ <!-- no translation found for hideybar_confirmation_message_right (5359586491708388067) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 44b4b4e..7faa2e4 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Notificările se afişează aici"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Accesaţi-le oricând glisând în jos."\n"Glisaţi în jos din nou pentru comenzile sistemului."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Glisați în sus din partea inferioară a ecranului pentru a afișa bara de sistem"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Glisați dinspre partea inferioară a ecranului pentru a afișa bara"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Glisați din partea dreaptă a ecranului pentru a afișa bara de sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9fabb39..2ca195a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -207,4 +207,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Это панель уведомлений"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Ее можно открыть, пролистнув экран вниз."\n"Чтобы открыть настройки, проведите пальцем вниз ещё раз."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Чтобы увидеть строку состояния, проведите пальцем от нижней части экрана вверх"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Чтобы увидеть строку состояния, проведите по экрану снизу вверх"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Чтобы увидеть строку состояния, проведите пальцем по экрану справа налево"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c5143dd..e5e1d58 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Tu sa zobrazujú upozornenia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Môžete ich kedykoľvek zobraziť tak, že posuniete prstom nadol."\n"Ak posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Systémový panel zobrazíte posunutím z dolnej časti obrazovky smerom nahor"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Panel zobrazíte posunutím zdola nahor"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Systémový panel zobrazíte posunutím z pravej strany obrazovky"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 48f0893..5a0f46a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Obvestila so prikazana tukaj"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Do njih lahko kadar koli dostopate tako, da povlečete navzdol."\n"Za prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Povlecite navzgor z dna zaslona, da prikažete sistemsko vrstico"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Prikažite vrstico tako, da povlečete na dnu zaslona"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sistemsko vrstico prikažete tako, da povlečete z desne strani zaslona"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 42ab38a..6a209d05 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Обавештења се појављују овде"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Приступите им у било ком тренутку листањем надоле."\n"Поново листајте надоле да би се приказале системске контроле."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Превуците нагоре од доњег дела екрана да би се приказала системска трака"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Превуците од доњег дела екрана да би се приказала трака"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Превуците од десне стране екрана да би се приказала системска трака"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4ddcb84..b1c1cf6 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Du kommer åt dem när som helst genom att dra nedåt."\n"Dra nedåt igen om du vill visa systemkontroller."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Dra uppåt från skärmens nederkant om du vill visa systemfältet"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Dra uppåt på skärmen om du vill visa fältet"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Dra från högersidan av skärmen om du vill visa systemfältet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d5c8282..2c8100d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -201,4 +201,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Wafikie wakati wowote kwa kupapasa chini."\n"Papasa chini tena kupata vidhibiti vya mfumo."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Papasa kwenda juu kutoka chini ya skrini ili kuonyesha upau wa mfumo"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Papasa chini ya skrini ili kuonyesha upau"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Papasa kutoka kulia kwa skrini ili kuonyesha upau wa mfumo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 20d165f..f36e07f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"การแจ้งเตือนจะแสดงขึ้นที่นี่"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"เข้าถึงได้ทุกเมื่อด้วยการกวาดนิ้วลง"\n"กวาดนิ้วลงอีกครั้งสำหรับการควบคุมระบบ"</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"กวาดขึ้นจากด้านล่างของหน้าจอเพื่อแสดงแถบระบบ"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"กวาดด้านล่างของหน้าจอเพื่อแสดงแถบ"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"กวาดจากด้านขวาของหน้าจอเพื่อแสดงแถบระบบ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 48dca2d..68b7896 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Dito lumalabas ang mga notification"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"I-access ang mga ito anumang oras sa pamamagitan ng pag-swipe pababa."\n"Muling mag-swipe pababa para sa mga kontrol ng system."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Mag-swipe pataas mula sa ibaba ng screen upang ipakita ang system bar"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Mag-swipe sa ibaba ng screen upang ipakita ang bar"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Mag-swipe mula sa kanan ng screen upang ipakita ang system bar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 5d64286..0017a9e 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Bildirimler burada görünür"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Aşağıya hızlıca kaydırarak bunlara istediğiniz zaman erişebilirsiniz."\n"Sistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Sistem çubuğunu görüntülemek için ekranın altında yukarı doğru hızlıca kaydırın"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Çubuğu görüntülemek için ekranın altından hızlıca kaydırın"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Sistem çubuğunu görüntülemek için ekranın sağından hızlıca kaydırın"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f862365..a9b0fe7 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Сповіщення з’являються тут"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Отримуйте до них доступ будь-коли, провівши пальцем униз."\n"Знову проведіть униз, щоб відкрити елементи керування системи."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Проведіть пальцем угору від низу екрана, щоб з’явився системний рядок"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Проведіть від низу екрана, щоб з’явився рядок"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Проведіть пальцем справа наліво на екрані, щоб з’явився системний рядок"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d5a64b0..38f6036 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Vuốt lên từ cuối màn hình để hiển thị thanh hệ thống"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Vuốt cuối màn hình để hiển thị thanh"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Vuốt từ bên phải màn hình để hiển thị thanh hệ thống"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3d2f2e1..18814c7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -40,7 +40,7 @@
<string name="invalid_charger" msgid="4549105996740522523">"不支持 USB 充电功能。"\n"只能使用随附的充电器充电。"</string>
<string name="battery_low_why" msgid="7279169609518386372">"电量使用情况"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
- <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
<string name="status_bar_settings_airplane" msgid="4879879698500955300">"飞行模式"</string>
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自动旋转屏幕"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"静音"</string>
@@ -100,12 +100,12 @@
<string name="accessibility_data_two_bars" msgid="6166018492360432091">"数据信号强度为两格。"</string>
<string name="accessibility_data_three_bars" msgid="9167670452395038520">"数据信号强度为三格。"</string>
<string name="accessibility_data_signal_full" msgid="2708384608124519369">"数据信号满格。"</string>
- <string name="accessibility_wifi_off" msgid="3177380296697933627">"已关闭 Wi-Fi。"</string>
- <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi 连接已断开。"</string>
- <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi 信号强度为一格。"</string>
- <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi 信号强度为两格。"</string>
- <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi 信号强度为三格。"</string>
- <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi 信号满格。"</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"已关闭 WLAN。"</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"WLAN 连接已断开。"</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WLAN 信号强度为一格。"</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WLAN 信号强度为两格。"</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WLAN 信号强度为三格。"</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"WLAN 信号满格。"</string>
<string name="accessibility_no_wimax" msgid="4329180129727630368">"无 WiMAX 信号。"</string>
<string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX 信号强度为一格。"</string>
<string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX 信号强度为两格。"</string>
@@ -130,7 +130,7 @@
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫游中"</string>
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
- <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
<string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"蓝牙共享网络。"</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"飞行模式。"</string>
@@ -164,7 +164,7 @@
<string name="data_usage_disabled_dialog" msgid="3853117269051806280">"您已达到指定的数据流量上限。"\n\n"如果您重新启用数据,运营商可能会收取相应的费用。"</string>
<string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"重新启用数据连接"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"未连接互联网"</string>
- <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已连接"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN 已连接"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索 GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
@@ -195,14 +195,17 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"设置"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"时间"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
- <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"WLAN"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未连接"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"无网络"</string>
- <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 已关闭"</string>
- <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi 显示"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN 已关闭"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WLAN 显示"</string>
<string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"无线显示"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"通知会显示在这里"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"向下滑动可随时查看通知。"\n"再次向下滑动可使用系统控制功能。"</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"从屏幕底部向上滑动即可显示系统栏"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"从底部向上滑可显示系统栏"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"从屏幕右侧向左滑动即可显示系统栏"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d7ecc3f..af3e469 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -205,4 +205,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。"\n"再次向下滑動即可使用系統控制項。"</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"從螢幕底部向上滑動即可顯示系統列"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"從螢幕底部滑動即可顯示系統列"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"從螢幕右側滑動即可顯示系統列"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index fc3c625..af790a3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -203,4 +203,7 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Izaziso zivela lapha"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Kufinyelele noma kunini ngokuswayiphela phansi."\n"Swayiphela phansi futhi ngezilawuli zesistimu."</string>
+ <string name="hideybar_confirmation_message_bottom" msgid="4678097945183429216">"Swayipha kusukela ngaphansi kwesikrini ukuze uveze ibha yesistimu"</string>
+ <string name="hideybar_confirmation_message_bottom_short" msgid="4014207345313478943">"Swayipha ngaphansi kwesikrini ukuze uveze ibha"</string>
+ <string name="hideybar_confirmation_message_right" msgid="5359586491708388067">"Swayipha kusukela ngakwesokudla ukuze uveze ibha yesistimu"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java b/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
deleted file mode 100644
index 735ee25..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
+++ /dev/null
@@ -1,60 +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.systemui.statusbar;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.CompoundButton;
-
-import com.android.systemui.statusbar.policy.AutoRotateController;
-
-public class RotationToggle extends CompoundButton
- implements AutoRotateController.RotationLockCallbacks {
- private AutoRotateController mRotater;
-
- public RotationToggle(Context context) {
- super(context);
- }
-
- public RotationToggle(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public RotationToggle(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mRotater = new AutoRotateController(getContext(), this, this);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (mRotater != null) {
- mRotater.release();
- mRotater = null;
- }
- }
-
- @Override
- public void setRotationLockControlVisibility(boolean show) {
- setVisibility(show ? VISIBLE : GONE);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 6b30b2c..978b36b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -88,6 +88,7 @@
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DateView;
@@ -161,6 +162,7 @@
BatteryController mBatteryController;
LocationController mLocationController;
NetworkController mNetworkController;
+ RotationLockController mRotationLockController;
int mNaturalBarHeight = -1;
int mIconSize = -1;
@@ -537,6 +539,7 @@
mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery));
mNetworkController = new NetworkController(mContext);
mBluetoothController = new BluetoothController(mContext);
+ mRotationLockController = new RotationLockController(mContext);
final SignalClusterView signalCluster =
(SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
@@ -629,7 +632,7 @@
mQS.setService(this);
mQS.setBar(mStatusBarView);
mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
- mLocationController);
+ mLocationController, mRotationLockController);
} else {
mQS = null; // fly away, be free
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 85bcd8b..b20a8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import com.android.internal.view.RotationPolicy;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
@@ -28,6 +27,7 @@
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RotationLockController;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
@@ -73,7 +73,6 @@
import java.util.ArrayList;
-
/**
*
*/
@@ -97,6 +96,7 @@
private WifiManager mWifiManager;
private BluetoothController mBluetoothController;
+ private RotationLockController mRotationLockController;
private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
@@ -113,14 +113,6 @@
private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles =
new ArrayList<QuickSettingsTileView>();
- private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
- new RotationPolicy.RotationPolicyListener() {
- @Override
- public void onChange() {
- mModel.onRotationLockChanged();
- }
- };
-
public QuickSettings(Context context, QuickSettingsContainerView container) {
mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
mContext = context;
@@ -170,8 +162,10 @@
}
void setup(NetworkController networkController, BluetoothController bluetoothController,
- BatteryController batteryController, LocationController locationController) {
+ BatteryController batteryController, LocationController locationController,
+ RotationLockController rotationLockController) {
mBluetoothController = bluetoothController;
+ mRotationLockController = rotationLockController;
setupQuickSettings();
updateWifiDisplayStatus();
@@ -181,8 +175,7 @@
bluetoothController.addStateChangedCallback(mModel);
batteryController.addStateChangedCallback(mModel);
locationController.addStateChangedCallback(mModel);
- RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
- UserHandle.USER_ALL);
+ rotationLockController.addRotationLockControllerCallback(mModel);
}
private void queryForUserInformation() {
@@ -471,13 +464,29 @@
= new QuickSettingsBasicTile(mContext);
rotationLockTile.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v) {
- boolean locked = RotationPolicy.isRotationLocked(mContext);
- RotationPolicy.setRotationLock(mContext, !locked);
+ public void onClick(View view) {
+ final boolean locked = mRotationLockController.isRotationLocked();
+ mRotationLockController.setRotationLocked(!locked);
}
});
- mModel.addRotationLockTile(rotationLockTile,
- new QuickSettingsModel.BasicRefreshCallback(rotationLockTile));
+ mModel.addRotationLockTile(rotationLockTile, mRotationLockController,
+ new QuickSettingsModel.RefreshCallback() {
+ @Override
+ public void refreshView(QuickSettingsTileView view, State state) {
+ QuickSettingsModel.RotationLockState rotationLockState =
+ (QuickSettingsModel.RotationLockState) state;
+ view.setVisibility(rotationLockState.visible
+ ? View.VISIBLE : View.GONE);
+ if (state.iconId != 0) {
+ // needed to flush any cached IDs
+ rotationLockTile.setImageDrawable(null);
+ rotationLockTile.setImageResource(state.iconId);
+ }
+ if (state.label != null) {
+ rotationLockTile.setText(state.label);
+ }
+ }
+ });
parent.addView(rotationLockTile);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 38c46c4..cdfd52e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -39,22 +39,23 @@
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
-import com.android.internal.view.RotationPolicy;
import com.android.systemui.R;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.settings.BrightnessController.BrightnessStateChangeCallback;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
import java.util.List;
-
class QuickSettingsModel implements BluetoothStateChangeCallback,
NetworkSignalChangedCallback,
BatteryStateChangeCallback,
LocationGpsStateChangeCallback,
- BrightnessStateChangeCallback {
+ BrightnessStateChangeCallback,
+ RotationLockControllerCallback {
// Sett InputMethoManagerService
private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
@@ -89,6 +90,9 @@
boolean connected = false;
String stateContentDescription;
}
+ public static class RotationLockState extends State {
+ boolean visible = false;
+ }
/** The callback to update a given tile. */
interface RefreshCallback {
@@ -245,7 +249,7 @@
private QuickSettingsTileView mRotationLockTile;
private RefreshCallback mRotationLockCallback;
- private State mRotationLockState = new State();
+ private RotationLockState mRotationLockState = new RotationLockState();
private QuickSettingsTileView mBrightnessTile;
private RefreshCallback mBrightnessCallback;
@@ -259,6 +263,8 @@
private RefreshCallback mSettingsCallback;
private State mSettingsState = new State();
+ private RotationLockController mRotationLockController;
+
public QuickSettingsModel(Context context) {
mContext = context;
mHandler = new Handler();
@@ -681,25 +687,29 @@
}
// Rotation lock
- void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) {
+ void addRotationLockTile(QuickSettingsTileView view,
+ RotationLockController rotationLockController,
+ RefreshCallback cb) {
mRotationLockTile = view;
mRotationLockCallback = cb;
+ mRotationLockController = rotationLockController;
onRotationLockChanged();
}
void onRotationLockChanged() {
- boolean locked = RotationPolicy.isRotationLocked(mContext);
- mRotationLockState.enabled = locked;
- mRotationLockState.iconId = locked
+ onRotationLockStateChanged(mRotationLockController.isRotationLocked(),
+ mRotationLockController.isRotationLockAffordanceVisible());
+ }
+ @Override
+ public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
+ mRotationLockState.visible = affordanceVisible;
+ mRotationLockState.enabled = rotationLocked;
+ mRotationLockState.iconId = rotationLocked
? R.drawable.ic_qs_rotation_locked
: R.drawable.ic_qs_auto_rotate;
- mRotationLockState.label = locked
+ mRotationLockState.label = rotationLocked
? mContext.getString(R.string.quick_settings_rotation_locked_label)
: mContext.getString(R.string.quick_settings_rotation_unlocked_label);
-
- // may be called before addRotationLockTile due to RotationPolicyListener in QuickSettings
- if (mRotationLockTile != null && mRotationLockCallback != null) {
- mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
- }
+ mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
}
void refreshRotationLockTile() {
if (mRotationLockTile != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
index 33335631..1897589 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -38,6 +38,7 @@
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RotationLockController;
public class SettingsPanelView extends PanelView {
public static final boolean DEBUG_GESTURES = true;
@@ -85,10 +86,11 @@
}
public void setup(NetworkController networkController, BluetoothController bluetoothController,
- BatteryController batteryController, LocationController locationController) {
+ BatteryController batteryController, LocationController locationController,
+ RotationLockController rotationLockController) {
if (mQS != null) {
mQS.setup(networkController, bluetoothController, batteryController,
- locationController);
+ locationController, rotationLockController);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
deleted file mode 100644
index 7d58032..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import com.android.internal.view.RotationPolicy;
-
-import android.content.Context;
-import android.os.UserHandle;
-import android.widget.CompoundButton;
-
-public final class AutoRotateController implements CompoundButton.OnCheckedChangeListener {
- private final Context mContext;
- private final CompoundButton mCheckbox;
- private final RotationLockCallbacks mCallbacks;
-
- private boolean mAutoRotation;
-
- private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
- new RotationPolicy.RotationPolicyListener() {
- @Override
- public void onChange() {
- updateState();
- }
- };
-
- public AutoRotateController(Context context, CompoundButton checkbox,
- RotationLockCallbacks callbacks) {
- mContext = context;
- mCheckbox = checkbox;
- mCallbacks = callbacks;
-
- mCheckbox.setOnCheckedChangeListener(this);
-
- RotationPolicy.registerRotationPolicyListener(context, mRotationPolicyListener,
- UserHandle.USER_ALL);
- updateState();
- }
-
- public void onCheckedChanged(CompoundButton view, boolean checked) {
- if (checked != mAutoRotation) {
- mAutoRotation = checked;
- RotationPolicy.setRotationLock(mContext, !checked);
- }
- }
-
- public void release() {
- RotationPolicy.unregisterRotationPolicyListener(mContext,
- mRotationPolicyListener);
- }
-
- private void updateState() {
- mAutoRotation = !RotationPolicy.isRotationLocked(mContext);
- mCheckbox.setChecked(mAutoRotation);
-
- boolean visible = RotationPolicy.isRotationLockToggleVisible(mContext);
- mCallbacks.setRotationLockControlVisibility(visible);
- mCheckbox.setEnabled(visible);
- }
-
- public interface RotationLockCallbacks {
- void setRotationLockControlVisibility(boolean show);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
new file mode 100644
index 0000000..6f61ec8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.os.UserHandle;
+
+import com.android.internal.view.RotationPolicy;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public final class RotationLockController {
+ private final Context mContext;
+ private final CopyOnWriteArrayList<RotationLockControllerCallback> mCallbacks =
+ new CopyOnWriteArrayList<RotationLockControllerCallback>();
+
+ private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
+ new RotationPolicy.RotationPolicyListener() {
+ @Override
+ public void onChange() {
+ notifyChanged();
+ }
+ };
+
+ public interface RotationLockControllerCallback {
+ public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible);
+ }
+
+ public RotationLockController(Context context) {
+ mContext = context;
+ notifyChanged();
+ if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+ RotationPolicy.registerRotationPolicyListener(mContext,
+ mRotationPolicyListener, UserHandle.USER_ALL);
+ }
+ }
+
+ public void addRotationLockControllerCallback(RotationLockControllerCallback callback) {
+ mCallbacks.add(callback);
+ }
+
+ public boolean isRotationLocked() {
+ if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+ return RotationPolicy.isRotationLocked(mContext);
+ }
+ return false;
+ }
+
+ public void setRotationLocked(boolean locked) {
+ if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+ RotationPolicy.setRotationLock(mContext, locked);
+ }
+ }
+
+ public boolean isRotationLockAffordanceVisible() {
+ if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+ return RotationPolicy.isRotationLockToggleVisible(mContext);
+ }
+ return false;
+ }
+
+ public void release() {
+ if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
+ RotationPolicy.unregisterRotationPolicyListener(mContext,
+ mRotationPolicyListener);
+ }
+ }
+
+ private void notifyChanged() {
+ for (RotationLockControllerCallback callback : mCallbacks) {
+ callback.onRotationLockStateChanged(RotationPolicy.isRotationLocked(mContext),
+ RotationPolicy.isRotationLockToggleVisible(mContext));
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index e0dcbcd..a55cc9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -22,26 +22,23 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.LinearLayout;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
-import android.widget.TextView;
+import android.widget.LinearLayout;
import com.android.systemui.R;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSlider;
import com.android.systemui.statusbar.policy.AirplaneModeController;
-import com.android.systemui.statusbar.policy.AutoRotateController;
import com.android.systemui.statusbar.policy.DoNotDisturbController;
-import com.android.systemui.statusbar.policy.VolumeController;
+import com.android.systemui.statusbar.policy.RotationLockController;
public class SettingsView extends LinearLayout implements View.OnClickListener {
static final String TAG = "SettingsView";
AirplaneModeController mAirplane;
- AutoRotateController mRotate;
+ RotationLockController mRotationController;
BrightnessController mBrightness;
DoNotDisturbController mDoNotDisturb;
View mRotationLockContainer;
@@ -67,15 +64,25 @@
mRotationLockContainer = findViewById(R.id.rotate);
mRotationLockSeparator = findViewById(R.id.rotate_separator);
- mRotate = new AutoRotateController(context,
- (CompoundButton)findViewById(R.id.rotate_checkbox),
- new AutoRotateController.RotationLockCallbacks() {
+ mRotationController = new RotationLockController(context);
+ mRotationController.addRotationLockControllerCallback(
+ new RotationLockController.RotationLockControllerCallback() {
@Override
- public void setRotationLockControlVisibility(boolean show) {
- mRotationLockContainer.setVisibility(show ? View.VISIBLE : View.GONE);
- mRotationLockSeparator.setVisibility(show ? View.VISIBLE : View.GONE);
+ public void onRotationLockStateChanged(boolean locked, boolean visible) {
+ mRotationLockContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
+ mRotationLockSeparator.setVisibility(visible ? View.VISIBLE : View.GONE);
}
});
+ CompoundButton rotateCheckbox = (CompoundButton) findViewById(R.id.rotate_checkbox);
+ rotateCheckbox.setChecked(!mRotationController.isRotationLocked());
+ rotateCheckbox.setVisibility(mRotationController.isRotationLockAffordanceVisible()
+ ? View.VISIBLE : View.GONE);
+ rotateCheckbox.setOnCheckedChangeListener(new CompoundButton. OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mRotationController.setRotationLocked(!buttonView.isChecked());
+ }
+ });
mBrightness = new BrightnessController(context,
(ImageView)findViewById(R.id.brightness_icon),
@@ -90,7 +97,7 @@
super.onDetachedFromWindow();
mAirplane.release();
mDoNotDisturb.release();
- mRotate.release();
+ mRotationController.release();
}
public void onClick(View v) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 6b28e8e..085134d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -139,6 +139,12 @@
private ActionMenuPresenterCallback mActionMenuPresenterCallback;
private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
+ static final int FLAG_RESOURCE_SET_ICON = 1 << 0;
+ static final int FLAG_RESOURCE_SET_LOGO = 1 << 1;
+ int mResourcesSetFlags;
+ int mIconRes;
+ int mLogoRes;
+
private DrawableFeatureState[] mDrawables;
private PanelFeatureState[] mPanels;
@@ -1393,6 +1399,46 @@
}
}
+ @Override
+ public void setIcon(int resId) {
+ mIconRes = resId;
+ mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON;
+ if (mActionBar != null) {
+ mActionBar.setIcon(resId);
+ }
+ }
+
+ @Override
+ public void setDefaultIcon(int resId) {
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0) {
+ return;
+ }
+ mIconRes = resId;
+ if (mActionBar != null && !mActionBar.hasIcon()) {
+ mActionBar.setIcon(resId);
+ }
+ }
+
+ @Override
+ public void setLogo(int resId) {
+ mLogoRes = resId;
+ mResourcesSetFlags |= FLAG_RESOURCE_SET_LOGO;
+ if (mActionBar != null) {
+ mActionBar.setLogo(resId);
+ }
+ }
+
+ @Override
+ public void setDefaultLogo(int resId) {
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0) {
+ return;
+ }
+ mLogoRes = resId;
+ if (mActionBar != null && !mActionBar.hasLogo()) {
+ mActionBar.setLogo(resId);
+ }
+ }
+
/**
* Request that key events come to this activity. Use this if your activity
* has no views with focus, but the activity still wants a chance to process
@@ -2946,6 +2992,15 @@
"incompatible window decor! Ignoring request.");
}
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
+ (mIconRes != 0 && !mActionBar.hasIcon())) {
+ mActionBar.setIcon(mIconRes);
+ }
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
+ (mLogoRes != 0 && !mActionBar.hasLogo())) {
+ mActionBar.setLogo(mLogoRes);
+ }
+
// Post the panel invalidate for later; avoid application onCreateOptionsMenu
// being called in the middle of onCreate or similar.
mDecor.post(new Runnable() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 79753a6..b8a9797 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1582,7 +1582,7 @@
@Override
public View addStartingWindow(IBinder appToken, String packageName, int theme,
CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int windowFlags) {
+ int icon, int logo, int windowFlags) {
if (!SHOW_STARTING_ANIMATIONS) {
return null;
}
@@ -1639,6 +1639,9 @@
win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
}
+ win.setDefaultIcon(icon);
+ win.setDefaultLogo(logo);
+
win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index fa758a8..bc06561 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -351,12 +351,11 @@
}
// iterator over the list removing any it where the intent match
- Iterator<Alarm> it = alarmList.iterator();
-
- while (it.hasNext()) {
- Alarm alarm = it.next();
+ for (int i=0; i<alarmList.size(); i++) {
+ Alarm alarm = alarmList.get(i);
if (alarm.operation.equals(operation)) {
- it.remove();
+ alarmList.remove(i);
+ i--;
}
}
}
@@ -375,12 +374,11 @@
}
// iterator over the list removing any it where the intent match
- Iterator<Alarm> it = alarmList.iterator();
-
- while (it.hasNext()) {
- Alarm alarm = it.next();
+ for (int i=0; i<alarmList.size(); i++) {
+ Alarm alarm = alarmList.get(i);
if (alarm.operation.getTargetPackage().equals(packageName)) {
- it.remove();
+ alarmList.remove(i);
+ i--;
}
}
}
@@ -398,12 +396,11 @@
}
// iterator over the list removing any it where the intent match
- Iterator<Alarm> it = alarmList.iterator();
-
- while (it.hasNext()) {
- Alarm alarm = it.next();
+ for (int i=0; i<alarmList.size(); i++) {
+ Alarm alarm = alarmList.get(i);
if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
- it.remove();
+ alarmList.remove(i);
+ i--;
}
}
}
@@ -666,12 +663,10 @@
ArrayList<Alarm> triggerList,
long now)
{
- Iterator<Alarm> it = alarmList.iterator();
- ArrayList<Alarm> repeats = new ArrayList<Alarm>();
-
- while (it.hasNext())
- {
- Alarm alarm = it.next();
+ ArrayList<Alarm> repeats = null;
+
+ for (int i=0; i<alarmList.size(); i++) {
+ Alarm alarm = alarmList.get(i);
if (localLOGV) Slog.v(TAG, "Checking active alarm when=" + alarm.when + " " + alarm);
@@ -702,20 +697,25 @@
triggerList.add(alarm);
// remove the alarm from the list
- it.remove();
-
+ alarmList.remove(i);
+ i--;
+
// if it repeats queue it up to be read-added to the list
if (alarm.repeatInterval > 0) {
+ if (repeats == null) {
+ repeats = new ArrayList<Alarm>();
+ }
repeats.add(alarm);
}
}
// reset any repeating alarms.
- it = repeats.iterator();
- while (it.hasNext()) {
- Alarm alarm = it.next();
- alarm.when += alarm.count * alarm.repeatInterval;
- addAlarmLocked(alarm);
+ if (repeats != null) {
+ for (int i=0; i<repeats.size(); i++) {
+ Alarm alarm = repeats.get(i);
+ alarm.when += alarm.count * alarm.repeatInterval;
+ addAlarmLocked(alarm);
+ }
}
if (alarmList.size() > 0) {
@@ -785,12 +785,14 @@
public void run()
{
+ ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
+
while (true)
{
int result = waitForAlarm(mDescriptor);
-
- ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
-
+
+ triggerList.clear();
+
if ((result & TIME_CHANGED_MASK) != 0) {
remove(mTimeTickSender);
mClockReceiver.scheduleTimeTickEvent();
@@ -820,9 +822,8 @@
triggerAlarmsLocked(mElapsedRealtimeAlarms, triggerList, nowELAPSED);
// now trigger the alarms
- Iterator<Alarm> it = triggerList.iterator();
- while (it.hasNext()) {
- Alarm alarm = it.next();
+ for (int i=0; i<triggerList.size(); i++) {
+ Alarm alarm = triggerList.get(i);
try {
if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
alarm.operation.send(mContext, 0,
@@ -913,10 +914,8 @@
}
// now trigger the alarms without the lock held
- Iterator<Alarm> it = triggerList.iterator();
- while (it.hasNext())
- {
- Alarm alarm = it.next();
+ for (int i=0; i<triggerList.size(); i++) {
+ Alarm alarm = triggerList.get(i);
try {
alarm.operation.send();
} catch (PendingIntent.CanceledException e) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 016a664..0bf3a11 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -135,8 +135,8 @@
// --- fields below are final after systemReady() ---
private LocationFudger mLocationFudger;
private GeofenceManager mGeofenceManager;
- private PowerManager.WakeLock mWakeLock;
private PackageManager mPackageManager;
+ private PowerManager mPowerManager;
private GeocoderProxy mGeocodeProvider;
private IGpsStatusProvider mGpsStatusProvider;
private INetInitiatedListener mNetInitiatedListener;
@@ -144,9 +144,6 @@
private PassiveProvider mPassiveProvider; // track passive provider for special cases
private LocationBlacklist mBlacklist;
- // --- fields below are protected by mWakeLock ---
- private int mPendingBroadcasts;
-
// --- fields below are protected by mLock ---
// Set of providers that are explicitly enabled
private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -209,10 +206,8 @@
// fetch package manager
mPackageManager = mContext.getPackageManager();
- // prepare wake lock
- PowerManager powerManager =
- (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+ // fetch power manager
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
// prepare worker thread
mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
@@ -466,6 +461,7 @@
final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
int mPendingBroadcasts;
+ PowerManager.WakeLock mWakeLock;
Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
String packageName) {
@@ -480,6 +476,10 @@
mUid = uid;
mPid = pid;
mPackageName = packageName;
+
+ // construct/configure wakelock
+ mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+ mWakeLock.setWorkSource(new WorkSource(mUid, mPackageName));
}
@Override
@@ -642,10 +642,7 @@
removeUpdatesLocked(this);
}
synchronized (this) {
- if (mPendingBroadcasts > 0) {
- LocationManagerService.this.decrementPendingBroadcasts();
- mPendingBroadcasts = 0;
- }
+ clearPendingBroadcastsLocked();
}
}
@@ -661,13 +658,24 @@
// containing the sending of the broadcaset
private void incrementPendingBroadcastsLocked() {
if (mPendingBroadcasts++ == 0) {
- LocationManagerService.this.incrementPendingBroadcasts();
+ mWakeLock.acquire();
}
}
private void decrementPendingBroadcastsLocked() {
if (--mPendingBroadcasts == 0) {
- LocationManagerService.this.decrementPendingBroadcasts();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+ }
+
+ public void clearPendingBroadcastsLocked() {
+ if (mPendingBroadcasts > 0) {
+ mPendingBroadcasts = 0;
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
}
}
}
@@ -1349,10 +1357,7 @@
if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
synchronized (receiver) {
- if (receiver.mPendingBroadcasts > 0) {
- decrementPendingBroadcasts();
- receiver.mPendingBroadcasts = 0;
- }
+ receiver.clearPendingBroadcastsLocked();
}
}
@@ -1954,43 +1959,6 @@
}
};
- // Wake locks
-
- private void incrementPendingBroadcasts() {
- synchronized (mWakeLock) {
- if (mPendingBroadcasts++ == 0) {
- try {
- mWakeLock.acquire();
- log("Acquired wakelock");
- } catch (Exception e) {
- // This is to catch a runtime exception thrown when we try to release an
- // already released lock.
- Slog.e(TAG, "exception in acquireWakeLock()", e);
- }
- }
- }
- }
-
- private void decrementPendingBroadcasts() {
- synchronized (mWakeLock) {
- if (--mPendingBroadcasts == 0) {
- try {
- // Release wake lock
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- log("Released wakelock");
- } else {
- log("Can't release wakelock again!");
- }
- } catch (Exception e) {
- // This is to catch a runtime exception thrown when we try to release an
- // already released lock.
- Slog.e(TAG, "exception in releaseWakeLock()", e);
- }
- }
- }
- }
-
// Geocoder
@Override
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 10db70f..84e44bd 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -574,30 +574,26 @@
b.binder = service;
b.requested = true;
b.received = true;
- if (r.connections.size() > 0) {
- Iterator<ArrayList<ConnectionRecord>> it
- = r.connections.values().iterator();
- while (it.hasNext()) {
- ArrayList<ConnectionRecord> clist = it.next();
- for (int i=0; i<clist.size(); i++) {
- ConnectionRecord c = clist.get(i);
- if (!filter.equals(c.binding.intent.intent)) {
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Not publishing to: " + c);
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Bound intent: " + c.binding.intent.intent);
- if (DEBUG_SERVICE) Slog.v(
- TAG, "Published intent: " + intent);
- continue;
- }
- if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
- try {
- c.conn.connected(r.name, service);
- } catch (Exception e) {
- Slog.w(TAG, "Failure sending service " + r.name +
- " to connection " + c.conn.asBinder() +
- " (in " + c.binding.client.processName + ")", e);
- }
+ for (int conni=r.connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
+ for (int i=0; i<clist.size(); i++) {
+ ConnectionRecord c = clist.get(i);
+ if (!filter.equals(c.binding.intent.intent)) {
+ if (DEBUG_SERVICE) Slog.v(
+ TAG, "Not publishing to: " + c);
+ if (DEBUG_SERVICE) Slog.v(
+ TAG, "Bound intent: " + c.binding.intent.intent);
+ if (DEBUG_SERVICE) Slog.v(
+ TAG, "Published intent: " + intent);
+ continue;
+ }
+ if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+ try {
+ c.conn.connected(r.name, service);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failure sending service " + r.name +
+ " to connection " + c.conn.asBinder() +
+ " (in " + c.binding.client.processName + ")", e);
}
}
}
@@ -1064,10 +1060,9 @@
}
private final void requestServiceBindingsLocked(ServiceRecord r) {
- Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
- while (bindings.hasNext()) {
- IntentBindRecord i = bindings.next();
- if (!requestServiceBindingLocked(r, i, false)) {
+ for (int i=r.bindings.size()-1; i>=0; i--) {
+ IntentBindRecord ibr = r.bindings.valueAt(i);
+ if (!requestServiceBindingLocked(r, ibr, false)) {
break;
}
}
@@ -1179,50 +1174,45 @@
if (!force && r.startRequested) {
return;
}
- if (r.connections.size() > 0) {
- if (!force) {
- // XXX should probably keep a count of the number of auto-create
- // connections directly in the service.
- Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
- while (it.hasNext()) {
- ArrayList<ConnectionRecord> cr = it.next();
- for (int i=0; i<cr.size(); i++) {
- if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
- return;
- }
- }
- }
- }
-
- // Report to all of the connections that the service is no longer
- // available.
- Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
- while (it.hasNext()) {
- ArrayList<ConnectionRecord> c = it.next();
- for (int i=0; i<c.size(); i++) {
- ConnectionRecord cr = c.get(i);
- // There is still a connection to the service that is
- // being brought down. Mark it as dead.
- cr.serviceDead = true;
- try {
- cr.conn.connected(r.name, null);
- } catch (Exception e) {
- Slog.w(TAG, "Failure disconnecting service " + r.name +
- " to connection " + c.get(i).conn.asBinder() +
- " (in " + c.get(i).binding.client.processName + ")", e);
+ if (!force) {
+ // XXX should probably keep a count of the number of auto-create
+ // connections directly in the service.
+ for (int conni=r.connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> cr = r.connections.valueAt(conni);
+ for (int i=0; i<cr.size(); i++) {
+ if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+ return;
}
}
}
}
+ // Report to all of the connections that the service is no longer
+ // available.
+ for (int conni=r.connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
+ for (int i=0; i<c.size(); i++) {
+ ConnectionRecord cr = c.get(i);
+ // There is still a connection to the service that is
+ // being brought down. Mark it as dead.
+ cr.serviceDead = true;
+ try {
+ cr.conn.connected(r.name, null);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failure disconnecting service " + r.name +
+ " to connection " + c.get(i).conn.asBinder() +
+ " (in " + c.get(i).binding.client.processName + ")", e);
+ }
+ }
+ }
+
// Tell the service that it has been unbound.
- if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
- Iterator<IntentBindRecord> it = r.bindings.values().iterator();
- while (it.hasNext()) {
- IntentBindRecord ibr = it.next();
+ if (r.app != null && r.app.thread != null) {
+ for (int i=r.bindings.size()-1; i>=0; i--) {
+ IntentBindRecord ibr = r.bindings.valueAt(i);
if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
+ ": hasBound=" + ibr.hasBound);
- if (r.app != null && r.app.thread != null && ibr.hasBound) {
+ if (ibr.hasBound) {
try {
bumpServiceExecutingLocked(r, "bring down unbind");
mAm.updateOomAdjLocked(r.app);
@@ -1595,22 +1585,18 @@
Iterator<ServiceRecord> it = app.services.iterator();
while (it.hasNext()) {
ServiceRecord r = it.next();
- if (r.connections.size() > 0) {
- Iterator<ArrayList<ConnectionRecord>> jt
- = r.connections.values().iterator();
- while (jt.hasNext()) {
- ArrayList<ConnectionRecord> cl = jt.next();
- for (int i=0; i<cl.size(); i++) {
- ConnectionRecord c = cl.get(i);
- if (c.binding.client != app) {
- try {
- //c.conn.connected(r.className, null);
- } catch (Exception e) {
- // todo: this should be asynchronous!
- Slog.w(TAG, "Exception thrown disconnected servce "
- + r.shortName
- + " from app " + app.processName, e);
- }
+ for (int conni=r.connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
+ for (int i=0; i<cl.size(); i++) {
+ ConnectionRecord c = cl.get(i);
+ if (c.binding.client != app) {
+ try {
+ //c.conn.connected(r.className, null);
+ } catch (Exception e) {
+ // todo: this should be asynchronous!
+ Slog.w(TAG, "Exception thrown disconnected servce "
+ + r.shortName
+ + " from app " + app.processName, e);
}
}
}
@@ -1645,17 +1631,13 @@
if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
}
- boolean hasClients = sr.bindings.size() > 0;
- if (hasClients) {
- Iterator<IntentBindRecord> bindings
- = sr.bindings.values().iterator();
- while (bindings.hasNext()) {
- IntentBindRecord b = bindings.next();
- if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
- + ": shouldUnbind=" + b.hasBound);
- b.binder = null;
- b.requested = b.received = b.hasBound = false;
- }
+ final int numClients = sr.bindings.size();
+ for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
+ IntentBindRecord b = sr.bindings.valueAt(bindingi);
+ if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
+ + ": shouldUnbind=" + b.hasBound);
+ b.binder = null;
+ b.requested = b.received = b.hasBound = false;
}
if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
@@ -1676,7 +1658,7 @@
if (sr.startRequested && (sr.stopIfKilled || canceled)) {
if (sr.pendingStarts.size() == 0) {
sr.startRequested = false;
- if (!hasClients) {
+ if (numClients > 0) {
// Whoops, no reason to restart!
bringDownServiceLocked(sr, true);
}
@@ -1732,7 +1714,8 @@
info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
}
- for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+ for (int conni=r.connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> connl = r.connections.valueAt(conni);
for (int i=0; i<connl.size(); i++) {
ConnectionRecord conn = connl.get(i);
if (conn.clientLabel != 0) {
@@ -1805,7 +1788,8 @@
int userId = UserHandle.getUserId(Binder.getCallingUid());
ServiceRecord r = mServiceMap.getServiceByName(name, userId);
if (r != null) {
- for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+ for (int conni=r.connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
for (int i=0; i<conn.size(); i++) {
if (conn.get(i).clientIntent != null) {
return conn.get(i).clientIntent;
@@ -1859,6 +1843,7 @@
boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
boolean needSep = false;
+ boolean needSepResult = false;
ItemMatcher matcher = new ItemMatcher();
matcher.build(args, opti);
@@ -1881,6 +1866,7 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
+ needSepResult = true;
if (!printed) {
if (user != 0) {
pw.println();
@@ -1907,7 +1893,8 @@
pw.println(r.connections.size());
if (r.connections.size() > 0) {
pw.println(" Connections:");
- for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+ for (int conni=0; conni<=r.connections.size(); conni++) {
+ ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord conn = clist.get(i);
pw.print(" ");
@@ -1960,6 +1947,7 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
+ needSepResult = true;
if (!printed) {
if (needSep) pw.println(" ");
needSep = true;
@@ -1982,6 +1970,7 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
+ needSepResult = true;
if (!printed) {
if (needSep) pw.println(" ");
needSep = true;
@@ -2004,6 +1993,7 @@
if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
continue;
}
+ needSepResult = true;
if (!printed) {
if (needSep) pw.println(" ");
needSep = true;
@@ -2032,6 +2022,7 @@
|| !dumpPackage.equals(cr.binding.client.info.packageName))) {
continue;
}
+ needSepResult = true;
if (!printed) {
if (needSep) pw.println(" ");
needSep = true;
@@ -2042,11 +2033,10 @@
cr.dump(pw, " ");
}
}
- needSep = true;
}
}
- return needSep;
+ return needSepResult;
}
/**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index ed6dcce..8d71cf9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6515,6 +6515,7 @@
int userId = app.userId;
if (providers != null) {
int N = providers.size();
+ app.pubProviders.ensureCapacity(N + app.pubProviders.size());
for (int i=0; i<N; i++) {
ProviderInfo cpi =
(ProviderInfo)providers.get(i);
@@ -6527,6 +6528,7 @@
// it runs in the process of the default user. Get rid of it.
providers.remove(i);
N--;
+ i--;
continue;
}
@@ -10098,6 +10100,7 @@
boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
+ boolean dumpedHeader = false;
boolean needSep = false;
boolean onlyHistory = false;
@@ -10193,14 +10196,14 @@
boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
- boolean needSep = true;
+ boolean needSep;
ItemMatcher matcher = new ItemMatcher();
matcher.build(args, opti);
pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
- mProviderMap.dumpProvidersLocked(pw, dumpAll);
+ needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
if (mLaunchingProviders.size() > 0) {
boolean printed = false;
@@ -10221,13 +10224,28 @@
}
if (mGrantedUriPermissions.size() > 0) {
- if (needSep) pw.println();
- needSep = true;
- pw.println("Granted Uri Permissions:");
+ boolean printed = false;
+ int dumpUid = -1;
+ if (dumpPackage != null) {
+ try {
+ dumpUid = mContext.getPackageManager().getPackageUid(dumpPackage, 0);
+ } catch (NameNotFoundException e) {
+ dumpUid = -1;
+ }
+ }
for (int i=0; i<mGrantedUriPermissions.size(); i++) {
int uid = mGrantedUriPermissions.keyAt(i);
+ if (dumpUid >= 0 && UserHandle.getAppId(uid) != dumpUid) {
+ continue;
+ }
HashMap<Uri, UriPermission> perms
= mGrantedUriPermissions.valueAt(i);
+ if (!printed) {
+ if (needSep) pw.println();
+ needSep = true;
+ pw.println(" Granted Uri Permissions:");
+ printed = true;
+ }
pw.print(" * UID "); pw.print(uid);
pw.println(" holds:");
for (UriPermission perm : perms.values()) {
@@ -10237,7 +10255,6 @@
}
}
}
- needSep = true;
}
return needSep;
@@ -11024,24 +11041,20 @@
boolean restart = false;
// Remove published content providers.
- if (!app.pubProviders.isEmpty()) {
- Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
- while (it.hasNext()) {
- ContentProviderRecord cpr = it.next();
-
- final boolean always = app.bad || !allowRestart;
- if (removeDyingProviderLocked(app, cpr, always) || always) {
- // We left the provider in the launching list, need to
- // restart it.
- restart = true;
- }
-
- cpr.provider = null;
- cpr.proc = null;
+ for (int i=app.pubProviders.size()-1; i>=0; i--) {
+ ContentProviderRecord cpr = app.pubProviders.valueAt(i);
+ final boolean always = app.bad || !allowRestart;
+ if (removeDyingProviderLocked(app, cpr, always) || always) {
+ // We left the provider in the launching list, need to
+ // restart it.
+ restart = true;
}
- app.pubProviders.clear();
+
+ cpr.provider = null;
+ cpr.proc = null;
}
-
+ app.pubProviders.clear();
+
// Take care of any launching providers waiting for this process.
if (checkAppInLaunchingProvidersLocked(app, false)) {
restart = true;
@@ -13118,158 +13131,159 @@
// has said it is doing work.
app.keeping = true;
}
- if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
- Iterator<ArrayList<ConnectionRecord>> kt
- = s.connections.values().iterator();
- while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
- ArrayList<ConnectionRecord> clist = kt.next();
- for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
- // XXX should compute this based on the max of
- // all connected clients.
- ConnectionRecord cr = clist.get(i);
- if (cr.binding.client == app) {
- // Binding to ourself is not interesting.
- continue;
+ for (int conni = s.connections.size()-1;
+ conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+ conni--) {
+ ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
+ for (int i = 0;
+ i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
+ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+ i++) {
+ // XXX should compute this based on the max of
+ // all connected clients.
+ ConnectionRecord cr = clist.get(i);
+ if (cr.binding.client == app) {
+ // Binding to ourself is not interesting.
+ continue;
+ }
+ if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
+ ProcessRecord client = cr.binding.client;
+ int clientAdj = adj;
+ int myHiddenAdj = hiddenAdj;
+ if (myHiddenAdj > client.hiddenAdj) {
+ if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ myHiddenAdj = client.hiddenAdj;
+ } else {
+ myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
+ }
}
- if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
- ProcessRecord client = cr.binding.client;
- int clientAdj = adj;
- int myHiddenAdj = hiddenAdj;
- if (myHiddenAdj > client.hiddenAdj) {
- if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
- myHiddenAdj = client.hiddenAdj;
- } else {
- myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
- }
+ int myClientHiddenAdj = clientHiddenAdj;
+ if (myClientHiddenAdj > client.clientHiddenAdj) {
+ if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ myClientHiddenAdj = client.clientHiddenAdj;
+ } else {
+ myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
}
- int myClientHiddenAdj = clientHiddenAdj;
- if (myClientHiddenAdj > client.clientHiddenAdj) {
- if (client.clientHiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
- myClientHiddenAdj = client.clientHiddenAdj;
- } else {
- myClientHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
- }
+ }
+ int myEmptyAdj = emptyAdj;
+ if (myEmptyAdj > client.emptyAdj) {
+ if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ myEmptyAdj = client.emptyAdj;
+ } else {
+ myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
}
- int myEmptyAdj = emptyAdj;
- if (myEmptyAdj > client.emptyAdj) {
- if (client.emptyAdj >= ProcessList.VISIBLE_APP_ADJ) {
- myEmptyAdj = client.emptyAdj;
- } else {
- myEmptyAdj = ProcessList.VISIBLE_APP_ADJ;
- }
- }
- clientAdj = computeOomAdjLocked(client, myHiddenAdj,
- myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
- String adjType = null;
- if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
- // Not doing bind OOM management, so treat
- // this guy more like a started service.
- if (app.hasShownUi && app != mHomeProcess) {
- // If this process has shown some UI, let it immediately
- // go to the LRU list because it may be pretty heavy with
- // UI stuff. We'll tag it with a label just to help
- // debug and understand what is going on.
- if (adj > clientAdj) {
- adjType = "bound-bg-ui-services";
- }
- app.hidden = false;
- clientAdj = adj;
- } else {
- if (now >= (s.lastActivity
- + ActiveServices.MAX_SERVICE_INACTIVITY)) {
- // This service has not seen activity within
- // recent memory, so allow it to drop to the
- // LRU list if there is no other reason to keep
- // it around. We'll also tag it with a label just
- // to help debug and undertand what is going on.
- if (adj > clientAdj) {
- adjType = "bound-bg-services";
- }
- clientAdj = adj;
- }
- }
- } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
- if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
- // If this connection is keeping the service
- // created, then we want to try to better follow
- // its memory management semantics for activities.
- // That is, if it is sitting in the background
- // LRU list as a hidden process (with activities),
- // we don't want the service it is connected to
- // to go into the empty LRU and quickly get killed,
- // because I'll we'll do is just end up restarting
- // the service.
- app.hasClientActivities |= client.hasActivities;
- }
- }
- if (adj > clientAdj) {
- // If this process has recently shown UI, and
- // the process that is binding to it is less
- // important than being visible, then we don't
- // care about the binding as much as we care
- // about letting this process get into the LRU
- // list to be killed and restarted if needed for
- // memory.
- if (app.hasShownUi && app != mHomeProcess
- && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ }
+ clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+ myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+ String adjType = null;
+ if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+ // Not doing bind OOM management, so treat
+ // this guy more like a started service.
+ if (app.hasShownUi && app != mHomeProcess) {
+ // If this process has shown some UI, let it immediately
+ // go to the LRU list because it may be pretty heavy with
+ // UI stuff. We'll tag it with a label just to help
+ // debug and understand what is going on.
+ if (adj > clientAdj) {
adjType = "bound-bg-ui-services";
- } else {
- if ((cr.flags&(Context.BIND_ABOVE_CLIENT
- |Context.BIND_IMPORTANT)) != 0) {
- adj = clientAdj;
- } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
- && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
- && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
- adj = clientAdj;
- } else {
- app.pendingUiClean = true;
- if (adj > ProcessList.VISIBLE_APP_ADJ) {
- adj = ProcessList.VISIBLE_APP_ADJ;
- }
- }
- if (!client.hidden) {
- app.hidden = false;
- }
- if (client.keeping) {
- app.keeping = true;
- }
- adjType = "service";
- }
- }
- if (adjType != null) {
- app.adjType = adjType;
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE;
- app.adjSource = cr.binding.client;
- app.adjSourceOom = clientAdj;
- app.adjTarget = s.name;
- }
- if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
- if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
- }
- }
- }
- final ActivityRecord a = cr.activity;
- if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
- if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
- (a.visible || a.state == ActivityState.RESUMED
- || a.state == ActivityState.PAUSING)) {
- adj = ProcessList.FOREGROUND_APP_ADJ;
- if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
}
app.hidden = false;
- app.adjType = "service";
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_SERVICE_IN_USE;
- app.adjSource = a;
- app.adjSourceOom = adj;
- app.adjTarget = s.name;
+ clientAdj = adj;
+ } else {
+ if (now >= (s.lastActivity
+ + ActiveServices.MAX_SERVICE_INACTIVITY)) {
+ // This service has not seen activity within
+ // recent memory, so allow it to drop to the
+ // LRU list if there is no other reason to keep
+ // it around. We'll also tag it with a label just
+ // to help debug and undertand what is going on.
+ if (adj > clientAdj) {
+ adjType = "bound-bg-services";
+ }
+ clientAdj = adj;
+ }
}
+ } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+ if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
+ // If this connection is keeping the service
+ // created, then we want to try to better follow
+ // its memory management semantics for activities.
+ // That is, if it is sitting in the background
+ // LRU list as a hidden process (with activities),
+ // we don't want the service it is connected to
+ // to go into the empty LRU and quickly get killed,
+ // because I'll we'll do is just end up restarting
+ // the service.
+ app.hasClientActivities |= client.hasActivities;
+ }
+ }
+ if (adj > clientAdj) {
+ // If this process has recently shown UI, and
+ // the process that is binding to it is less
+ // important than being visible, then we don't
+ // care about the binding as much as we care
+ // about letting this process get into the LRU
+ // list to be killed and restarted if needed for
+ // memory.
+ if (app.hasShownUi && app != mHomeProcess
+ && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adjType = "bound-bg-ui-services";
+ } else {
+ if ((cr.flags&(Context.BIND_ABOVE_CLIENT
+ |Context.BIND_IMPORTANT)) != 0) {
+ adj = clientAdj;
+ } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
+ && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+ && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
+ adj = clientAdj;
+ } else {
+ app.pendingUiClean = true;
+ if (adj > ProcessList.VISIBLE_APP_ADJ) {
+ adj = ProcessList.VISIBLE_APP_ADJ;
+ }
+ }
+ if (!client.hidden) {
+ app.hidden = false;
+ }
+ if (client.keeping) {
+ app.keeping = true;
+ }
+ adjType = "service";
+ }
+ }
+ if (adjType != null) {
+ app.adjType = adjType;
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
+ app.adjSource = cr.binding.client;
+ app.adjSourceOom = clientAdj;
+ app.adjTarget = s.name;
+ }
+ if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+ if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ }
+ }
+ }
+ final ActivityRecord a = cr.activity;
+ if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
+ if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
+ (a.visible || a.state == ActivityState.RESUMED
+ || a.state == ActivityState.PAUSING)) {
+ adj = ProcessList.FOREGROUND_APP_ADJ;
+ if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ }
+ app.hidden = false;
+ app.adjType = "service";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
+ app.adjSource = a;
+ app.adjSourceOom = adj;
+ app.adjTarget = s.name;
}
}
}
@@ -13288,86 +13302,84 @@
}
}
- if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
- Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
- while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
- ContentProviderRecord cpr = jt.next();
- for (int i = cpr.connections.size()-1;
- i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
- i--) {
- ContentProviderConnection conn = cpr.connections.get(i);
- ProcessRecord client = conn.client;
- if (client == app) {
- // Being our own client is not interesting.
- continue;
- }
- int myHiddenAdj = hiddenAdj;
- if (myHiddenAdj > client.hiddenAdj) {
- if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
- myHiddenAdj = client.hiddenAdj;
- } else {
- myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
- }
- }
- int myClientHiddenAdj = clientHiddenAdj;
- if (myClientHiddenAdj > client.clientHiddenAdj) {
- if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
- myClientHiddenAdj = client.clientHiddenAdj;
- } else {
- myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
- }
- }
- int myEmptyAdj = emptyAdj;
- if (myEmptyAdj > client.emptyAdj) {
- if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
- myEmptyAdj = client.emptyAdj;
- } else {
- myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
- }
- }
- int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
- myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
- if (adj > clientAdj) {
- if (app.hasShownUi && app != mHomeProcess
- && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
- app.adjType = "bg-ui-provider";
- } else {
- adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
- ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
- app.adjType = "provider";
- }
- if (!client.hidden) {
- app.hidden = false;
- }
- if (client.keeping) {
- app.keeping = true;
- }
- app.adjTypeCode = ActivityManager.RunningAppProcessInfo
- .REASON_PROVIDER_IN_USE;
- app.adjSource = client;
- app.adjSourceOom = clientAdj;
- app.adjTarget = cpr.name;
- }
- if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ for (int provi = app.pubProviders.size()-1;
+ provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+ provi--) {
+ ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
+ for (int i = cpr.connections.size()-1;
+ i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
+ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE);
+ i--) {
+ ContentProviderConnection conn = cpr.connections.get(i);
+ ProcessRecord client = conn.client;
+ if (client == app) {
+ // Being our own client is not interesting.
+ continue;
+ }
+ int myHiddenAdj = hiddenAdj;
+ if (myHiddenAdj > client.hiddenAdj) {
+ if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
+ myHiddenAdj = client.hiddenAdj;
+ } else {
+ myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
}
}
- // If the provider has external (non-framework) process
- // dependencies, ensure that its adjustment is at least
- // FOREGROUND_APP_ADJ.
- if (cpr.hasExternalProcessHandles()) {
- if (adj > ProcessList.FOREGROUND_APP_ADJ) {
- adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
- app.hidden = false;
- app.keeping = true;
- app.adjType = "provider";
- app.adjTarget = cpr.name;
+ int myClientHiddenAdj = clientHiddenAdj;
+ if (myClientHiddenAdj > client.clientHiddenAdj) {
+ if (client.clientHiddenAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+ myClientHiddenAdj = client.clientHiddenAdj;
+ } else {
+ myClientHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
}
}
+ int myEmptyAdj = emptyAdj;
+ if (myEmptyAdj > client.emptyAdj) {
+ if (client.emptyAdj > ProcessList.FOREGROUND_APP_ADJ) {
+ myEmptyAdj = client.emptyAdj;
+ } else {
+ myEmptyAdj = ProcessList.FOREGROUND_APP_ADJ;
+ }
+ }
+ int clientAdj = computeOomAdjLocked(client, myHiddenAdj,
+ myClientHiddenAdj, myEmptyAdj, TOP_APP, true, doingAll);
+ if (adj > clientAdj) {
+ if (app.hasShownUi && app != mHomeProcess
+ && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ app.adjType = "bg-ui-provider";
+ } else {
+ adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
+ ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
+ app.adjType = "provider";
+ }
+ if (!client.hidden) {
+ app.hidden = false;
+ }
+ if (client.keeping) {
+ app.keeping = true;
+ }
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_PROVIDER_IN_USE;
+ app.adjSource = client;
+ app.adjSourceOom = clientAdj;
+ app.adjTarget = cpr.name;
+ }
+ if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ }
+ }
+ // If the provider has external (non-framework) process
+ // dependencies, ensure that its adjustment is at least
+ // FOREGROUND_APP_ADJ.
+ if (cpr.hasExternalProcessHandles()) {
+ if (adj > ProcessList.FOREGROUND_APP_ADJ) {
+ adj = ProcessList.FOREGROUND_APP_ADJ;
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.hidden = false;
+ app.keeping = true;
+ app.adjType = "provider";
+ app.adjTarget = cpr.name;
+ }
}
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a40b13c..561dd0f 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -86,6 +86,7 @@
CharSequence nonLocalizedLabel; // the label information from the package mgr.
int labelRes; // the label information from the package mgr.
int icon; // resource identifier of activity's icon.
+ int logo; // resource identifier of activity's logo.
int theme; // resource identifier of activity's theme.
int realTheme; // actual theme resource we will use, never 0.
int windowFlags; // custom window flags for preview window.
@@ -399,6 +400,7 @@
labelRes = app.labelRes;
}
icon = aInfo.getIconResource();
+ logo = aInfo.getLogoResource();
theme = aInfo.getThemeResource();
realTheme = theme;
if (realTheme == 0) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d6a6eb8..5e88d3b 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1465,8 +1465,8 @@
mWindowManager.setAppStartingWindow(
next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
- next.nonLocalizedLabel, next.labelRes, next.icon, next.windowFlags,
- null, true);
+ next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
+ next.windowFlags, null, true);
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -1500,7 +1500,7 @@
mService.compatibilityInfoForPackageLocked(
next.info.applicationInfo),
next.nonLocalizedLabel,
- next.labelRes, next.icon, next.windowFlags,
+ next.labelRes, next.icon, next.logo, next.windowFlags,
null, true);
}
if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
@@ -1639,7 +1639,7 @@
r.appToken, r.packageName, r.theme,
mService.compatibilityInfoForPackageLocked(
r.info.applicationInfo), r.nonLocalizedLabel,
- r.labelRes, r.icon, r.windowFlags,
+ r.labelRes, r.icon, r.logo, r.windowFlags,
prev != null ? prev.appToken : null, showStartingIcon);
}
} else {
@@ -3333,14 +3333,16 @@
}
}
- void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
- boolean dumpClient, String dumpPackage) {
+ boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
+ boolean dumpClient, String dumpPackage, boolean needSep) {
+ boolean printed = false;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
- pw.print(" Task "); pw.print(taskNdx); pw.print(": id #"); pw.println(task.taskId);
- ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
- " ", "Hist", true, !dumpAll, dumpClient, dumpPackage);
+ printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
+ mTaskHistory.get(taskNdx).mActivities, " ", "Hist", true, !dumpAll,
+ dumpClient, dumpPackage, needSep, " Task " + taskNdx + ": id #" + task.taskId);
}
+ return printed;
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index bddca2b..a638981 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2215,82 +2215,95 @@
return getFocusedStack().getDumpActivitiesLocked(name);
}
+ static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
+ boolean needSep, String prefix) {
+ if (activity != null) {
+ if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ pw.print(prefix);
+ pw.println(activity);
+ }
+ }
+ return needSep;
+ }
+
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage) {
- pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
- if (mGoingToSleepActivities.size() > 0) {
- pw.println(" Activities waiting to sleep:");
- dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
- dumpPackage);
- }
- if (dumpAll) {
- pw.println(" mSleepTimeout: " + mSleepTimeout);
- }
final int numStacks = mStacks.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
+ if (stackNdx != 0) {
+ pw.println();
+ }
pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
- stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
- pw.println(" ");
- pw.println(" Running activities (most recent first):");
- dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
- dumpPackage);
+ stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, false);
+ dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false,
+ dumpPackage, true, " Running activities (most recent first):");
- pw.print(" Stack #"); pw.println(mStacks.indexOf(stack));
- if (stack.mPausingActivity != null) {
- pw.println(" mPausingActivity: " + stack.mPausingActivity);
- }
- pw.println(" mResumedActivity: " + stack.mResumedActivity);
+ boolean needSep = true;
+ needSep = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+ " mPausingActivity: ");
+ needSep = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+ " mResumedActivity: ");
if (dumpAll) {
- pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity);
+ printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+ " mLastPausedActivity: ");
}
}
- if (mFinishingActivities.size() > 0) {
- pw.println(" ");
- pw.println(" Activities waiting to finish:");
- dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
- dumpPackage);
- }
+ dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll, false,
+ dumpPackage, true, " Activities waiting to finish:");
+ dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
+ dumpPackage, true, " Activities waiting to stop:");
+ dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting for another to become visible:");
+ dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
+ dumpPackage, true, " Activities waiting to sleep:");
+ dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false,
+ dumpPackage, true, " Activities waiting to sleep:");
- if (mStoppingActivities.size() > 0) {
- pw.println(" ");
- pw.println(" Activities waiting to stop:");
- dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false,
- dumpPackage);
- }
-
- if (mWaitingVisibleActivities.size() > 0) {
- pw.println(" ");
- pw.println(" Activities waiting for another to become visible:");
- dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll,
- false, dumpPackage);
- }
-
- if (dumpAll) {
- pw.println(" ");
- pw.println(" mCurTaskId: " + mCurTaskId);
+ if (dumpPackage == null) {
+ pw.println();
+ pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
+ if (dumpAll) {
+ pw.println(" mSleepTimeout: " + mSleepTimeout);
+ }
+ if (dumpAll) {
+ pw.println(" mCurTaskId: " + mCurTaskId);
+ }
}
return true;
}
- static void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
+ static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
String prefix, String label, boolean complete, boolean brief, boolean client,
- String dumpPackage) {
+ String dumpPackage, boolean needNL, String header) {
TaskRecord lastTask = null;
- boolean needNL = false;
- final String innerPrefix = prefix + " ";
- final String[] args = new String[0];
+ String innerPrefix = null;
+ String[] args = null;
+ boolean printed = false;
for (int i=list.size()-1; i>=0; i--) {
final ActivityRecord r = list.get(i);
if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
continue;
}
+ if (innerPrefix == null) {
+ innerPrefix = prefix + " ";
+ args = new String[0];
+ }
+ printed = true;
final boolean full = !brief && (complete || !r.isInHistory());
if (needNL) {
- pw.println(" ");
+ pw.println("");
needNL = false;
}
+ if (header != null) {
+ pw.println(header);
+ header = null;
+ }
if (lastTask != r.task) {
lastTask = r.task;
pw.print(prefix);
@@ -2341,6 +2354,7 @@
needNL = true;
}
}
+ return printed;
}
void scheduleIdleTimeoutLocked(ActivityRecord next) {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 7929f96..3a4a34c 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -32,12 +32,12 @@
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
/**
@@ -129,8 +129,8 @@
// all IIntentReceivers that are registered from this process.
final HashSet<ReceiverList> receivers = new HashSet<ReceiverList>();
// class (String) -> ContentProviderRecord
- final HashMap<String, ContentProviderRecord> pubProviders
- = new HashMap<String, ContentProviderRecord>();
+ final ArrayMap<String, ContentProviderRecord> pubProviders
+ = new ArrayMap<String, ContentProviderRecord>();
// All ContentProviderRecord process is using
final ArrayList<ContentProviderConnection> conProviders
= new ArrayList<ContentProviderConnection>();
@@ -302,9 +302,9 @@
}
if (pubProviders.size() > 0) {
pw.print(prefix); pw.println("Published Providers:");
- for (HashMap.Entry<String, ContentProviderRecord> ent : pubProviders.entrySet()) {
- pw.print(prefix); pw.print(" - "); pw.println(ent.getKey());
- pw.print(prefix); pw.print(" -> "); pw.println(ent.getValue());
+ for (int i=0; i<pubProviders.size(); i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(pubProviders.keyAt(i));
+ pw.print(prefix); pw.print(" -> "); pw.println(pubProviders.valueAt(i));
}
}
if (conProviders.size() > 0) {
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 9dbf5f5..3249e1e 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -230,58 +230,88 @@
return didSomething;
}
- private void dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll,
- HashMap<ComponentName, ContentProviderRecord> map) {
+ private boolean dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll, String dumpPackage,
+ String header, boolean needSep, HashMap<ComponentName, ContentProviderRecord> map) {
Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
+ boolean written = false;
while (it.hasNext()) {
Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
ContentProviderRecord r = e.getValue();
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (needSep) {
+ pw.println("");
+ needSep = false;
+ }
+ if (header != null) {
+ pw.println(header);
+ header = null;
+ }
+ written = true;
pw.print(" * ");
pw.println(r);
r.dump(pw, " ", dumpAll);
}
+ return written;
}
- private void dumpProvidersByNameLocked(PrintWriter pw,
- HashMap<String, ContentProviderRecord> map) {
+ private boolean dumpProvidersByNameLocked(PrintWriter pw, String dumpPackage,
+ String header, boolean needSep, HashMap<String, ContentProviderRecord> map) {
Iterator<Map.Entry<String, ContentProviderRecord>> it = map.entrySet().iterator();
+ boolean written = false;
while (it.hasNext()) {
Map.Entry<String, ContentProviderRecord> e = it.next();
ContentProviderRecord r = e.getValue();
+ if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
+ continue;
+ }
+ if (needSep) {
+ pw.println("");
+ needSep = false;
+ }
+ if (header != null) {
+ pw.println(header);
+ header = null;
+ }
+ written = true;
pw.print(" ");
pw.print(e.getKey());
pw.print(": ");
pw.println(r.toShortString());
}
+ return written;
}
- void dumpProvidersLocked(PrintWriter pw, boolean dumpAll) {
+ boolean dumpProvidersLocked(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+ boolean needSep = false;
+
if (mSingletonByClass.size() > 0) {
pw.println(" Published single-user content providers (by class):");
- dumpProvidersByClassLocked(pw, dumpAll, mSingletonByClass);
+ needSep = dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+ " Published single-user content providers (by class):", needSep,
+ mSingletonByClass);
}
- pw.println("");
for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
- pw.println("");
- pw.println(" Published user " + mProvidersByClassPerUser.keyAt(i)
- + " content providers (by class):");
- dumpProvidersByClassLocked(pw, dumpAll, map);
+ needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
+ " Published user " + mProvidersByClassPerUser.keyAt(i)
+ + " content providers (by class):", needSep, map);
}
if (dumpAll) {
- pw.println("");
- pw.println(" Single-user authority to provider mappings:");
- dumpProvidersByNameLocked(pw, mSingletonByName);
+ needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
+ " Single-user authority to provider mappings:", needSep, mSingletonByName);
for (int i = 0; i < mProvidersByNamePerUser.size(); i++) {
- pw.println("");
- pw.println(" User " + mProvidersByNamePerUser.keyAt(i)
- + " authority to provider mappings:");
- dumpProvidersByNameLocked(pw, mProvidersByNamePerUser.valueAt(i));
+ needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
+ " User " + mProvidersByNamePerUser.keyAt(i)
+ + " authority to provider mappings:", needSep,
+ mProvidersByNamePerUser.valueAt(i));
}
}
+ return needSep;
}
protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 9fdd293..707e8ee 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -16,34 +16,32 @@
package com.android.server.am;
-import android.app.PendingIntent;
-import android.net.Uri;
-import android.provider.Settings;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.NotificationManagerService;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArrayMap;
import android.util.Slog;
import android.util.TimeUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
/**
@@ -76,11 +74,11 @@
final boolean exported; // from ServiceInfo.exported
final Runnable restarter; // used to schedule retries of starting the service
final long createTime; // when this service was created
- final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
- = new HashMap<Intent.FilterComparison, IntentBindRecord>();
+ final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
+ = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
// All active bindings to the service.
- final HashMap<IBinder, ArrayList<ConnectionRecord>> connections
- = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
+ final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
+ = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
// IBinder -> ConnectionRecord of all bound clients
ProcessRecord app; // where this service is running or null.
@@ -258,10 +256,9 @@
dumpStartList(pw, prefix, pendingStarts, 0);
}
if (bindings.size() > 0) {
- Iterator<IntentBindRecord> it = bindings.values().iterator();
pw.print(prefix); pw.println("Bindings:");
- while (it.hasNext()) {
- IntentBindRecord b = it.next();
+ for (int i=0; i<bindings.size(); i++) {
+ IntentBindRecord b = bindings.valueAt(i);
pw.print(prefix); pw.print("* IntentBindRecord{");
pw.print(Integer.toHexString(System.identityHashCode(b)));
if ((b.collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
@@ -273,9 +270,8 @@
}
if (connections.size() > 0) {
pw.print(prefix); pw.println("All Connections:");
- Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator();
- while (it.hasNext()) {
- ArrayList<ConnectionRecord> c = it.next();
+ for (int conni=0; conni<connections.size(); conni++) {
+ ArrayList<ConnectionRecord> c = connections.valueAt(conni);
for (int i=0; i<c.size(); i++) {
pw.print(prefix); pw.print(" "); pw.println(c.get(i));
}
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/java/com/android/server/wifi/WifiController.java
index 228fabf..87b4394 100644
--- a/services/java/com/android/server/wifi/WifiController.java
+++ b/services/java/com/android/server/wifi/WifiController.java
@@ -150,7 +150,11 @@
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
- setInitialState(mApStaDisabledState);
+ if (mSettingsStore.isScanAlwaysAvailable()) {
+ setInitialState(mStaDisabledWithScanState);
+ } else {
+ setInitialState(mApStaDisabledState);
+ }
setLogRecSize(100);
setLogOnlyTransitions(false);
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 8ddc776..66ef978 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -651,7 +651,12 @@
Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
" with persist set to " + persist);
enforceChangePermission();
- mWifiStateMachine.setCountryCode(countryCode, persist);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mWifiStateMachine.setCountryCode(countryCode, persist);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
/**
@@ -668,7 +673,12 @@
if (!isDualBandSupported()) return;
Slog.i(TAG, "WifiService trying to set frequency band to " + band +
" with persist set to " + persist);
- mWifiStateMachine.setFrequencyBand(band, persist);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mWifiStateMachine.setFrequencyBand(band, persist);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
diff --git a/services/java/com/android/server/wm/StartingData.java b/services/java/com/android/server/wm/StartingData.java
index 46bb480..7115b0f 100644
--- a/services/java/com/android/server/wm/StartingData.java
+++ b/services/java/com/android/server/wm/StartingData.java
@@ -25,17 +25,19 @@
final CharSequence nonLocalizedLabel;
final int labelRes;
final int icon;
+ final int logo;
final int windowFlags;
StartingData(String _pkg, int _theme, CompatibilityInfo _compatInfo,
CharSequence _nonLocalizedLabel,
- int _labelRes, int _icon, int _windowFlags) {
+ int _labelRes, int _icon, int _logo, int _windowFlags) {
pkg = _pkg;
theme = _theme;
compatInfo = _compatInfo;
nonLocalizedLabel = _nonLocalizedLabel;
labelRes = _labelRes;
icon = _icon;
+ logo = _logo;
windowFlags = _windowFlags;
}
}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a1e07dc..b4dcdec 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3878,7 +3878,7 @@
@Override
public void setAppStartingWindow(IBinder token, String pkg,
int theme, CompatibilityInfo compatInfo,
- CharSequence nonLocalizedLabel, int labelRes, int icon,
+ CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppStartingWindow()")) {
@@ -4079,7 +4079,7 @@
if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
mStartingIconInTransition = true;
wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
- labelRes, icon, windowFlags);
+ labelRes, icon, logo, windowFlags);
Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
// Note: we really want to do sendMessageAtFrontOfQueue() because we
// want to process the message ASAP, before any other queued
@@ -7083,7 +7083,7 @@
try {
view = mPolicy.addStartingWindow(
wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
- sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags);
+ sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
} catch (Exception e) {
Slog.w(TAG, "Exception when adding starting window", e);
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 8b85d8c..3ae2106 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -152,6 +152,11 @@
String number = null;
Uri uri = intent.getData();
+
+ if (uri == null) {
+ return null;
+ }
+
String scheme = uri.getScheme();
if (scheme.equals("tel") || scheme.equals("sip")) {
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
index 668f61d..3681784 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
@@ -49,8 +49,8 @@
float4 diff = idealPixel - givenPixel;
float totalDiff = diff.x + diff.y + diff.z + diff.w;
if (totalDiff < 0) {
- v_out[0] = rsPackColorTo8888(0, 0, clamp(-totalDiff/2, 0, 1));
+ v_out[0] = rsPackColorTo8888(0, 0, clamp(-totalDiff/2.f, 0.f, 1.f));
} else {
- v_out[0] = rsPackColorTo8888(clamp(totalDiff/2, 0, 1), 0, 0);
+ v_out[0] = rsPackColorTo8888(clamp(totalDiff/2.f, 0.f, 1.f), 0, 0);
}
}
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 10baac5..53318a4 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -164,7 +164,7 @@
}
try {
- mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, null, false);
+ mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, 0, null, false);
fail("IWindowManager.setAppStartingWindow did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 0ca230c..a7b48bb 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -304,7 +304,7 @@
@Override
public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
- CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+ CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10)
throws RemoteException {
// TODO Auto-generated method stub
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d53c320..9f3a0d3 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -347,6 +347,8 @@
public static final int CMD_DISABLE_P2P_REQ = BASE + 132;
public static final int CMD_DISABLE_P2P_RSP = BASE + 133;
+ public static final int CMD_BOOT_COMPLETED = BASE + 134;
+
public static final int CONNECT_MODE = 1;
public static final int SCAN_ONLY_MODE = 2;
public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3;
@@ -410,6 +412,10 @@
private int mDelayedStopCounter;
private boolean mInDelayedStop = false;
+ // sometimes telephony gives us this data before boot is complete and we can't store it
+ // until after, so the write is deferred
+ private volatile String mPersistedCountryCode;
+
private static final int MIN_RSSI = -200;
private static final int MAX_RSSI = 256;
@@ -637,6 +643,15 @@
}
});
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ sendMessage(CMD_BOOT_COMPLETED);
+ }
+ },
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+
mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
@@ -1004,6 +1019,7 @@
*/
public void setCountryCode(String countryCode, boolean persist) {
if (persist) {
+ mPersistedCountryCode = countryCode;
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.WIFI_COUNTRY_CODE,
countryCode);
@@ -1889,6 +1905,19 @@
setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
}
break;
+ case CMD_BOOT_COMPLETED:
+ String countryCode = mPersistedCountryCode;
+ if (TextUtils.isEmpty(countryCode) == false) {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.WIFI_COUNTRY_CODE,
+ countryCode);
+ // it may be that the state transition that should send this info
+ // to the driver happened between mPersistedCountryCode getting set
+ // and now, so simply persisting it here would mean we have sent
+ // nothing to the driver. Send the cmd so it might be set now.
+ sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
+ }
+ break;
/* Discard */
case CMD_START_SUPPLICANT:
case CMD_STOP_SUPPLICANT:
@@ -2359,7 +2388,6 @@
mInDelayedStop = false;
mDelayedStopCounter++;
updateBatteryWorkSource(null);
-
/**
* Enable bluetooth coexistence scan mode when bluetooth connection is active.
* When this mode is on, some of the low-level scan parameters used by the